Merge tag 'for-linus-20190516' of git://git.kernel.dk/linux-block
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 May 2019 02:10:37 +0000 (19:10 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 May 2019 02:10:37 +0000 (19:10 -0700)
Pull io_uring fixes from Jens Axboe:
 "A small set of fixes for io_uring.

  This contains:

   - smp_rmb() cleanup for io_cqring_events() (Jackie)

   - io_cqring_wait() simplification (Jackie)

   - removal of dead 'ev_flags' passing (me)

   - SQ poll CPU affinity verification fix (me)

   - SQ poll wait fix (Roman)

   - SQE command prep cleanup and fix (Stefan)"

* tag 'for-linus-20190516' of git://git.kernel.dk/linux-block:
  io_uring: use wait_event_interruptible for cq_wait conditional wait
  io_uring: adjust smp_rmb inside io_cqring_events
  io_uring: fix infinite wait in khread_park() on io_finish_async()
  io_uring: remove 'ev_flags' argument
  io_uring: fix failure to verify SQ_AFF cpu
  io_uring: fix race condition reading SQE data

2169 files changed:
Documentation/ABI/testing/sysfs-class-power
Documentation/ABI/testing/sysfs-devices-system-cpu
Documentation/accounting/psi.txt
Documentation/admin-guide/hw-vuln/index.rst [new file with mode: 0644]
Documentation/admin-guide/hw-vuln/l1tf.rst [new file with mode: 0644]
Documentation/admin-guide/hw-vuln/mds.rst [new file with mode: 0644]
Documentation/admin-guide/index.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/l1tf.rst [deleted file]
Documentation/core-api/kernel-api.rst
Documentation/dev-tools/gcov.rst
Documentation/device-mapper/dm-dust.txt [new file with mode: 0644]
Documentation/device-mapper/dm-integrity.txt
Documentation/devicetree/bindings/arm/altera/socfpga-system.txt
Documentation/devicetree/bindings/arm/amlogic.txt
Documentation/devicetree/bindings/arm/atmel-sysregs.txt
Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
Documentation/devicetree/bindings/arm/fsl.yaml
Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/arm/omap/omap.txt
Documentation/devicetree/bindings/arm/rockchip.yaml
Documentation/devicetree/bindings/arm/stm32/stm32-syscon.txt
Documentation/devicetree/bindings/arm/sunxi.txt [deleted file]
Documentation/devicetree/bindings/arm/sunxi.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/bus/ti-sysc.txt
Documentation/devicetree/bindings/clock/xlnx,zynqmp-clk.txt [new file with mode: 0644]
Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpu/arm,mali-midgard.txt
Documentation/devicetree/bindings/hwmon/pwm-fan.txt
Documentation/devicetree/bindings/iio/adc/imx7d-adc.txt
Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.txt
Documentation/devicetree/bindings/input/gpio-vibrator.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/input/lpc32xx-key.txt
Documentation/devicetree/bindings/input/max77650-onkey.txt [new file with mode: 0644]
Documentation/devicetree/bindings/input/microchip,qt1050.txt [new file with mode: 0644]
Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt
Documentation/devicetree/bindings/input/touchscreen/goodix.txt
Documentation/devicetree/bindings/input/touchscreen/iqs5xx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
Documentation/devicetree/bindings/leds/backlight/lm3630a-backlight.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/leds/leds-max77650.txt [new file with mode: 0644]
Documentation/devicetree/bindings/memory-controllers/fsl/mmdc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt
Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt
Documentation/devicetree/bindings/mfd/max77620.txt
Documentation/devicetree/bindings/mfd/max77650.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/stmfx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/ti-lmu.txt
Documentation/devicetree/bindings/misc/intel,ixp4xx-queue-manager.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
Documentation/devicetree/bindings/net/keystone-netcp.txt
Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt
Documentation/devicetree/bindings/pci/designware-pcie.txt
Documentation/devicetree/bindings/pci/pci-keystone.txt
Documentation/devicetree/bindings/pci/pci.txt
Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/amlogic,meson-gx-pwrc.txt
Documentation/devicetree/bindings/power/reset/syscon-reboot.txt
Documentation/devicetree/bindings/power/supply/axp20x_usb_power.txt
Documentation/devicetree/bindings/power/supply/gpio-charger.txt
Documentation/devicetree/bindings/power/supply/ingenic,battery.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/supply/lt3651-charger.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/supply/ltc3651-charger.txt [deleted file]
Documentation/devicetree/bindings/power/supply/max77650-charger.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/supply/olpc_battery.txt
Documentation/devicetree/bindings/pps/pps-gpio.txt
Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt
Documentation/devicetree/bindings/serial/mtk-uart.txt
Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt [new file with mode: 0644]
Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt
Documentation/devicetree/bindings/thermal/qcom-tsens.txt
Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt
Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/timer/mediatek,mtk-timer.txt
Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
Documentation/devicetree/bindings/vendor-prefixes.txt [deleted file]
Documentation/devicetree/bindings/vendor-prefixes.yaml [new file with mode: 0644]
Documentation/filesystems/autofs-mount-control.txt
Documentation/filesystems/autofs.txt
Documentation/firmware-guide/acpi/dsd/data-node-references.rst
Documentation/firmware-guide/acpi/dsd/graph.rst
Documentation/index.rst
Documentation/media/uapi/v4l/field-order.rst
Documentation/networking/rxrpc.txt
Documentation/sysctl/vm.txt
Documentation/trace/ftrace.rst
Documentation/trace/histogram.rst
Documentation/trace/postprocess/trace-vmscan-postprocess.pl
Documentation/vm/hmm.rst
Documentation/x86/conf.py [new file with mode: 0644]
Documentation/x86/index.rst
Documentation/x86/mds.rst [new file with mode: 0644]
Documentation/xilinx/eemi.txt
MAINTAINERS
arch/Kconfig
arch/alpha/include/asm/segment.h [deleted file]
arch/alpha/kernel/smc37c669.c
arch/alpha/kernel/smc37c93x.c
arch/alpha/mm/init.c
arch/arc/include/asm/uaccess.h
arch/arc/mm/init.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am335x-baltos-ir2110.dts
arch/arm/boot/dts/am335x-baltos-ir3220.dts
arch/arm/boot/dts/am335x-baltos-ir5221.dts
arch/arm/boot/dts/am335x-baltos-leds.dtsi
arch/arm/boot/dts/am335x-baltos.dtsi
arch/arm/boot/dts/am335x-base0033.dts
arch/arm/boot/dts/am335x-bone-common.dtsi
arch/arm/boot/dts/am335x-boneblack-common.dtsi
arch/arm/boot/dts/am335x-boneblack-wireless.dts
arch/arm/boot/dts/am335x-boneblue.dts
arch/arm/boot/dts/am335x-bonegreen-common.dtsi
arch/arm/boot/dts/am335x-bonegreen-wireless.dts
arch/arm/boot/dts/am335x-chiliboard.dts
arch/arm/boot/dts/am335x-chilisom.dtsi
arch/arm/boot/dts/am335x-cm-t335.dts
arch/arm/boot/dts/am335x-evm.dts
arch/arm/boot/dts/am335x-evmsk.dts
arch/arm/boot/dts/am335x-icev2.dts
arch/arm/boot/dts/am335x-igep0033.dtsi
arch/arm/boot/dts/am335x-lxm.dts
arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi
arch/arm/boot/dts/am335x-moxa-uc-2101.dts
arch/arm/boot/dts/am335x-moxa-uc-8100-me-t.dts
arch/arm/boot/dts/am335x-nano.dts
arch/arm/boot/dts/am335x-osd3358-sm-red.dts
arch/arm/boot/dts/am335x-osd335x-common.dtsi
arch/arm/boot/dts/am335x-pcm-953.dtsi
arch/arm/boot/dts/am335x-pdu001.dts
arch/arm/boot/dts/am335x-pepper.dts
arch/arm/boot/dts/am335x-phycore-som.dtsi
arch/arm/boot/dts/am335x-pocketbeagle.dts
arch/arm/boot/dts/am335x-sancloud-bbe.dts
arch/arm/boot/dts/am335x-sbc-t335.dts
arch/arm/boot/dts/am335x-shc.dts
arch/arm/boot/dts/am335x-sl50.dts
arch/arm/boot/dts/am335x-wega.dtsi
arch/arm/boot/dts/am43x-epos-evm.dts
arch/arm/boot/dts/am5718.dtsi [new file with mode: 0644]
arch/arm/boot/dts/am571x-idk.dts
arch/arm/boot/dts/am5728.dtsi [new file with mode: 0644]
arch/arm/boot/dts/am572x-idk.dts
arch/arm/boot/dts/am5748.dtsi [new file with mode: 0644]
arch/arm/boot/dts/am574x-idk.dts
arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
arch/arm/boot/dts/am57xx-cl-som-am57x.dts
arch/arm/boot/dts/armada-38x.dtsi
arch/arm/boot/dts/aspeed-ast2500-evb.dts
arch/arm/boot/dts/aspeed-bmc-facebook-cmm.dts
arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts
arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts
arch/arm/boot/dts/aspeed-g4.dtsi
arch/arm/boot/dts/aspeed-g5.dtsi
arch/arm/boot/dts/at91-sama5d27_som1.dtsi
arch/arm/boot/dts/at91-sama5d27_som1_ek.dts
arch/arm/boot/dts/at91-sama5d2_xplained.dts
arch/arm/boot/dts/at91-sama5d4_xplained.dts
arch/arm/boot/dts/at91-sama5d4ek.dts
arch/arm/boot/dts/at91-vinco.dts
arch/arm/boot/dts/at91sam9260ek.dts
arch/arm/boot/dts/at91sam9xe.dtsi
arch/arm/boot/dts/axp81x.dtsi
arch/arm/boot/dts/dra7-l4.dtsi
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/emev2-kzm9d.dts
arch/arm/boot/dts/exynos3250.dtsi
arch/arm/boot/dts/exynos4.dtsi
arch/arm/boot/dts/exynos4210-origen.dts
arch/arm/boot/dts/exynos4210-smdkv310.dts
arch/arm/boot/dts/exynos4210-trats.dts
arch/arm/boot/dts/exynos4210-universal_c210.dts
arch/arm/boot/dts/exynos4412-odroidu3.dts
arch/arm/boot/dts/exynos4412-origen.dts
arch/arm/boot/dts/exynos4412-smdk4412.dts
arch/arm/boot/dts/exynos4412-trats2.dts
arch/arm/boot/dts/exynos4412.dtsi
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/exynos5260-pinctrl.dtsi
arch/arm/boot/dts/exynos5260-xyref5260.dts
arch/arm/boot/dts/exynos5260.dtsi
arch/arm/boot/dts/exynos5410-odroidxu.dts
arch/arm/boot/dts/exynos5410-smdk5410.dts
arch/arm/boot/dts/exynos5420-arndale-octa.dts
arch/arm/boot/dts/exynos5420-smdk5420.dts
arch/arm/boot/dts/exynos5420.dtsi
arch/arm/boot/dts/exynos5422-odroidxu3-audio.dtsi
arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
arch/arm/boot/dts/exynos54xx.dtsi
arch/arm/boot/dts/gemini-dlink-dir-685.dts
arch/arm/boot/dts/imx35.dtsi
arch/arm/boot/dts/imx50-kobo-aura.dts [new file with mode: 0644]
arch/arm/boot/dts/imx50.dtsi
arch/arm/boot/dts/imx51-zii-rdu1.dts
arch/arm/boot/dts/imx51.dtsi
arch/arm/boot/dts/imx53-m53.dtsi
arch/arm/boot/dts/imx53-m53menlo.dts [new file with mode: 0644]
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/imx6-logicpd-baseboard.dtsi
arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6dl-riotboard.dts
arch/arm/boot/dts/imx6dl-sabreauto.dts
arch/arm/boot/dts/imx6q-ba16.dtsi
arch/arm/boot/dts/imx6q-gw54xx.dts
arch/arm/boot/dts/imx6q-logicpd.dts
arch/arm/boot/dts/imx6q-marsboard.dts
arch/arm/boot/dts/imx6q-tbs2910.dts
arch/arm/boot/dts/imx6q-zii-rdu2.dts
arch/arm/boot/dts/imx6qdl-apf6.dtsi
arch/arm/boot/dts/imx6qdl-emcon.dtsi
arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
arch/arm/boot/dts/imx6qdl-gw551x.dtsi
arch/arm/boot/dts/imx6qdl-gw5903.dtsi
arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
arch/arm/boot/dts/imx6qdl-sabresd.dtsi
arch/arm/boot/dts/imx6qdl-sr-som.dtsi
arch/arm/boot/dts/imx6qdl-var-dart.dtsi
arch/arm/boot/dts/imx6qdl-wandboard.dtsi
arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/imx6qp-zii-rdu2.dts
arch/arm/boot/dts/imx6sl.dtsi
arch/arm/boot/dts/imx6sll.dtsi
arch/arm/boot/dts/imx6sx-sabreauto.dts
arch/arm/boot/dts/imx6sx-sdb.dtsi
arch/arm/boot/dts/imx6sx.dtsi
arch/arm/boot/dts/imx6ul.dtsi
arch/arm/boot/dts/imx7-mba7.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx7-tqma7.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx7d-mba7.dts [new file with mode: 0644]
arch/arm/boot/dts/imx7d-pico.dtsi
arch/arm/boot/dts/imx7d-tqma7.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx7d-zii-rpu2.dts [new file with mode: 0644]
arch/arm/boot/dts/imx7d.dtsi
arch/arm/boot/dts/imx7s-mba7.dts [new file with mode: 0644]
arch/arm/boot/dts/imx7s-tqma7.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx7s-warp.dts
arch/arm/boot/dts/imx7s.dtsi
arch/arm/boot/dts/imx7ulp.dtsi
arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts [new file with mode: 0644]
arch/arm/boot/dts/intel-ixp42x.dtsi [new file with mode: 0644]
arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358.dts [new file with mode: 0644]
arch/arm/boot/dts/intel-ixp43x.dtsi [new file with mode: 0644]
arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi [new file with mode: 0644]
arch/arm/boot/dts/intel-ixp4xx.dtsi [new file with mode: 0644]
arch/arm/boot/dts/lpc3250-ea3250.dts
arch/arm/boot/dts/lpc3250-phy3250.dts
arch/arm/boot/dts/lpc32xx.dtsi
arch/arm/boot/dts/ls1021a-moxa-uc-8410a.dts
arch/arm/boot/dts/ls1021a-qds.dts
arch/arm/boot/dts/ls1021a-twr.dts
arch/arm/boot/dts/ls1021a.dtsi
arch/arm/boot/dts/meson.dtsi
arch/arm/boot/dts/meson8.dtsi
arch/arm/boot/dts/meson8b-ec100.dts
arch/arm/boot/dts/meson8b-odroidc1.dts
arch/arm/boot/dts/meson8b.dtsi
arch/arm/boot/dts/omap2420-n810.dts
arch/arm/boot/dts/omap4-duovero.dtsi
arch/arm/boot/dts/omap4-l4-abe.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap4-mcpdm.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap4-panda-common.dtsi
arch/arm/boot/dts/omap4-sdp.dts
arch/arm/boot/dts/omap4-var-som-om44.dtsi
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/omap5-board-common.dtsi
arch/arm/boot/dts/omap5-l4-abe.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/qcom-apq8064.dtsi
arch/arm/boot/dts/qcom-ipq4019.dtsi
arch/arm/boot/dts/qcom-mdm9615.dtsi
arch/arm/boot/dts/qcom-msm8660.dtsi
arch/arm/boot/dts/qcom-pma8084.dtsi
arch/arm/boot/dts/r7s72100-rskrza1.dts
arch/arm/boot/dts/r8a73a4-ape6evm.dts
arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts
arch/arm/boot/dts/r8a77470.dtsi
arch/arm/boot/dts/r8a7778-bockw.dts
arch/arm/boot/dts/r8a7779-marzen.dts
arch/arm/boot/dts/r8a7792-blanche.dts
arch/arm/boot/dts/r8a7792.dtsi
arch/arm/boot/dts/r8a7794-alt.dts
arch/arm/boot/dts/rk3036-kylin.dts
arch/arm/boot/dts/rk3036.dtsi
arch/arm/boot/dts/rk3066a-marsboard.dts
arch/arm/boot/dts/rk3066a-mk808.dts
arch/arm/boot/dts/rk3066a-rayeager.dts
arch/arm/boot/dts/rk3066a.dtsi
arch/arm/boot/dts/rk3188-px3-evb.dts
arch/arm/boot/dts/rk3188-radxarock.dts
arch/arm/boot/dts/rk3188.dtsi
arch/arm/boot/dts/rk322x.dtsi
arch/arm/boot/dts/rk3288-evb-act8846.dts
arch/arm/boot/dts/rk3288-evb.dtsi
arch/arm/boot/dts/rk3288-fennec.dts
arch/arm/boot/dts/rk3288-firefly-beta.dts
arch/arm/boot/dts/rk3288-firefly-reload-core.dtsi
arch/arm/boot/dts/rk3288-firefly-reload.dts
arch/arm/boot/dts/rk3288-firefly.dts
arch/arm/boot/dts/rk3288-firefly.dtsi
arch/arm/boot/dts/rk3288-miqi.dts
arch/arm/boot/dts/rk3288-phycore-rdk.dts
arch/arm/boot/dts/rk3288-phycore-som.dtsi
arch/arm/boot/dts/rk3288-r89.dts
arch/arm/boot/dts/rk3288-rock2-som.dtsi
arch/arm/boot/dts/rk3288-rock2-square.dts
arch/arm/boot/dts/rk3288-tinker-s.dts
arch/arm/boot/dts/rk3288-tinker.dtsi
arch/arm/boot/dts/rk3288-veyron-analog-audio.dtsi
arch/arm/boot/dts/rk3288-veyron-brain.dts
arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi
arch/arm/boot/dts/rk3288-veyron-jaq.dts
arch/arm/boot/dts/rk3288-veyron-jerry.dts
arch/arm/boot/dts/rk3288-veyron-mickey.dts
arch/arm/boot/dts/rk3288-veyron-mighty.dts [new file with mode: 0644]
arch/arm/boot/dts/rk3288-veyron-minnie.dts
arch/arm/boot/dts/rk3288-veyron-pinky.dts
arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi
arch/arm/boot/dts/rk3288-veyron-speedy.dts
arch/arm/boot/dts/rk3288-veyron.dtsi
arch/arm/boot/dts/rk3288-vyasa.dts
arch/arm/boot/dts/rk3288.dtsi
arch/arm/boot/dts/rv1108-elgin-r1.dts
arch/arm/boot/dts/rv1108.dtsi
arch/arm/boot/dts/s5pv210-goni.dts
arch/arm/boot/dts/s5pv210.dtsi
arch/arm/boot/dts/sama5d2.dtsi
arch/arm/boot/dts/sama5d36ek_cmp.dts
arch/arm/boot/dts/sama5d3xcm_cmp.dtsi
arch/arm/boot/dts/sama5d3xmb_cmp.dtsi
arch/arm/boot/dts/sama5d4.dtsi
arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts
arch/arm/boot/dts/ste-dbx5x0.dtsi
arch/arm/boot/dts/ste-href-stuib.dtsi
arch/arm/boot/dts/ste-href-tvk1281618.dtsi
arch/arm/boot/dts/stm32f429.dtsi
arch/arm/boot/dts/stm32f769-disco.dts
arch/arm/boot/dts/stm32h743-pinctrl.dtsi
arch/arm/boot/dts/stm32h743.dtsi
arch/arm/boot/dts/stm32h743i-disco.dts
arch/arm/boot/dts/stm32h743i-eval.dts
arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
arch/arm/boot/dts/stm32mp157a-dk1.dts [new file with mode: 0644]
arch/arm/boot/dts/stm32mp157c-dk2.dts [new file with mode: 0644]
arch/arm/boot/dts/stm32mp157c-ed1.dts
arch/arm/boot/dts/stm32mp157c.dtsi
arch/arm/boot/dts/sun4i-a10-chuwi-v7-cw0825.dts
arch/arm/boot/dts/sun4i-a10-cubieboard.dts
arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts
arch/arm/boot/dts/sun4i-a10-hyundai-a7hd.dts
arch/arm/boot/dts/sun4i-a10-inet1.dts
arch/arm/boot/dts/sun4i-a10-inet97fv2.dts
arch/arm/boot/dts/sun4i-a10-inet9f-rev03.dts
arch/arm/boot/dts/sun4i-a10-marsboard.dts
arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
arch/arm/boot/dts/sun4i-a10-pcduino.dts
arch/arm/boot/dts/sun4i-a10-pov-protab2-ips9.dts
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts
arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
arch/arm/boot/dts/sun5i-a13-empire-electronix-d709.dts
arch/arm/boot/dts/sun5i-a13-hsg-h702.dts
arch/arm/boot/dts/sun5i-a13-licheepi-one.dts
arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
arch/arm/boot/dts/sun5i-a13-olinuxino.dts
arch/arm/boot/dts/sun5i-a13-q8-tablet.dts
arch/arm/boot/dts/sun5i-a13-utoo-p66.dts
arch/arm/boot/dts/sun5i-gr8-chip-pro.dts
arch/arm/boot/dts/sun5i-gr8-evb.dts
arch/arm/boot/dts/sun5i-r8-chip.dts
arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi
arch/arm/boot/dts/sun5i.dtsi
arch/arm/boot/dts/sun6i-a31-colombus.dts
arch/arm/boot/dts/sun6i-a31-hummingbird.dts
arch/arm/boot/dts/sun6i-a31-i7.dts
arch/arm/boot/dts/sun6i-a31.dtsi
arch/arm/boot/dts/sun6i-a31s-primo81.dts
arch/arm/boot/dts/sun6i-reference-design-tablet.dtsi
arch/arm/boot/dts/sun7i-a20-bananapi.dts
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts
arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts
arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts
arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts
arch/arm/boot/dts/sun7i-a20-orangepi.dts
arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts
arch/arm/boot/dts/sun7i-a20-pcduino3.dts
arch/arm/boot/dts/sun7i-a20-wexler-tab7200.dts
arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/boot/dts/sun8i-a23-a33.dtsi
arch/arm/boot/dts/sun8i-a23-q8-tablet.dts
arch/arm/boot/dts/sun8i-a33-q8-tablet.dts
arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts
arch/arm/boot/dts/sun8i-a33.dtsi
arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts
arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts
arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
arch/arm/boot/dts/sun8i-a83t.dtsi
arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
arch/arm/boot/dts/sun8i-h3-mapleboard-mp130.dts
arch/arm/boot/dts/sun8i-h3-nanopi-m1-plus.dts
arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
arch/arm/boot/dts/sun8i-h3-nanopi-neo-air.dts
arch/arm/boot/dts/sun8i-h3-nanopi.dtsi
arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
arch/arm/boot/dts/sun8i-h3-orangepi-zero-plus2.dts
arch/arm/boot/dts/sun8i-h3-rervision-dvk.dts [new file with mode: 0644]
arch/arm/boot/dts/sun8i-h3.dtsi
arch/arm/boot/dts/sun8i-q8-common.dtsi
arch/arm/boot/dts/sun8i-r16-nintendo-nes-classic.dts
arch/arm/boot/dts/sun8i-r16-parrot.dts
arch/arm/boot/dts/sun8i-r40.dtsi
arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi
arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
arch/arm/boot/dts/sun8i-v3s.dtsi
arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts
arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
arch/arm/boot/dts/sun9i-a80-optimus.dts
arch/arm/boot/dts/sun9i-a80.dtsi
arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi
arch/arm/boot/dts/sunxi-h3-h5.dtsi
arch/arm/boot/dts/sunxi-libretech-all-h3-cc.dtsi
arch/arm/boot/dts/tegra124-apalis-emc.dtsi
arch/arm/boot/dts/tegra124-apalis-eval.dts
arch/arm/boot/dts/tegra124-apalis-v1.2-eval.dts
arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi
arch/arm/boot/dts/tegra124-apalis.dtsi
arch/arm/boot/dts/tegra124-jetson-tk1.dts
arch/arm/boot/dts/tegra124-nyan.dtsi
arch/arm/boot/dts/tegra124-venice2.dts
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/vf610-zii-cfu1.dts
arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
arch/arm/boot/dts/vf610-zii-dev-rev-c.dts
arch/arm/boot/dts/vf610-zii-dev.dtsi
arch/arm/boot/dts/vf610-zii-scu4-aib.dts
arch/arm/boot/dts/vf610-zii-spb4.dts [new file with mode: 0644]
arch/arm/boot/dts/vf610-zii-ssmb-dtu.dts
arch/arm/boot/dts/vf610-zii-ssmb-spu3.dts
arch/arm/common/sa1111.c
arch/arm/configs/exynos_defconfig
arch/arm/configs/mini2440_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/pxa_defconfig
arch/arm/configs/qcom_defconfig
arch/arm/configs/shmobile_defconfig
arch/arm/configs/socfpga_defconfig
arch/arm/configs/tegra_defconfig
arch/arm/firmware/Kconfig [deleted file]
arch/arm/firmware/Makefile [deleted file]
arch/arm/firmware/trusted_foundations.c [deleted file]
arch/arm/include/asm/Kbuild
arch/arm/include/asm/domain.h
arch/arm/include/asm/firmware.h
arch/arm/include/asm/futex.h
arch/arm/include/asm/hardirq.h
arch/arm/include/asm/limits.h [deleted file]
arch/arm/include/asm/processor.h
arch/arm/include/asm/trusted_foundations.h [deleted file]
arch/arm/include/asm/uaccess.h
arch/arm/kernel/atags.h
arch/arm/kernel/smp.c
arch/arm/mach-davinci/board-da830-evm.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm355-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-omapl138-hawk.c
arch/arm/mach-davinci/da830.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm365.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/dm646x.c
arch/arm/mach-dove/common.c
arch/arm/mach-ep93xx/adssphere.c
arch/arm/mach-ep93xx/clock.c
arch/arm/mach-ep93xx/core.c
arch/arm/mach-ep93xx/dma.c
arch/arm/mach-ep93xx/edb93xx.c
arch/arm/mach-ep93xx/gesbc9312.c
arch/arm/mach-ep93xx/gpio-ep93xx.h [new file with mode: 0644]
arch/arm/mach-ep93xx/hardware.h [new file with mode: 0644]
arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h [deleted file]
arch/arm/mach-ep93xx/include/mach/hardware.h [deleted file]
arch/arm/mach-ep93xx/include/mach/platform.h [deleted file]
arch/arm/mach-ep93xx/micro9.c
arch/arm/mach-ep93xx/platform.h [new file with mode: 0644]
arch/arm/mach-ep93xx/simone.c
arch/arm/mach-ep93xx/snappercl15.c
arch/arm/mach-ep93xx/ts72xx.c
arch/arm/mach-ep93xx/vision_ep9307.c
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/Makefile
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/exynos.c
arch/arm/mach-exynos/firmware.c
arch/arm/mach-exynos/mcpm-exynos.c
arch/arm/mach-exynos/platsmp.c
arch/arm/mach-exynos/smc.h
arch/arm/mach-exynos/suspend.c
arch/arm/mach-imx/devices/platform-fec.c
arch/arm/mach-imx/devices/platform-gpio_keys.c
arch/arm/mach-imx/devices/platform-imx2-wdt.c
arch/arm/mach-imx/devices/platform-mxc_nand.c
arch/arm/mach-imx/hardware.h
arch/arm/mach-imx/pm-imx6.c
arch/arm/mach-integrator/impd1.c
arch/arm/mach-iop13xx/pci.c
arch/arm/mach-iop13xx/tpmi.c
arch/arm/mach-ixp4xx/Kconfig
arch/arm/mach-ixp4xx/Makefile
arch/arm/mach-ixp4xx/avila-pci.c
arch/arm/mach-ixp4xx/avila-setup.c
arch/arm/mach-ixp4xx/common-pci.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-ixp4xx/coyote-pci.c
arch/arm/mach-ixp4xx/coyote-setup.c
arch/arm/mach-ixp4xx/dsmg600-pci.c
arch/arm/mach-ixp4xx/dsmg600-setup.c
arch/arm/mach-ixp4xx/fsg-pci.c
arch/arm/mach-ixp4xx/fsg-setup.c
arch/arm/mach-ixp4xx/gateway7001-pci.c
arch/arm/mach-ixp4xx/gateway7001-setup.c
arch/arm/mach-ixp4xx/gtwx5715-pci.c
arch/arm/mach-ixp4xx/gtwx5715-setup.c
arch/arm/mach-ixp4xx/include/mach/entry-macro.S [deleted file]
arch/arm/mach-ixp4xx/include/mach/irqs.h [deleted file]
arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
arch/arm/mach-ixp4xx/include/mach/npe.h [deleted file]
arch/arm/mach-ixp4xx/include/mach/qmgr.h [deleted file]
arch/arm/mach-ixp4xx/irqs.h [new file with mode: 0644]
arch/arm/mach-ixp4xx/ixdp425-pci.c
arch/arm/mach-ixp4xx/ixdp425-setup.c
arch/arm/mach-ixp4xx/ixdpg425-pci.c
arch/arm/mach-ixp4xx/ixp4xx-of.c [new file with mode: 0644]
arch/arm/mach-ixp4xx/ixp4xx_npe.c [deleted file]
arch/arm/mach-ixp4xx/ixp4xx_qmgr.c [deleted file]
arch/arm/mach-ixp4xx/nas100d-pci.c
arch/arm/mach-ixp4xx/nas100d-setup.c
arch/arm/mach-ixp4xx/nslu2-pci.c
arch/arm/mach-ixp4xx/nslu2-setup.c
arch/arm/mach-ixp4xx/wg302v2-pci.c
arch/arm/mach-ixp4xx/wg302v2-setup.c
arch/arm/mach-ks8695/include/mach/hardware.h
arch/arm/mach-lpc32xx/phy3250.c
arch/arm/mach-mediatek/mediatek.c
arch/arm/mach-mv78xx0/common.c
arch/arm/mach-omap1/include/mach/hardware.h
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/i2c.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/mmc.h
arch/arm/mach-omap2/omap-wakeupgen.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod.h
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h
arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c
arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_33xx_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_43xx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_hwmod_54xx_data.c
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm/mach-omap2/omap_hwmod_81xx_data.c
arch/arm/mach-omap2/pm33xx-core.c
arch/arm/mach-omap2/sleep43xx.S
arch/arm/mach-omap2/sr_device.c
arch/arm/mach-orion5x/common.c
arch/arm/mach-prima2/common.c
arch/arm/mach-pxa/balloon3.c
arch/arm/mach-pxa/colibri-pxa270.c
arch/arm/mach-pxa/colibri-pxa300.c
arch/arm/mach-pxa/colibri-pxa320.c
arch/arm/mach-pxa/colibri-pxa3xx.c
arch/arm/mach-pxa/gumstix.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/trizeps4.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-rockchip/platsmp.c
arch/arm/mach-rockchip/pm.c
arch/arm/mach-rockchip/rockchip.c
arch/arm/mach-s3c24xx/include/mach/hardware.h
arch/arm/mach-s3c64xx/mach-crag6410-module.c
arch/arm/mach-sa1100/include/mach/memory.h
arch/arm/mach-sa1100/neponset.c
arch/arm/mach-shmobile/pm-rcar-gen2.c
arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
arch/arm/mach-stm32/Kconfig
arch/arm/mach-sunxi/mc_smp.c
arch/arm/mach-sunxi/platsmp.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/cpuidle-tegra114.c
arch/arm/mach-tegra/cpuidle-tegra20.c
arch/arm/mach-tegra/cpuidle-tegra30.c
arch/arm/mach-tegra/iomap.h
arch/arm/mach-tegra/irammap.h
arch/arm/mach-tegra/pm.c
arch/arm/mach-tegra/reset-handler.S
arch/arm/mach-tegra/reset.c
arch/arm/mach-tegra/reset.h
arch/arm/mach-tegra/sleep-tegra20.S
arch/arm/mach-tegra/sleep-tegra30.S
arch/arm/mach-tegra/sleep.S
arch/arm/mach-tegra/tegra.c
arch/arm/mach-u300/regulator.c
arch/arm/mach-w90x900/include/mach/hardware.h
arch/arm/mach-zynq/common.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/init.c
arch/arm/plat-pxa/ssp.c
arch/arm/vdso/Makefile
arch/arm/xen/p2m.c
arch/arm64/Kconfig
arch/arm64/Kconfig.platforms
arch/arm64/boot/dts/Makefile
arch/arm64/boot/dts/allwinner/Makefile
arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-oceanic-5205-5inmfd.dts [new file with mode: 0644]
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi
arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
arch/arm64/boot/dts/allwinner/sun50i-h5-emlid-neutis-n5-devboard.dts
arch/arm64/boot/dts/allwinner/sun50i-h5-emlid-neutis-n5.dtsi
arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo-plus2.dts
arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus.dts
arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts
arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts [new file with mode: 0644]
arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts [new file with mode: 0644]
arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi
arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
arch/arm64/boot/dts/amlogic/Makefile
arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts
arch/arm64/boot/dts/amlogic/meson-g12a.dtsi
arch/arm64/boot/dts/amlogic/meson-gxl-s905d-phicomm-n1.dts
arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
arch/arm64/boot/dts/bitmain/bm1880-sophon-edge.dts
arch/arm64/boot/dts/bitmain/bm1880.dtsi
arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi
arch/arm64/boot/dts/exynos/exynos5433-tm2.dts
arch/arm64/boot/dts/exynos/exynos5433.dtsi
arch/arm64/boot/dts/exynos/exynos7.dtsi
arch/arm64/boot/dts/freescale/Makefile
arch/arm64/boot/dts/freescale/fsl-ls1012a-oxalis.dts
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
arch/arm64/boot/dts/freescale/fsl-lx2160a-qds.dts
arch/arm64/boot/dts/freescale/fsl-lx2160a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
arch/arm64/boot/dts/freescale/imx8mm-evk.dts [new file with mode: 0644]
arch/arm64/boot/dts/freescale/imx8mm.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/freescale/imx8mq-evk.dts
arch/arm64/boot/dts/freescale/imx8mq-zii-ultra-rmb3.dts [new file with mode: 0644]
arch/arm64/boot/dts/freescale/imx8mq-zii-ultra-zest.dts [new file with mode: 0644]
arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/freescale/imx8mq.dtsi
arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
arch/arm64/boot/dts/freescale/imx8qxp.dtsi
arch/arm64/boot/dts/hisilicon/hi3660.dtsi
arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
arch/arm64/boot/dts/hisilicon/hi3670.dtsi
arch/arm64/boot/dts/hisilicon/hikey970-pinctrl.dtsi
arch/arm64/boot/dts/intel/Makefile [new file with mode: 0644]
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts [new file with mode: 0644]
arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
arch/arm64/boot/dts/mediatek/mt2712e.dtsi
arch/arm64/boot/dts/mediatek/mt8173.dtsi
arch/arm64/boot/dts/mediatek/mt8183-pinfunc.h [new file with mode: 0644]
arch/arm64/boot/dts/nvidia/Makefile
arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
arch/arm64/boot/dts/nvidia/tegra186.dtsi
arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
arch/arm64/boot/dts/nvidia/tegra194-p2972-0000.dts
arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts
arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
arch/arm64/boot/dts/nvidia/tegra210-p2894.dtsi
arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts [new file with mode: 0644]
arch/arm64/boot/dts/nvidia/tegra210-smaug.dts
arch/arm64/boot/dts/nvidia/tegra210.dtsi
arch/arm64/boot/dts/qcom/apq8096-db820c-pins.dtsi
arch/arm64/boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi
arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
arch/arm64/boot/dts/qcom/msm8916.dtsi
arch/arm64/boot/dts/qcom/msm8996-pins.dtsi
arch/arm64/boot/dts/qcom/msm8996.dtsi
arch/arm64/boot/dts/qcom/msm8998-mtp.dtsi
arch/arm64/boot/dts/qcom/msm8998.dtsi
arch/arm64/boot/dts/qcom/pm8005.dtsi
arch/arm64/boot/dts/qcom/pm8998.dtsi
arch/arm64/boot/dts/qcom/pmi8994.dtsi
arch/arm64/boot/dts/qcom/pmi8998.dtsi
arch/arm64/boot/dts/qcom/pms405.dtsi
arch/arm64/boot/dts/qcom/qcs404-evb-1000.dts
arch/arm64/boot/dts/qcom/qcs404-evb-4000.dts
arch/arm64/boot/dts/qcom/qcs404-evb.dtsi
arch/arm64/boot/dts/qcom/qcs404.dtsi
arch/arm64/boot/dts/qcom/sdm845-mtp.dts
arch/arm64/boot/dts/qcom/sdm845.dtsi
arch/arm64/boot/dts/renesas/cat875.dtsi
arch/arm64/boot/dts/renesas/r8a774a1.dtsi
arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts
arch/arm64/boot/dts/renesas/r8a774c0.dtsi
arch/arm64/boot/dts/renesas/r8a7795.dtsi
arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts
arch/arm64/boot/dts/renesas/r8a7796.dtsi
arch/arm64/boot/dts/renesas/r8a77965.dtsi
arch/arm64/boot/dts/renesas/r8a77980.dtsi
arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
arch/arm64/boot/dts/renesas/r8a77990.dtsi
arch/arm64/boot/dts/renesas/r8a77995-draak.dts
arch/arm64/boot/dts/renesas/salvator-common.dtsi
arch/arm64/boot/dts/rockchip/Makefile
arch/arm64/boot/dts/rockchip/px30-evb.dts
arch/arm64/boot/dts/rockchip/rk3328-evb.dts
arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
arch/arm64/boot/dts/rockchip/rk3328.dtsi
arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi
arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts
arch/arm64/boot/dts/rockchip/rk3368-lion-haikou.dts
arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi
arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts
arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts
arch/arm64/boot/dts/rockchip/rk3368-r88.dts
arch/arm64/boot/dts/rockchip/rk3368.dtsi
arch/arm64/boot/dts/rockchip/rk3399-evb.dts
arch/arm64/boot/dts/rockchip/rk3399-ficus.dts
arch/arm64/boot/dts/rockchip/rk3399-gru-bob.dts
arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi
arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi
arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
arch/arm64/boot/dts/rockchip/rk3399-nanopc-t4.dts
arch/arm64/boot/dts/rockchip/rk3399-nanopi-neo4.dts [new file with mode: 0644]
arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi
arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts [new file with mode: 0644]
arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts
arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi
arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts
arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi
arch/arm64/boot/dts/rockchip/rk3399.dtsi
arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts
arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts
arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revB.dts
arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revA.dts
arch/arm64/boot/dts/xilinx/zynqmp-zcu106-revA.dts
arch/arm64/boot/dts/xilinx/zynqmp-zcu111-revA.dts
arch/arm64/configs/defconfig
arch/arm64/include/asm/Kbuild
arch/arm64/include/asm/boot.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/hugetlb.h
arch/arm64/include/asm/memory.h
arch/arm64/mm/init.c
arch/arm64/mm/mmu.c
arch/c6x/include/asm/Kbuild
arch/c6x/mm/init.c
arch/h8300/Kconfig
arch/h8300/include/asm/Kbuild
arch/h8300/include/asm/uaccess.h [deleted file]
arch/h8300/kernel/setup.c
arch/h8300/mm/init.c
arch/hexagon/Kconfig
arch/hexagon/include/asm/Kbuild
arch/hexagon/include/asm/uaccess.h
arch/hexagon/mm/init.c
arch/ia64/Kconfig
arch/ia64/include/asm/segment.h [deleted file]
arch/ia64/kernel/machvec.c
arch/ia64/mm/init.c
arch/m68k/Kconfig
arch/m68k/mm/init.c
arch/microblaze/mm/init.c
arch/mips/Kconfig
arch/mips/ath79/clock.c
arch/mips/ath79/setup.c
arch/mips/configs/ip22_defconfig
arch/mips/configs/ip27_defconfig
arch/mips/include/asm/Kbuild
arch/mips/include/asm/bitops.h
arch/mips/kernel/cpu-bugs64.c
arch/mips/mm/gup.c
arch/mips/mm/init.c
arch/mips/txx9/generic/setup.c
arch/nds32/include/asm/Kbuild
arch/nds32/include/asm/pgtable.h
arch/nds32/kernel/ftrace.c
arch/nds32/kernel/head.S
arch/nds32/mm/init.c
arch/nios2/Kconfig
arch/nios2/include/asm/Kbuild
arch/nios2/mm/init.c
arch/openrisc/include/asm/Kbuild
arch/openrisc/kernel/ptrace.c
arch/openrisc/kernel/setup.c
arch/openrisc/kernel/traps.c
arch/openrisc/mm/init.c
arch/openrisc/mm/tlb.c
arch/parisc/include/asm/Kbuild
arch/parisc/include/asm/cache.h
arch/parisc/kernel/cache.c
arch/parisc/kernel/drivers.c
arch/parisc/kernel/firmware.c
arch/parisc/kernel/ftrace.c
arch/parisc/kernel/head.S
arch/parisc/kernel/inventory.c
arch/parisc/kernel/pci.c
arch/parisc/kernel/perf_images.h
arch/parisc/kernel/process.c
arch/parisc/kernel/processor.c
arch/parisc/kernel/syscall.S
arch/parisc/kernel/time.c
arch/parisc/kernel/unwind.c
arch/parisc/kernel/vmlinux.lds.S
arch/parisc/mm/init.c
arch/powerpc/Kconfig
arch/powerpc/include/asm/book3s/64/hugetlb.h
arch/powerpc/include/asm/livepatch.h
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/e500_mmu.c
arch/powerpc/mm/book3s64/iommu_api.c
arch/powerpc/mm/book3s64/radix_tlb.c
arch/powerpc/mm/mem.c
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/powernv/npu-dma.c
arch/powerpc/sysdev/tsi108_dev.c
arch/riscv/mm/init.c
arch/s390/Kconfig
arch/s390/include/asm/cpacf.h
arch/s390/include/asm/hugetlb.h
arch/s390/include/asm/livepatch.h
arch/s390/include/asm/segment.h [deleted file]
arch/s390/kernel/ptrace.c
arch/s390/kvm/interrupt.c
arch/s390/mm/init.c
arch/sh/Kconfig
arch/sh/boards/board-apsh4a3a.c
arch/sh/boards/board-apsh4ad0a.c
arch/sh/boards/board-edosk7705.c
arch/sh/boards/board-edosk7760.c
arch/sh/boards/board-espt.c
arch/sh/boards/board-urquell.c
arch/sh/boards/mach-dreamcast/irq.c
arch/sh/boards/mach-microdev/setup.c
arch/sh/boards/mach-sdk7786/fpga.c
arch/sh/boards/mach-sdk7786/setup.c
arch/sh/boards/mach-sdk7786/sram.c
arch/sh/boards/mach-se/7343/irq.c
arch/sh/boards/mach-se/7722/irq.c
arch/sh/drivers/pci/pci-sh7751.c
arch/sh/drivers/pci/pci-sh7780.c
arch/sh/drivers/pci/pcie-sh7786.c
arch/sh/include/asm/Kbuild
arch/sh/mm/gup.c
arch/sh/mm/init.c
arch/sh/mm/pmb.c
arch/sh/mm/uncached.c
arch/sparc/Kconfig
arch/sparc/include/asm/pgtable_64.h
arch/sparc/kernel/time_64.c
arch/sparc/mm/gup.c
arch/sparc/mm/init_32.c
arch/sparc/mm/init_64.c
arch/um/kernel/mem.c
arch/unicore32/Kconfig
arch/unicore32/configs/unicore32_defconfig
arch/unicore32/include/asm/Kbuild
arch/unicore32/include/asm/memory.h
arch/unicore32/mm/init.c
arch/unicore32/mm/ioremap.c
arch/unicore32/mm/mmu.c
arch/x86/Kconfig
arch/x86/Kconfig.debug
arch/x86/entry/common.c
arch/x86/entry/entry_64.S
arch/x86/entry/vdso/vdso2c.c
arch/x86/events/amd/iommu.c
arch/x86/events/intel/bts.c
arch/x86/events/intel/core.c
arch/x86/events/perf_event.h
arch/x86/include/asm/arch_hweight.h
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/ftrace.h
arch/x86/include/asm/hugetlb.h
arch/x86/include/asm/hyperv-tlfs.h
arch/x86/include/asm/irqflags.h
arch/x86/include/asm/livepatch.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/mwait.h
arch/x86/include/asm/nospec-branch.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/text-patching.h
arch/x86/include/asm/vdso.h
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/intel_epb.c
arch/x86/kernel/ftrace.c
arch/x86/kernel/ftrace_32.S
arch/x86/kernel/ftrace_64.S
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/nmi.c
arch/x86/kernel/tsc.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/svm.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/hugetlbpage.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/mem_encrypt.c
arch/x86/mm/mm_internal.h
arch/x86/pci/irq.c
arch/x86/platform/olpc/olpc_dt.c
arch/x86/platform/pvh/enlighten.c
arch/x86/xen/efi.c
arch/x86/xen/enlighten_pv.c
arch/x86/xen/enlighten_pvh.c
arch/x86/xen/time.c
arch/x86/xen/xen-ops.h
arch/xtensa/include/asm/irqflags.h
arch/xtensa/include/asm/segment.h [deleted file]
arch/xtensa/kernel/smp.c
arch/xtensa/mm/init.c
arch/xtensa/platforms/xtfpga/setup.c
block/bio-integrity.c
drivers/acpi/acpi_apd.c
drivers/acpi/device_sysfs.c
drivers/acpi/pci_mcfg.c
drivers/acpi/pci_root.c
drivers/acpi/sleep.c
drivers/ata/pata_ep93xx.c
drivers/ata/sata_rcar.c
drivers/base/cpu.c
drivers/base/memory.c
drivers/base/power/domain.c
drivers/block/brd.c
drivers/block/rbd.c
drivers/bus/tegra-aconnect.c
drivers/bus/ti-sysc.c
drivers/clk/axs10x/i2s_pll_clock.c
drivers/clk/axs10x/pll_clock.c
drivers/clk/bcm/clk-bcm2835-aux.c
drivers/clk/bcm/clk-bcm2835.c
drivers/clk/bcm/clk-kona.c
drivers/clk/berlin/berlin2-div.c
drivers/clk/berlin/bg2.c
drivers/clk/berlin/bg2q.c
drivers/clk/clk-fixed-mmio.c
drivers/clk/clk-fractional-divider.c
drivers/clk/clk-hsdk-pll.c
drivers/clk/clk-multiplier.c
drivers/clk/davinci/pll-da850.c
drivers/clk/h8300/clk-div.c
drivers/clk/h8300/clk-h8s2678.c
drivers/clk/hisilicon/clk-hi3660-stub.c
drivers/clk/imx/clk-composite-8m.c
drivers/clk/imx/clk-frac-pll.c
drivers/clk/imx/clk-imx21.c
drivers/clk/imx/clk-imx27.c
drivers/clk/imx/clk-pfdv2.c
drivers/clk/imx/clk-pllv4.c
drivers/clk/imx/clk-sccg-pll.c
drivers/clk/ingenic/cgu.c
drivers/clk/ingenic/jz4740-cgu.c
drivers/clk/ingenic/jz4770-cgu.c
drivers/clk/ingenic/jz4780-cgu.c
drivers/clk/loongson1/clk-loongson1c.c
drivers/clk/microchip/clk-core.c
drivers/clk/microchip/clk-pic32mzda.c
drivers/clk/mvebu/armada-37xx-periph.c
drivers/clk/mvebu/armada-37xx-tbg.c
drivers/clk/mvebu/clk-corediv.c
drivers/clk/nxp/clk-lpc18xx-ccu.c
drivers/clk/nxp/clk-lpc18xx-cgu.c
drivers/clk/nxp/clk-lpc32xx.c
drivers/clk/pxa/clk-pxa.c
drivers/clk/renesas/clk-r8a73a4.c
drivers/clk/renesas/clk-r8a7740.c
drivers/clk/renesas/clk-rcar-gen2.c
drivers/clk/renesas/clk-rz.c
drivers/clk/renesas/clk-sh73a0.c
drivers/clk/renesas/r9a06g032-clocks.c
drivers/clk/renesas/rcar-usb2-clock-sel.c
drivers/clk/renesas/renesas-cpg-mssr.c
drivers/clk/rockchip/clk-half-divider.c
drivers/clk/rockchip/clk-px30.c
drivers/clk/rockchip/clk-rk3036.c
drivers/clk/rockchip/clk-rk3128.c
drivers/clk/rockchip/clk-rk3188.c
drivers/clk/rockchip/clk-rk3228.c
drivers/clk/rockchip/clk-rk3288.c
drivers/clk/rockchip/clk-rk3328.c
drivers/clk/rockchip/clk-rk3368.c
drivers/clk/rockchip/clk-rk3399.c
drivers/clk/rockchip/clk-rv1108.c
drivers/clk/rockchip/clk.c
drivers/clk/samsung/clk-cpu.c
drivers/clk/samsung/clk-exynos-clkout.c
drivers/clk/samsung/clk-exynos3250.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5-subcmu.c
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/samsung/clk-pll.c
drivers/clk/samsung/clk-s3c2410-dclk.c
drivers/clk/samsung/clk-s3c2412.c
drivers/clk/samsung/clk-s3c2443.c
drivers/clk/samsung/clk.c
drivers/clk/sifive/fu540-prci.c
drivers/clk/socfpga/clk-gate-s10.c
drivers/clk/socfpga/clk-periph-s10.c
drivers/clk/socfpga/clk-pll-s10.c
drivers/clk/st/clkgen-mux.c
drivers/clk/sunxi-ng/ccu-sun4i-a10.c
drivers/clk/sunxi-ng/ccu-sun50i-a64.c
drivers/clk/sunxi-ng/ccu-sun50i-h6.c
drivers/clk/sunxi-ng/ccu-sun5i.c
drivers/clk/sunxi-ng/ccu-sun6i-a31.c
drivers/clk/sunxi-ng/ccu-sun8i-a23.c
drivers/clk/sunxi-ng/ccu-sun8i-a33.c
drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
drivers/clk/sunxi-ng/ccu-sun8i-h3.c
drivers/clk/sunxi-ng/ccu-sun8i-r40.c
drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
drivers/clk/sunxi-ng/ccu-sun9i-a80.c
drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
drivers/clk/sunxi-ng/ccu_div.c
drivers/clk/sunxi-ng/ccu_frac.c
drivers/clk/sunxi-ng/ccu_gate.c
drivers/clk/sunxi-ng/ccu_mmc_timing.c
drivers/clk/sunxi-ng/ccu_mp.c
drivers/clk/sunxi-ng/ccu_mult.c
drivers/clk/sunxi-ng/ccu_mux.c
drivers/clk/sunxi-ng/ccu_nk.c
drivers/clk/sunxi-ng/ccu_nkm.c
drivers/clk/sunxi-ng/ccu_nkmp.c
drivers/clk/sunxi-ng/ccu_nm.c
drivers/clk/sunxi-ng/ccu_phase.c
drivers/clk/sunxi-ng/ccu_sdm.c
drivers/clk/sunxi/clk-a10-mod1.c
drivers/clk/sunxi/clk-a10-pll2.c
drivers/clk/sunxi/clk-a10-ve.c
drivers/clk/sunxi/clk-a20-gmac.c
drivers/clk/sunxi/clk-mod0.c
drivers/clk/sunxi/clk-simple-gates.c
drivers/clk/sunxi/clk-sun4i-display.c
drivers/clk/sunxi/clk-sun4i-pll3.c
drivers/clk/sunxi/clk-sun4i-tcon-ch1.c
drivers/clk/sunxi/clk-sun8i-apb0.c
drivers/clk/sunxi/clk-sun8i-bus-gates.c
drivers/clk/sunxi/clk-sun8i-mbus.c
drivers/clk/sunxi/clk-sun9i-cpus.c
drivers/clk/sunxi/clk-sun9i-mmc.c
drivers/clk/sunxi/clk-sunxi.c
drivers/clk/sunxi/clk-usb.c
drivers/clk/tegra/clk-emc.c
drivers/clk/tegra/clk-periph-fixed.c
drivers/clk/tegra/clk-sdmmc-mux.c
drivers/clk/tegra/clk.c
drivers/clk/ti/adpll.c
drivers/clk/ti/clk.c
drivers/clk/ti/fapll.c
drivers/clk/versatile/clk-sp810.c
drivers/clk/x86/clk-pmc-atom.c
drivers/clk/zynqmp/clkc.c
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/timer-ixp4xx.c [new file with mode: 0644]
drivers/cpufreq/cpufreq.c
drivers/cpufreq/loongson1-cpufreq.c
drivers/crypto/caam/caamalg.c
drivers/crypto/caam/caamalg_qi.c
drivers/crypto/caam/caamalg_qi2.c
drivers/crypto/caam/error.c
drivers/crypto/caam/jr.c
drivers/crypto/caam/regs.h
drivers/crypto/chelsio/chcr_algo.c
drivers/crypto/chelsio/chcr_core.c
drivers/crypto/chelsio/chcr_ipsec.c
drivers/crypto/ixp4xx_crypto.c
drivers/dax/Kconfig
drivers/dax/device.c
drivers/dax/pmem/core.c
drivers/dma-buf/dma-fence.c
drivers/edac/Kconfig
drivers/edac/edac_mc.c
drivers/firewire/core-iso.c
drivers/firmware/Kconfig
drivers/firmware/Makefile
drivers/firmware/arm_scmi/driver.c
drivers/firmware/imx/Makefile
drivers/firmware/imx/imx-scu-irq.c [new file with mode: 0644]
drivers/firmware/imx/imx-scu.c
drivers/firmware/imx/scu-pd.c
drivers/firmware/trusted_foundations.c [new file with mode: 0644]
drivers/firmware/xilinx/zynqmp-debug.c
drivers/firmware/xilinx/zynqmp.c
drivers/fpga/Kconfig
drivers/fpga/Makefile
drivers/fpga/dfl-afu-dma-region.c
drivers/fpga/zynqmp-fpga.c [new file with mode: 0644]
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-ixp4xx.c [new file with mode: 0644]
drivers/gpio/gpio-max77650.c [new file with mode: 0644]
drivers/gpu/drm/Kconfig
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c
drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h
drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
drivers/gpu/drm/amd/amdgpu/vega10_ih.c
drivers/gpu/drm/amd/amdkfd/kfd_topology.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/bridge/Kconfig
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
drivers/gpu/drm/fsl-dcu/Kconfig
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/gvt/debugfs.c
drivers/gpu/drm/i915/gvt/dmabuf.c
drivers/gpu/drm/i915/gvt/gtt.c
drivers/gpu/drm/i915/gvt/gtt.h
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/mmio_context.c
drivers/gpu/drm/i915/gvt/reg.h
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/i915_gem_userptr.c
drivers/gpu/drm/i915/i915_request.c
drivers/gpu/drm/i915/intel_breadcrumbs.c
drivers/gpu/drm/i915/intel_context.c
drivers/gpu/drm/i915/intel_context_types.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_fbc.c
drivers/gpu/drm/i915/intel_guc_submission.c
drivers/gpu/drm/i915/intel_pipe_crc.c
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
drivers/gpu/drm/msm/msm_atomic.c
drivers/gpu/drm/msm/msm_drv.h
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem.h
drivers/gpu/drm/nouveau/Kconfig
drivers/gpu/drm/nouveau/dispnv50/disp.h
drivers/gpu/drm/nouveau/dispnv50/head.c
drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c
drivers/gpu/drm/nouveau/dispnv50/wndw.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
drivers/gpu/drm/panfrost/panfrost_device.c
drivers/gpu/drm/panfrost/panfrost_drv.c
drivers/gpu/drm/pl111/pl111_display.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_mn.c
drivers/gpu/drm/rockchip/rockchip_drm_gem.c
drivers/gpu/drm/shmobile/Kconfig
drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
drivers/gpu/drm/tilcdc/Kconfig
drivers/gpu/drm/vc4/vc4_dsi.c
drivers/gpu/drm/via/via_dmablit.c
drivers/gpu/drm/xen/xen_drm_front_gem.c
drivers/hid/hid-input.c
drivers/hwmon/aspeed-pwm-tacho.c
drivers/hwmon/gpio-fan.c
drivers/hwmon/hwmon.c
drivers/hwmon/mlxreg-fan.c
drivers/hwmon/npcm750-pwm-fan.c
drivers/hwmon/pwm-fan.c
drivers/iio/inkern.c
drivers/infiniband/core/addr.c
drivers/infiniband/core/nldev.c
drivers/infiniband/core/umem.c
drivers/infiniband/core/umem_odp.c
drivers/infiniband/hw/hfi1/user_pages.c
drivers/infiniband/hw/mlx5/devx.c
drivers/infiniband/hw/mthca/mthca_memfree.c
drivers/infiniband/hw/ocrdma/ocrdma_ah.c
drivers/infiniband/hw/ocrdma/ocrdma_hw.c
drivers/infiniband/hw/qib/qib_user_pages.c
drivers/infiniband/hw/qib/qib_user_sdma.c
drivers/infiniband/hw/usnic/usnic_uiom.c
drivers/input/evdev.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/ep93xx_keypad.c
drivers/input/keyboard/qt1050.c [new file with mode: 0644]
drivers/input/keyboard/snvs_pwrkey.c
drivers/input/keyboard/sun4i-lradc-keys.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/gpio-vibra.c [new file with mode: 0644]
drivers/input/misc/ixp4xx-beeper.c
drivers/input/misc/max77650-onkey.c [new file with mode: 0644]
drivers/input/mouse/psmouse-base.c
drivers/input/rmi4/rmi_f54.c
drivers/input/serio/Kconfig
drivers/input/serio/hyperv-keyboard.c
drivers/input/serio/i8042.c
drivers/input/serio/libps2.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/edt-ft5x06.c
drivers/input/touchscreen/goodix.c
drivers/input/touchscreen/iqs5xx.c [new file with mode: 0644]
drivers/iommu/amd_iommu.c
drivers/iommu/dma-iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/intel_irq_remapping.c
drivers/iommu/msm_iommu.c
drivers/irqchip/Kconfig
drivers/irqchip/Makefile
drivers/irqchip/irq-ixp4xx.c [new file with mode: 0644]
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/leds-max77650.c [new file with mode: 0644]
drivers/lightnvm/core.c
drivers/lightnvm/pblk-cache.c
drivers/lightnvm/pblk-core.c
drivers/lightnvm/pblk-gc.c
drivers/lightnvm/pblk-init.c
drivers/lightnvm/pblk-map.c
drivers/lightnvm/pblk-rb.c
drivers/lightnvm/pblk-read.c
drivers/lightnvm/pblk-recovery.c
drivers/lightnvm/pblk-write.c
drivers/lightnvm/pblk.h
drivers/mailbox/mtk-cmdq-mailbox.c
drivers/md/Kconfig
drivers/md/Makefile
drivers/md/dm-cache-metadata.c
drivers/md/dm-crypt.c
drivers/md/dm-delay.c
drivers/md/dm-dust.c [new file with mode: 0644]
drivers/md/dm-exception-store.h
drivers/md/dm-init.c
drivers/md/dm-integrity.c
drivers/md/dm-ioctl.c
drivers/md/dm-mpath.c
drivers/md/dm-rq.c
drivers/md/dm-snap.c
drivers/md/dm-target.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-writecache.c
drivers/md/dm-zoned-metadata.c
drivers/md/dm-zoned-target.c
drivers/md/dm.c
drivers/md/persistent-data/dm-space-map-common.c
drivers/media/common/videobuf2/videobuf2-core.c
drivers/media/common/videobuf2/videobuf2-dma-contig.c
drivers/media/common/videobuf2/videobuf2-dma-sg.c
drivers/media/platform/atmel/atmel-isc-regs.h
drivers/media/platform/atmel/atmel-isc.c
drivers/media/platform/coda/coda-common.c
drivers/media/platform/davinci/vpbe.c
drivers/media/platform/omap/omap_vout.c
drivers/media/platform/rcar-vin/rcar-csi2.c
drivers/media/platform/tegra-cec/tegra_cec.c
drivers/media/v4l2-core/videobuf-dma-sg.c
drivers/memory/emif.h
drivers/memory/tegra/mc.c
drivers/memory/tegra/mc.h
drivers/memory/tegra/tegra114.c
drivers/memory/tegra/tegra124-emc.c
drivers/memory/tegra/tegra124.c
drivers/memory/tegra/tegra20.c
drivers/memory/tegra/tegra210.c
drivers/memory/tegra/tegra30.c
drivers/memory/ti-emif-pm.c
drivers/memory/ti-emif-sram-pm.S
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/ab8500-debugfs.c
drivers/mfd/altera-sysmgr.c [new file with mode: 0644]
drivers/mfd/atmel-hlcdc.c
drivers/mfd/axp20x-i2c.c
drivers/mfd/axp20x.c
drivers/mfd/cros_ec.c
drivers/mfd/cros_ec_dev.c
drivers/mfd/cs47l35-tables.c
drivers/mfd/cs47l90-tables.c
drivers/mfd/da9063-core.c
drivers/mfd/da9063-i2c.c
drivers/mfd/da9063-irq.c
drivers/mfd/intel-lpss-pci.c
drivers/mfd/intel-lpss.c
drivers/mfd/intel_quark_i2c_gpio.c
drivers/mfd/intel_soc_pmic_chtwc.c
drivers/mfd/max77620.c
drivers/mfd/max77650.c [new file with mode: 0644]
drivers/mfd/mfd-core.c
drivers/mfd/rk808.c
drivers/mfd/sec-core.c
drivers/mfd/sec-irq.c
drivers/mfd/ssbi.c
drivers/mfd/stmfx.c [new file with mode: 0644]
drivers/mfd/sun6i-prcm.c
drivers/mfd/syscon.c
drivers/mfd/t7l66xb.c
drivers/mfd/tc6387xb.c
drivers/mfd/tc6393xb.c
drivers/mfd/tps65912-spi.c
drivers/mfd/twl6040.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/aspeed-lpc-ctrl.c [deleted file]
drivers/misc/aspeed-lpc-snoop.c [deleted file]
drivers/misc/aspeed-p2a-ctrl.c [deleted file]
drivers/misc/genwqe/card_utils.c
drivers/misc/pci_endpoint_test.c
drivers/misc/vmw_vmci/vmci_host.c
drivers/misc/vmw_vmci/vmci_queue_pair.c
drivers/mmc/host/meson-mx-sdio.c
drivers/mmc/host/mvsdio.c
drivers/mmc/host/pxamci.c
drivers/mtd/maps/sa1100-flash.c
drivers/mtd/nand/raw/vf610_nfc.c
drivers/net/bonding/bond_options.c
drivers/net/ethernet/allwinner/sun4i-emac.c
drivers/net/ethernet/arc/emac_main.c
drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
drivers/net/ethernet/cirrus/Kconfig
drivers/net/ethernet/cirrus/ep93xx_eth.c
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/freescale/fec_mpc52xx.c
drivers/net/ethernet/freescale/fman/mac.c
drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/ibm/ibmvnic.h
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlxsw/Kconfig
drivers/net/ethernet/micrel/ks8851.c
drivers/net/ethernet/micrel/ks8851_mll.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/seeq/sgiseeq.c
drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
drivers/net/ethernet/ti/Makefile
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/ethernet/xilinx/xilinx_emaclite.c
drivers/net/ethernet/xscale/ixp4xx_eth.c
drivers/net/ieee802154/ca8210.c
drivers/net/phy/mdio-mux-meson-g12a.c
drivers/net/phy/realtek.c
drivers/net/wan/ixp4xx_hss.c
drivers/net/wireless/mediatek/mt76/eeprom.c
drivers/nvdimm/label.c
drivers/nvdimm/namespace_devs.c
drivers/nvdimm/nd.h
drivers/nvme/host/core.c
drivers/nvme/host/fabrics.c
drivers/nvme/host/fc.c
drivers/nvme/host/lightnvm.c
drivers/nvme/host/multipath.c
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/host/trace.h
drivers/nvmem/zynqmp_nvmem.c
drivers/of/of_net.c
drivers/pci/Makefile
drivers/pci/bus.c
drivers/pci/controller/dwc/Kconfig
drivers/pci/controller/dwc/Makefile
drivers/pci/controller/dwc/pci-dra7xx.c
drivers/pci/controller/dwc/pci-imx6.c
drivers/pci/controller/dwc/pci-keystone.c
drivers/pci/controller/dwc/pci-layerscape-ep.c
drivers/pci/controller/dwc/pci-layerscape.c
drivers/pci/controller/dwc/pcie-al.c [new file with mode: 0644]
drivers/pci/controller/dwc/pcie-artpec6.c
drivers/pci/controller/dwc/pcie-designware-ep.c
drivers/pci/controller/dwc/pcie-designware-host.c
drivers/pci/controller/dwc/pcie-designware-plat.c
drivers/pci/controller/dwc/pcie-designware.c
drivers/pci/controller/dwc/pcie-designware.h
drivers/pci/controller/dwc/pcie-qcom.c
drivers/pci/controller/dwc/pcie-uniphier.c
drivers/pci/controller/pci-aardvark.c
drivers/pci/controller/pci-host-generic.c
drivers/pci/controller/pci-hyperv.c
drivers/pci/controller/pci-tegra.c
drivers/pci/controller/pcie-iproc-msi.c
drivers/pci/controller/pcie-iproc.c
drivers/pci/controller/pcie-mediatek.c
drivers/pci/controller/pcie-rcar.c
drivers/pci/controller/pcie-rockchip-ep.c
drivers/pci/controller/pcie-rockchip-host.c
drivers/pci/controller/pcie-xilinx-nwl.c
drivers/pci/controller/pcie-xilinx.c
drivers/pci/endpoint/functions/pci-epf-test.c
drivers/pci/endpoint/pci-epf-core.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/pciehp_pci.c
drivers/pci/hotplug/rpadlpar_core.c
drivers/pci/hotplug/rpaphp_slot.c
drivers/pci/msi.c
drivers/pci/of.c
drivers/pci/p2pdma.c
drivers/pci/pci-acpi.c
drivers/pci/pci-stub.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aer.c
drivers/pci/pcie/aer_inject.c
drivers/pci/pcie/aspm.c
drivers/pci/pcie/bw_notification.c
drivers/pci/pcie/dpc.c
drivers/pci/pcie/pme.c
drivers/pci/probe.c
drivers/pci/proc.c
drivers/pci/quirks.c
drivers/pci/search.c
drivers/pci/setup-bus.c
drivers/pci/slot.c
drivers/pci/switch/switchtec.c
drivers/pci/xen-pcifront.c
drivers/pcmcia/omap_cf.c
drivers/pinctrl/Kconfig
drivers/pinctrl/Makefile
drivers/pinctrl/pinctrl-stmfx.c [new file with mode: 0644]
drivers/platform/chrome/chromeos_laptop.c
drivers/platform/chrome/cros_ec_proto.c
drivers/platform/goldfish/goldfish_pipe.c
drivers/power/reset/at91-sama5d2_shdwc.c
drivers/power/reset/syscon-reboot.c
drivers/power/supply/Kconfig
drivers/power/supply/Makefile
drivers/power/supply/ab8500_bmdata.c
drivers/power/supply/axp20x_usb_power.c
drivers/power/supply/axp288_charger.c
drivers/power/supply/axp288_fuel_gauge.c
drivers/power/supply/bq27xxx_battery.c
drivers/power/supply/charger-manager.c
drivers/power/supply/cpcap-battery.c
drivers/power/supply/cpcap-charger.c
drivers/power/supply/gpio-charger.c
drivers/power/supply/ingenic-battery.c [new file with mode: 0644]
drivers/power/supply/lt3651-charger.c [new file with mode: 0644]
drivers/power/supply/ltc3651-charger.c [deleted file]
drivers/power/supply/max14656_charger_detector.c
drivers/power/supply/max77650-charger.c [new file with mode: 0644]
drivers/power/supply/olpc_battery.c
drivers/power/supply/power_supply_core.c
drivers/power/supply/power_supply_sysfs.c
drivers/power/supply/ucs1002_power.c [new file with mode: 0644]
drivers/pps/clients/pps-gpio.c
drivers/pwm/pwm-ep93xx.c
drivers/rapidio/devices/rio_mport_cdev.c
drivers/rapidio/rio_cm.c
drivers/reset/reset-zynqmp.c
drivers/rtc/rtc-omap.c
drivers/s390/block/dasd_eckd.c
drivers/s390/virtio/virtio_ccw.c
drivers/sbus/char/oradax.c
drivers/scsi/st.c
drivers/sh/intc/userimask.c
drivers/soc/Kconfig
drivers/soc/Makefile
drivers/soc/amlogic/meson-gx-pwrc-vpu.c
drivers/soc/amlogic/meson-gx-socinfo.c
drivers/soc/aspeed/Kconfig [new file with mode: 0644]
drivers/soc/aspeed/Makefile [new file with mode: 0644]
drivers/soc/aspeed/aspeed-lpc-ctrl.c [new file with mode: 0644]
drivers/soc/aspeed/aspeed-lpc-snoop.c [new file with mode: 0644]
drivers/soc/aspeed/aspeed-p2a-ctrl.c [new file with mode: 0644]
drivers/soc/imx/Makefile
drivers/soc/imx/gpc.c
drivers/soc/imx/gpcv2.c
drivers/soc/imx/soc-imx8.c [new file with mode: 0644]
drivers/soc/ixp4xx/Kconfig [new file with mode: 0644]
drivers/soc/ixp4xx/Makefile [new file with mode: 0644]
drivers/soc/ixp4xx/ixp4xx-npe.c [new file with mode: 0644]
drivers/soc/ixp4xx/ixp4xx-qmgr.c [new file with mode: 0644]
drivers/soc/mediatek/mtk-pmic-wrap.c
drivers/soc/qcom/cmd-db.c
drivers/soc/qcom/qmi_interface.c
drivers/soc/qcom/rmtfs_mem.c
drivers/soc/qcom/rpmh-rsc.c
drivers/soc/renesas/renesas-soc.c
drivers/soc/rockchip/grf.c
drivers/soc/tegra/pmc.c
drivers/soc/ti/Kconfig
drivers/soc/ti/pm33xx.c
drivers/soc/xilinx/zynqmp_pm_domains.c
drivers/soc/xilinx/zynqmp_power.c
drivers/spi/spi-rockchip.c
drivers/spi/spi-zynqmp-gqspi.c
drivers/staging/gasket/gasket_page_table.c
drivers/staging/media/imx/imx-ic-prpencvf.c
drivers/staging/media/imx/imx-media-capture.c
drivers/staging/media/imx/imx-media-csi.c
drivers/staging/media/imx/imx-media.h
drivers/staging/media/imx/imx7-media-csi.c
drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c
drivers/staging/media/rockchip/vpu/rockchip_vpu_enc.c
drivers/staging/olpc_dcon/Kconfig
drivers/tee/optee/core.c
drivers/tee/tee_shm.c
drivers/thermal/Kconfig
drivers/thermal/Makefile
drivers/thermal/broadcom/sr-thermal.c
drivers/thermal/cpu_cooling.c
drivers/thermal/intel/Kconfig
drivers/thermal/intel/int340x_thermal/int3403_thermal.c
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
drivers/thermal/of-thermal.c
drivers/thermal/qcom/Kconfig
drivers/thermal/qcom/Makefile
drivers/thermal/qcom/tsens-8916.c [deleted file]
drivers/thermal/qcom/tsens-8960.c
drivers/thermal/qcom/tsens-8974.c [deleted file]
drivers/thermal/qcom/tsens-common.c
drivers/thermal/qcom/tsens-v0_1.c [new file with mode: 0644]
drivers/thermal/qcom/tsens-v1.c [new file with mode: 0644]
drivers/thermal/qcom/tsens-v2.c
drivers/thermal/qcom/tsens.c
drivers/thermal/qcom/tsens.h
drivers/thermal/qoriq_thermal.c
drivers/thermal/rcar_gen3_thermal.c
drivers/thermal/rcar_thermal.c
drivers/thermal/rockchip_thermal.c
drivers/thermal/st/Kconfig
drivers/thermal/st/stm_thermal.c
drivers/thermal/tegra/Kconfig
drivers/thermal/tegra/soctherm.c
drivers/thermal/tegra/soctherm.h
drivers/thermal/tegra/tegra124-soctherm.c
drivers/thermal/tegra/tegra132-soctherm.c
drivers/thermal/tegra/tegra210-soctherm.c
drivers/thermal/thermal-generic-adc.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_mmio.c [new file with mode: 0644]
drivers/tty/sysrq.c
drivers/usb/host/ohci-da8xx.c
drivers/usb/misc/Kconfig
drivers/vfio/vfio_iommu_spapr_tce.c
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/scsi.c
drivers/vhost/vhost.c
drivers/video/backlight/Kconfig
drivers/video/backlight/lm3630a_bl.c
drivers/video/backlight/pwm_bl.c
drivers/video/fbdev/Kconfig
drivers/video/fbdev/fb-puv3.c
drivers/video/fbdev/pvr2fb.c
drivers/virt/fsl_hypervisor.c
drivers/virtio/virtio_ring.c
drivers/watchdog/ixp4xx_wdt.c
drivers/xen/gntdev.c
drivers/xen/privcmd-buf.c
drivers/xen/xen-pciback/xenbus.c
drivers/xen/xenbus/xenbus_dev_frontend.c
fs/afs/addr_list.c
fs/afs/afs.h
fs/afs/callback.c
fs/afs/cell.c
fs/afs/cmservice.c
fs/afs/dir.c
fs/afs/dir_silly.c
fs/afs/dynroot.c
fs/afs/file.c
fs/afs/flock.c
fs/afs/fs_probe.c
fs/afs/fsclient.c
fs/afs/inode.c
fs/afs/internal.h
fs/afs/proc.c
fs/afs/rotate.c
fs/afs/rxrpc.c
fs/afs/security.c
fs/afs/server.c
fs/afs/super.c
fs/afs/vl_list.c
fs/afs/vl_probe.c
fs/afs/vl_rotate.c
fs/afs/vlclient.c
fs/afs/write.c
fs/afs/xattr.c
fs/afs/yfsclient.c
fs/binfmt_elf.c
fs/block_dev.c
fs/cachefiles/namei.c
fs/ceph/caps.c
fs/ceph/debugfs.c
fs/ceph/export.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/locks.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/mdsmap.c
fs/ceph/quota.c
fs/ceph/super.c
fs/ceph/super.h
fs/cifs/dns_resolve.c
fs/coda/psdev.c
fs/configfs/dir.c
fs/dax.c
fs/eventfd.c
fs/exec.c
fs/ext2/inode.c
fs/f2fs/acl.c
fs/f2fs/checkpoint.c
fs/f2fs/data.c
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/gc.c
fs/f2fs/inline.c
fs/f2fs/inode.c
fs/f2fs/namei.c
fs/f2fs/node.c
fs/f2fs/recovery.c
fs/f2fs/segment.c
fs/f2fs/segment.h
fs/f2fs/super.c
fs/f2fs/xattr.c
fs/f2fs/xattr.h
fs/fat/file.c
fs/fuse/control.c
fs/fuse/cuse.c
fs/fuse/dev.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/gfs2/sys.c
fs/hugetlbfs/inode.c
fs/io_uring.c
fs/lockd/clntlock.c
fs/lockd/svc.c
fs/locks.c
fs/nfs/callback.c
fs/nfs/callback_xdr.c
fs/nfs/client.c
fs/nfs/dns_resolve.c
fs/nfsd/export.c
fs/nfsd/netns.h
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4idmap.c
fs/nfsd/nfs4layouts.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4recover.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsd.h
fs/nfsd/nfssvc.c
fs/nfsd/nfsxdr.c
fs/nfsd/state.h
fs/nfsd/vfs.c
fs/nfsd/vfs.h
fs/notify/fsnotify.c
fs/notify/mark.c
fs/ocfs2/dir.c
fs/ocfs2/export.c
fs/ocfs2/ocfs2_fs.h
fs/orangefs/orangefs-bufmap.c
fs/overlayfs/copy_up.c
fs/overlayfs/dir.c
fs/overlayfs/file.c
fs/overlayfs/inode.c
fs/overlayfs/overlayfs.h
fs/proc/base.c
fs/proc/task_mmu.c
fs/quota/dquot.c
fs/quota/quota_v1.c
fs/quota/quota_v2.c
fs/reiserfs/journal.c
fs/reiserfs/xattr.c
fs/sync.c
fs/udf/namei.c
fs/udf/super.c
fs/userfaultfd.c
include/acpi/acpi_bus.h
include/acpi/acpixf.h
include/acpi/platform/aclinux.h
include/asm-generic/hugetlb.h
include/asm-generic/segment.h [deleted file]
include/asm-generic/shmparam.h
include/asm-generic/sizes.h [deleted file]
include/asm-generic/uaccess.h
include/asm-generic/vmlinux.lds.h
include/dt-bindings/clock/xlnx,zynqmp-clk.h [deleted file]
include/dt-bindings/clock/xlnx-zynqmp-clk.h [new file with mode: 0644]
include/dt-bindings/firmware/imx/rsrc.h
include/dt-bindings/pinctrl/am33xx.h
include/dt-bindings/pinctrl/omap.h
include/dt-bindings/power/r8a77965-sysc.h
include/dt-bindings/thermal/tegra124-soctherm.h
include/linux/acpi.h
include/linux/balloon_compaction.h
include/linux/binfmts.h
include/linux/bitops.h
include/linux/ceph/ceph_fs.h
include/linux/ceph/messenger.h
include/linux/ceph/osdmap.h
include/linux/clk-provider.h
include/linux/compiler.h
include/linux/compiler_types.h
include/linux/cper.h
include/linux/cpu.h
include/linux/cpufreq.h
include/linux/cpumask.h
include/linux/device-mapper.h
include/linux/dns_resolver.h
include/linux/f2fs_fs.h
include/linux/firmware/imx/sci.h
include/linux/firmware/trusted_foundations.h [new file with mode: 0644]
include/linux/firmware/xlnx-zynqmp.h
include/linux/fsnotify.h
include/linux/fsnotify_backend.h
include/linux/ftrace.h
include/linux/gfp.h
include/linux/hmm.h
include/linux/huge_mm.h
include/linux/hugetlb.h
include/linux/iio/consumer.h
include/linux/ipc_namespace.h
include/linux/irqchip/irq-ixp4xx.h [new file with mode: 0644]
include/linux/kernel.h
include/linux/kthread.h
include/linux/latencytop.h
include/linux/lightnvm.h
include/linux/list.h
include/linux/list_bl.h
include/linux/list_sort.h
include/linux/lockd/bind.h
include/linux/memblock.h
include/linux/memcontrol.h
include/linux/memory.h
include/linux/memory_hotplug.h
include/linux/mfd/altera-sysmgr.h [new file with mode: 0644]
include/linux/mfd/cros_ec.h
include/linux/mfd/cros_ec_commands.h
include/linux/mfd/da9063/core.h
include/linux/mfd/da9063/registers.h
include/linux/mfd/max77620.h
include/linux/mfd/max77650.h [new file with mode: 0644]
include/linux/mfd/stmfx.h [new file with mode: 0644]
include/linux/mfd/syscon/atmel-matrix.h
include/linux/mfd/syscon/atmel-mc.h
include/linux/mfd/syscon/atmel-smc.h
include/linux/mfd/syscon/atmel-st.h
include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mm.h
include/linux/mm_inline.h
include/linux/mm_types.h
include/linux/mmu_notifier.h
include/linux/mmzone.h
include/linux/module.h
include/linux/msi.h
include/linux/nvme.h
include/linux/overflow.h
include/linux/pagemap.h
include/linux/pci-ecam.h
include/linux/pci-epc.h
include/linux/pci-epf.h
include/linux/pci.h
include/linux/pci_hotplug.h
include/linux/percpu.h
include/linux/platform_data/eth-ep93xx.h [new file with mode: 0644]
include/linux/platform_data/keypad-ep93xx.h
include/linux/platform_data/lm3630a_bl.h
include/linux/platform_data/pm33xx.h
include/linux/platform_data/ti-sysc.h
include/linux/platform_data/timer-ixp4xx.h [new file with mode: 0644]
include/linux/plist.h
include/linux/pm_domain.h
include/linux/poll.h
include/linux/power_supply.h
include/linux/pps-gpio.h
include/linux/printk.h
include/linux/psi.h
include/linux/psi_types.h
include/linux/qcom-geni-se.h
include/linux/reboot.h
include/linux/reset.h
include/linux/rtc/rtc-omap.h [new file with mode: 0644]
include/linux/sched.h
include/linux/sched/signal.h
include/linux/slab_def.h
include/linux/soc/cirrus/ep93xx.h [new file with mode: 0644]
include/linux/soc/ixp4xx/npe.h [new file with mode: 0644]
include/linux/soc/ixp4xx/qmgr.h [new file with mode: 0644]
include/linux/sunrpc/svc.h
include/linux/sunrpc/svc_xprt.h
include/linux/sunrpc/svcsock.h
include/linux/switchtec.h
include/linux/thermal.h
include/linux/ti-emif-sram.h
include/linux/tracepoint.h
include/linux/userfaultfd_k.h
include/linux/virtio.h
include/linux/vmstat.h
include/linux/wait_bit.h
include/media/davinci/vpbe.h
include/net/af_rxrpc.h
include/net/dsa.h
include/trace/define_trace.h
include/trace/events/compaction.h
include/trace/events/f2fs.h
include/trace/events/rcu.h
include/trace/events/sched.h
include/trace/events/vmscan.h
include/trace/events/writeback.h
include/uapi/linux/bpf.h
include/uapi/linux/fs.h
include/uapi/linux/fuse.h
include/uapi/linux/input-event-codes.h
include/uapi/linux/netfilter/nf_tables.h
include/uapi/linux/nfsd/cld.h
include/uapi/linux/pci_regs.h
include/uapi/linux/switchtec_ioctl.h
include/uapi/rdma/rdma_netlink.h
init/Kconfig
init/initramfs.c
init/main.c
ipc/ipc_sysctl.c
ipc/mqueue.c
ipc/msgutil.c
ipc/util.c
ipc/util.h
kernel/Makefile
kernel/bpf/core.c
kernel/bpf/verifier.c
kernel/cgroup/cgroup.c
kernel/compat.c
kernel/debug/gdbstub.c
kernel/debug/kdb/Makefile
kernel/debug/kdb/kdb_io.c
kernel/debug/kdb/kdb_main.c
kernel/debug/kdb/kdb_support.c
kernel/events/uprobes.c
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/gcov/Kconfig
kernel/gcov/Makefile
kernel/gcov/base.c
kernel/gcov/clang.c [new file with mode: 0644]
kernel/gcov/gcc_3_4.c
kernel/gcov/gcc_4_7.c
kernel/gcov/gcc_base.c [new file with mode: 0644]
kernel/gcov/gcov.h
kernel/kexec_file.c
kernel/kthread.c
kernel/latencytop.c
kernel/livepatch/core.c
kernel/locking/rwsem-xadd.c
kernel/memremap.c
kernel/module-internal.h
kernel/module.c
kernel/notifier.c
kernel/panic.c
kernel/pid.c
kernel/printk/printk.c
kernel/rcu/rcu.h
kernel/rcu/tree.c
kernel/reboot.c
kernel/sched/psi.c
kernel/signal.c
kernel/sys.c
kernel/sysctl.c
kernel/time/ntp.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/ring_buffer_benchmark.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_events.c
kernel/trace/trace_events_filter.c
kernel/trace/trace_events_hist.c
kernel/trace/trace_events_trigger.c
kernel/trace/trace_kdb.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_probe.c
kernel/trace/trace_probe.h
kernel/trace/trace_probe_tmpl.h
kernel/trace/trace_selftest.c
kernel/trace/trace_uprobe.c
kernel/user.c
lib/Kconfig
lib/Kconfig.debug
lib/Makefile
lib/bitmap.c
lib/cordic.c [deleted file]
lib/div64.c [deleted file]
lib/gcd.c [deleted file]
lib/hweight.c
lib/int_sqrt.c [deleted file]
lib/iov_iter.c
lib/lcm.c [deleted file]
lib/list_sort.c
lib/math/Kconfig [new file with mode: 0644]
lib/math/Makefile [new file with mode: 0644]
lib/math/cordic.c [new file with mode: 0644]
lib/math/div64.c [new file with mode: 0644]
lib/math/gcd.c [new file with mode: 0644]
lib/math/int_pow.c [new file with mode: 0644]
lib/math/int_sqrt.c [new file with mode: 0644]
lib/math/lcm.c [new file with mode: 0644]
lib/math/prime_numbers.c [new file with mode: 0644]
lib/math/rational.c [new file with mode: 0644]
lib/math/reciprocal_div.c [new file with mode: 0644]
lib/plist.c
lib/prime_numbers.c [deleted file]
lib/rational.c [deleted file]
lib/reciprocal_div.c [deleted file]
lib/sort.c
lib/test_bitmap.c
lib/test_sysctl.c
lib/test_vmalloc.c
mm/Kconfig
mm/Kconfig.debug
mm/Makefile
mm/cma.c
mm/cma_debug.c
mm/compaction.c
mm/debug.c
mm/filemap.c
mm/gup.c
mm/gup_benchmark.c
mm/hmm.c
mm/huge_memory.c
mm/hugetlb.c
mm/khugepaged.c
mm/ksm.c
mm/madvise.c
mm/memblock.c
mm/memcontrol.c
mm/memfd.c
mm/memory.c
mm/memory_hotplug.c
mm/migrate.c
mm/mincore.c
mm/mmu_notifier.c
mm/mprotect.c
mm/mremap.c
mm/nommu.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/page_isolation.c
mm/percpu-internal.h
mm/percpu-km.c
mm/percpu-stats.c
mm/percpu.c
mm/rmap.c
mm/shmem.c
mm/shuffle.c [new file with mode: 0644]
mm/shuffle.h [new file with mode: 0644]
mm/slab.c
mm/slob.c
mm/slub.c
mm/sparse.c
mm/swap.c
mm/swap_state.c
mm/userfaultfd.c
mm/util.c
mm/vmalloc.c
mm/vmscan.c
mm/workingset.c
mm/z3fold.c
net/bridge/br_if.c
net/bridge/netfilter/ebtables.c
net/ceph/cls_lock_client.c
net/ceph/debugfs.c
net/ceph/messenger.c
net/ceph/mon_client.c
net/ceph/osd_client.c
net/ceph/pagevec.c
net/core/flow_dissector.c
net/dccp/proto.c
net/dns_resolver/dns_query.c
net/dsa/slave.c
net/dsa/tag_brcm.c
net/netfilter/core.c
net/netfilter/nf_conntrack_h323_asn1.c
net/netfilter/nf_conntrack_h323_main.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_flow_table_ip.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_flow_offload.c
net/qrtr/qrtr.c
net/rds/info.c
net/rds/rdma.c
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/call_object.c
net/rxrpc/conn_client.c
net/rxrpc/sendmsg.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/cache.c
net/sunrpc/svc.c
net/sunrpc/svc_xprt.c
net/sunrpc/svcauth_unix.c
net/sunrpc/svcsock.c
net/xdp/xdp_umem.c
samples/vfs/.gitignore [new file with mode: 0644]
scripts/bpf_helpers_doc.py
scripts/gcc-plugins/arm_ssp_per_task_plugin.c
scripts/gdb/linux/clk.py [new file with mode: 0644]
scripts/gdb/linux/config.py [new file with mode: 0644]
scripts/gdb/linux/constants.py.in
scripts/gdb/linux/cpus.py
scripts/gdb/linux/lists.py
scripts/gdb/linux/proc.py
scripts/gdb/linux/rbtree.py [new file with mode: 0644]
scripts/gdb/linux/symbols.py
scripts/gdb/linux/tasks.py
scripts/gdb/linux/timerlist.py [new file with mode: 0644]
scripts/gdb/linux/utils.py
scripts/gdb/vmlinux-gdb.py
scripts/kconfig/confdata.c
scripts/kconfig/gconf.c
scripts/kconfig/lexer.l
scripts/kconfig/lkc.h
scripts/kconfig/lxdialog/BIG.FAT.WARNING
scripts/kconfig/mconf.c
scripts/kconfig/nconf-cfg.sh [changed mode: 0644->0755]
scripts/kconfig/nconf.c
security/selinux/hooks.c
sound/soc/cirrus/edb93xx.c
sound/soc/cirrus/ep93xx-ac97.c
sound/soc/cirrus/ep93xx-i2s.c
sound/soc/cirrus/simone.c
sound/soc/cirrus/snappercl15.c
sound/soc/mxs/mxs-saif.c
tools/include/uapi/linux/bpf.h
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf_internal.h [new file with mode: 0644]
tools/lib/bpf/libbpf_probes.c
tools/objtool/Documentation/stack-validation.txt
tools/objtool/check.c
tools/pci/Makefile
tools/pci/pcitest.c
tools/power/x86/turbostat/Makefile
tools/power/x86/x86_energy_perf_policy/Makefile
tools/testing/ktest/ktest.pl
tools/testing/ktest/sample.conf
tools/testing/nvdimm/Kbuild
tools/testing/nvdimm/dax_pmem_compat_test.c [new file with mode: 0644]
tools/testing/nvdimm/dax_pmem_core_test.c [new file with mode: 0644]
tools/testing/nvdimm/dax_pmem_test.c [new file with mode: 0644]
tools/testing/nvdimm/test/nfit.c
tools/testing/nvdimm/watermark.h
tools/testing/selftests/.gitignore
tools/testing/selftests/Makefile
tools/testing/selftests/bpf/.gitignore
tools/testing/selftests/bpf/verifier/jump.c
tools/testing/selftests/breakpoints/breakpoint_test.c
tools/testing/selftests/breakpoints/breakpoint_test_arm64.c
tools/testing/selftests/breakpoints/step_after_suspend_test.c
tools/testing/selftests/capabilities/test_execve.c
tools/testing/selftests/drivers/.gitignore [new file with mode: 0644]
tools/testing/selftests/exec/.gitignore
tools/testing/selftests/exec/Makefile
tools/testing/selftests/exec/recursion-depth.c [new file with mode: 0644]
tools/testing/selftests/ftrace/test.d/ftrace/tracing-error-log.tc [new file with mode: 0644]
tools/testing/selftests/ftrace/test.d/functions
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc [new file with mode: 0644]
tools/testing/selftests/ftrace/test.d/kprobe/uprobe_syntax_errors.tc [new file with mode: 0644]
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-extended-error-support.tc [deleted file]
tools/testing/selftests/futex/functional/futex_requeue_pi.c
tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c
tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
tools/testing/selftests/futex/functional/futex_wait_timeout.c
tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
tools/testing/selftests/kselftest.h
tools/testing/selftests/kselftest/prefix.pl [new file with mode: 0755]
tools/testing/selftests/kselftest/runner.sh [new file with mode: 0644]
tools/testing/selftests/lib.mk
tools/testing/selftests/membarrier/membarrier_test.c
tools/testing/selftests/pidfd/.gitignore [new file with mode: 0644]
tools/testing/selftests/pidfd/pidfd_test.c
tools/testing/selftests/rseq/Makefile
tools/testing/selftests/rseq/rseq-arm.h
tools/testing/selftests/rseq/rseq-arm64.h
tools/testing/selftests/rseq/rseq-mips.h
tools/testing/selftests/rseq/rseq-ppc.h
tools/testing/selftests/rseq/rseq-s390.h
tools/testing/selftests/rseq/rseq-x86.h
tools/testing/selftests/rseq/rseq.c
tools/testing/selftests/rseq/rseq.h
tools/testing/selftests/sigaltstack/sas.c
tools/testing/selftests/sync/sync_test.c
tools/testing/selftests/sysctl/sysctl.sh
tools/virtio/ringtest/ptr_ring.c
virt/kvm/kvm_main.c

index 5e23e22..b77e30b 100644 (file)
@@ -114,15 +114,60 @@ Description:
                Access: Read
                Valid values: Represented in microamps
 
+What:          /sys/class/power_supply/<supply_name>/charge_control_limit
+Date:          Oct 2012
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Maximum allowable charging current. Used for charge rate
+               throttling for thermal cooling or improving battery health.
+
+               Access: Read, Write
+               Valid values: Represented in microamps
+
+What:          /sys/class/power_supply/<supply_name>/charge_control_limit_max
+Date:          Oct 2012
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Maximum legal value for the charge_control_limit property.
+
+               Access: Read
+               Valid values: Represented in microamps
+
+What:          /sys/class/power_supply/<supply_name>/charge_control_start_threshold
+Date:          April 2019
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Represents a battery percentage level, below which charging will
+               begin.
+
+               Access: Read, Write
+               Valid values: 0 - 100 (percent)
+
+What:          /sys/class/power_supply/<supply_name>/charge_control_end_threshold
+Date:          April 2019
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Represents a battery percentage level, above which charging will
+               stop.
+
+               Access: Read, Write
+               Valid values: 0 - 100 (percent)
+
 What:          /sys/class/power_supply/<supply_name>/charge_type
 Date:          July 2009
 Contact:       linux-pm@vger.kernel.org
 Description:
                Represents the type of charging currently being applied to the
-               battery.
+               battery. "Trickle", "Fast", and "Standard" all mean different
+               charging speeds. "Adaptive" means that the charger uses some
+               algorithm to adjust the charge rate dynamically, without
+               any user configuration required. "Custom" means that the charger
+               uses the charge_control_* properties as configuration for some
+               different algorithm.
 
-               Access: Read
-               Valid values: "Unknown", "N/A", "Trickle", "Fast"
+               Access: Read, Write
+               Valid values: "Unknown", "N/A", "Trickle", "Fast", "Standard",
+                             "Adaptive", "Custom"
 
 What:          /sys/class/power_supply/<supply_name>/charge_term_current
 Date:          July 2014
index 4fb76c0..1528239 100644 (file)
@@ -484,6 +484,7 @@ What:               /sys/devices/system/cpu/vulnerabilities
                /sys/devices/system/cpu/vulnerabilities/spectre_v2
                /sys/devices/system/cpu/vulnerabilities/spec_store_bypass
                /sys/devices/system/cpu/vulnerabilities/l1tf
+               /sys/devices/system/cpu/vulnerabilities/mds
 Date:          January 2018
 Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
 Description:   Information about CPU vulnerabilities
@@ -496,8 +497,7 @@ Description:        Information about CPU vulnerabilities
                "Vulnerable"      CPU is affected and no mitigation in effect
                "Mitigation: $M"  CPU is affected and mitigation $M is in effect
 
-               Details about the l1tf file can be found in
-               Documentation/admin-guide/l1tf.rst
+               See also: Documentation/admin-guide/hw-vuln/index.rst
 
 What:          /sys/devices/system/cpu/smt
                /sys/devices/system/cpu/smt/active
index 7e71c9c..5cbe565 100644 (file)
@@ -63,6 +63,110 @@ as well as medium and long term trends. The total absolute stall time
 spikes which wouldn't necessarily make a dent in the time averages,
 or to average trends over custom time frames.
 
+Monitoring for pressure thresholds
+==================================
+
+Users can register triggers and use poll() to be woken up when resource
+pressure exceeds certain thresholds.
+
+A trigger describes the maximum cumulative stall time over a specific
+time window, e.g. 100ms of total stall time within any 500ms window to
+generate a wakeup event.
+
+To register a trigger user has to open psi interface file under
+/proc/pressure/ representing the resource to be monitored and write the
+desired threshold and time window. The open file descriptor should be
+used to wait for trigger events using select(), poll() or epoll().
+The following format is used:
+
+<some|full> <stall amount in us> <time window in us>
+
+For example writing "some 150000 1000000" into /proc/pressure/memory
+would add 150ms threshold for partial memory stall measured within
+1sec time window. Writing "full 50000 1000000" into /proc/pressure/io
+would add 50ms threshold for full io stall measured within 1sec time window.
+
+Triggers can be set on more than one psi metric and more than one trigger
+for the same psi metric can be specified. However for each trigger a separate
+file descriptor is required to be able to poll it separately from others,
+therefore for each trigger a separate open() syscall should be made even
+when opening the same psi interface file.
+
+Monitors activate only when system enters stall state for the monitored
+psi metric and deactivates upon exit from the stall state. While system is
+in the stall state psi signal growth is monitored at a rate of 10 times per
+tracking window.
+
+The kernel accepts window sizes ranging from 500ms to 10s, therefore min
+monitoring update interval is 50ms and max is 1s. Min limit is set to
+prevent overly frequent polling. Max limit is chosen as a high enough number
+after which monitors are most likely not needed and psi averages can be used
+instead.
+
+When activated, psi monitor stays active for at least the duration of one
+tracking window to avoid repeated activations/deactivations when system is
+bouncing in and out of the stall state.
+
+Notifications to the userspace are rate-limited to one per tracking window.
+
+The trigger will de-register when the file descriptor used to define the
+trigger  is closed.
+
+Userspace monitor usage example
+===============================
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <poll.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * Monitor memory partial stall with 1s tracking window size
+ * and 150ms threshold.
+ */
+int main() {
+       const char trig[] = "some 150000 1000000";
+       struct pollfd fds;
+       int n;
+
+       fds.fd = open("/proc/pressure/memory", O_RDWR | O_NONBLOCK);
+       if (fds.fd < 0) {
+               printf("/proc/pressure/memory open error: %s\n",
+                       strerror(errno));
+               return 1;
+       }
+       fds.events = POLLPRI;
+
+       if (write(fds.fd, trig, strlen(trig) + 1) < 0) {
+               printf("/proc/pressure/memory write error: %s\n",
+                       strerror(errno));
+               return 1;
+       }
+
+       printf("waiting for events...\n");
+       while (1) {
+               n = poll(&fds, 1, -1);
+               if (n < 0) {
+                       printf("poll error: %s\n", strerror(errno));
+                       return 1;
+               }
+               if (fds.revents & POLLERR) {
+                       printf("got POLLERR, event source is gone\n");
+                       return 0;
+               }
+               if (fds.revents & POLLPRI) {
+                       printf("event triggered!\n");
+               } else {
+                       printf("unknown event received: 0x%x\n", fds.revents);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
 Cgroup2 interface
 =================
 
@@ -71,3 +175,6 @@ mounted, pressure stall information is also tracked for tasks grouped
 into cgroups. Each subdirectory in the cgroupfs mountpoint contains
 cpu.pressure, memory.pressure, and io.pressure files; the format is
 the same as the /proc/pressure/ files.
+
+Per-cgroup psi monitors can be specified and used the same way as
+system-wide ones.
diff --git a/Documentation/admin-guide/hw-vuln/index.rst b/Documentation/admin-guide/hw-vuln/index.rst
new file mode 100644 (file)
index 0000000..ffc064c
--- /dev/null
@@ -0,0 +1,13 @@
+========================
+Hardware vulnerabilities
+========================
+
+This section describes CPU vulnerabilities and provides an overview of the
+possible mitigations along with guidance for selecting mitigations if they
+are configurable at compile, boot or run time.
+
+.. toctree::
+   :maxdepth: 1
+
+   l1tf
+   mds
diff --git a/Documentation/admin-guide/hw-vuln/l1tf.rst b/Documentation/admin-guide/hw-vuln/l1tf.rst
new file mode 100644 (file)
index 0000000..31653a9
--- /dev/null
@@ -0,0 +1,615 @@
+L1TF - L1 Terminal Fault
+========================
+
+L1 Terminal Fault is a hardware vulnerability which allows unprivileged
+speculative access to data which is available in the Level 1 Data Cache
+when the page table entry controlling the virtual address, which is used
+for the access, has the Present bit cleared or other reserved bits set.
+
+Affected processors
+-------------------
+
+This vulnerability affects a wide range of Intel processors. The
+vulnerability is not present on:
+
+   - Processors from AMD, Centaur and other non Intel vendors
+
+   - Older processor models, where the CPU family is < 6
+
+   - A range of Intel ATOM processors (Cedarview, Cloverview, Lincroft,
+     Penwell, Pineview, Silvermont, Airmont, Merrifield)
+
+   - The Intel XEON PHI family
+
+   - Intel processors which have the ARCH_CAP_RDCL_NO bit set in the
+     IA32_ARCH_CAPABILITIES MSR. If the bit is set the CPU is not affected
+     by the Meltdown vulnerability either. These CPUs should become
+     available by end of 2018.
+
+Whether a processor is affected or not can be read out from the L1TF
+vulnerability file in sysfs. See :ref:`l1tf_sys_info`.
+
+Related CVEs
+------------
+
+The following CVE entries are related to the L1TF vulnerability:
+
+   =============  =================  ==============================
+   CVE-2018-3615  L1 Terminal Fault  SGX related aspects
+   CVE-2018-3620  L1 Terminal Fault  OS, SMM related aspects
+   CVE-2018-3646  L1 Terminal Fault  Virtualization related aspects
+   =============  =================  ==============================
+
+Problem
+-------
+
+If an instruction accesses a virtual address for which the relevant page
+table entry (PTE) has the Present bit cleared or other reserved bits set,
+then speculative execution ignores the invalid PTE and loads the referenced
+data if it is present in the Level 1 Data Cache, as if the page referenced
+by the address bits in the PTE was still present and accessible.
+
+While this is a purely speculative mechanism and the instruction will raise
+a page fault when it is retired eventually, the pure act of loading the
+data and making it available to other speculative instructions opens up the
+opportunity for side channel attacks to unprivileged malicious code,
+similar to the Meltdown attack.
+
+While Meltdown breaks the user space to kernel space protection, L1TF
+allows to attack any physical memory address in the system and the attack
+works across all protection domains. It allows an attack of SGX and also
+works from inside virtual machines because the speculation bypasses the
+extended page table (EPT) protection mechanism.
+
+
+Attack scenarios
+----------------
+
+1. Malicious user space
+^^^^^^^^^^^^^^^^^^^^^^^
+
+   Operating Systems store arbitrary information in the address bits of a
+   PTE which is marked non present. This allows a malicious user space
+   application to attack the physical memory to which these PTEs resolve.
+   In some cases user-space can maliciously influence the information
+   encoded in the address bits of the PTE, thus making attacks more
+   deterministic and more practical.
+
+   The Linux kernel contains a mitigation for this attack vector, PTE
+   inversion, which is permanently enabled and has no performance
+   impact. The kernel ensures that the address bits of PTEs, which are not
+   marked present, never point to cacheable physical memory space.
+
+   A system with an up to date kernel is protected against attacks from
+   malicious user space applications.
+
+2. Malicious guest in a virtual machine
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+   The fact that L1TF breaks all domain protections allows malicious guest
+   OSes, which can control the PTEs directly, and malicious guest user
+   space applications, which run on an unprotected guest kernel lacking the
+   PTE inversion mitigation for L1TF, to attack physical host memory.
+
+   A special aspect of L1TF in the context of virtualization is symmetric
+   multi threading (SMT). The Intel implementation of SMT is called
+   HyperThreading. The fact that Hyperthreads on the affected processors
+   share the L1 Data Cache (L1D) is important for this. As the flaw allows
+   only to attack data which is present in L1D, a malicious guest running
+   on one Hyperthread can attack the data which is brought into the L1D by
+   the context which runs on the sibling Hyperthread of the same physical
+   core. This context can be host OS, host user space or a different guest.
+
+   If the processor does not support Extended Page Tables, the attack is
+   only possible, when the hypervisor does not sanitize the content of the
+   effective (shadow) page tables.
+
+   While solutions exist to mitigate these attack vectors fully, these
+   mitigations are not enabled by default in the Linux kernel because they
+   can affect performance significantly. The kernel provides several
+   mechanisms which can be utilized to address the problem depending on the
+   deployment scenario. The mitigations, their protection scope and impact
+   are described in the next sections.
+
+   The default mitigations and the rationale for choosing them are explained
+   at the end of this document. See :ref:`default_mitigations`.
+
+.. _l1tf_sys_info:
+
+L1TF system information
+-----------------------
+
+The Linux kernel provides a sysfs interface to enumerate the current L1TF
+status of the system: whether the system is vulnerable, and which
+mitigations are active. The relevant sysfs file is:
+
+/sys/devices/system/cpu/vulnerabilities/l1tf
+
+The possible values in this file are:
+
+  ===========================   ===============================
+  'Not affected'               The processor is not vulnerable
+  'Mitigation: PTE Inversion'  The host protection is active
+  ===========================   ===============================
+
+If KVM/VMX is enabled and the processor is vulnerable then the following
+information is appended to the 'Mitigation: PTE Inversion' part:
+
+  - SMT status:
+
+    =====================  ================
+    'VMX: SMT vulnerable'  SMT is enabled
+    'VMX: SMT disabled'    SMT is disabled
+    =====================  ================
+
+  - L1D Flush mode:
+
+    ================================  ====================================
+    'L1D vulnerable'                 L1D flushing is disabled
+
+    'L1D conditional cache flushes'   L1D flush is conditionally enabled
+
+    'L1D cache flushes'                      L1D flush is unconditionally enabled
+    ================================  ====================================
+
+The resulting grade of protection is discussed in the following sections.
+
+
+Host mitigation mechanism
+-------------------------
+
+The kernel is unconditionally protected against L1TF attacks from malicious
+user space running on the host.
+
+
+Guest mitigation mechanisms
+---------------------------
+
+.. _l1d_flush:
+
+1. L1D flush on VMENTER
+^^^^^^^^^^^^^^^^^^^^^^^
+
+   To make sure that a guest cannot attack data which is present in the L1D
+   the hypervisor flushes the L1D before entering the guest.
+
+   Flushing the L1D evicts not only the data which should not be accessed
+   by a potentially malicious guest, it also flushes the guest
+   data. Flushing the L1D has a performance impact as the processor has to
+   bring the flushed guest data back into the L1D. Depending on the
+   frequency of VMEXIT/VMENTER and the type of computations in the guest
+   performance degradation in the range of 1% to 50% has been observed. For
+   scenarios where guest VMEXIT/VMENTER are rare the performance impact is
+   minimal. Virtio and mechanisms like posted interrupts are designed to
+   confine the VMEXITs to a bare minimum, but specific configurations and
+   application scenarios might still suffer from a high VMEXIT rate.
+
+   The kernel provides two L1D flush modes:
+    - conditional ('cond')
+    - unconditional ('always')
+
+   The conditional mode avoids L1D flushing after VMEXITs which execute
+   only audited code paths before the corresponding VMENTER. These code
+   paths have been verified that they cannot expose secrets or other
+   interesting data to an attacker, but they can leak information about the
+   address space layout of the hypervisor.
+
+   Unconditional mode flushes L1D on all VMENTER invocations and provides
+   maximum protection. It has a higher overhead than the conditional
+   mode. The overhead cannot be quantified correctly as it depends on the
+   workload scenario and the resulting number of VMEXITs.
+
+   The general recommendation is to enable L1D flush on VMENTER. The kernel
+   defaults to conditional mode on affected processors.
+
+   **Note**, that L1D flush does not prevent the SMT problem because the
+   sibling thread will also bring back its data into the L1D which makes it
+   attackable again.
+
+   L1D flush can be controlled by the administrator via the kernel command
+   line and sysfs control files. See :ref:`mitigation_control_command_line`
+   and :ref:`mitigation_control_kvm`.
+
+.. _guest_confinement:
+
+2. Guest VCPU confinement to dedicated physical cores
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+   To address the SMT problem, it is possible to make a guest or a group of
+   guests affine to one or more physical cores. The proper mechanism for
+   that is to utilize exclusive cpusets to ensure that no other guest or
+   host tasks can run on these cores.
+
+   If only a single guest or related guests run on sibling SMT threads on
+   the same physical core then they can only attack their own memory and
+   restricted parts of the host memory.
+
+   Host memory is attackable, when one of the sibling SMT threads runs in
+   host OS (hypervisor) context and the other in guest context. The amount
+   of valuable information from the host OS context depends on the context
+   which the host OS executes, i.e. interrupts, soft interrupts and kernel
+   threads. The amount of valuable data from these contexts cannot be
+   declared as non-interesting for an attacker without deep inspection of
+   the code.
+
+   **Note**, that assigning guests to a fixed set of physical cores affects
+   the ability of the scheduler to do load balancing and might have
+   negative effects on CPU utilization depending on the hosting
+   scenario. Disabling SMT might be a viable alternative for particular
+   scenarios.
+
+   For further information about confining guests to a single or to a group
+   of cores consult the cpusets documentation:
+
+   https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt
+
+.. _interrupt_isolation:
+
+3. Interrupt affinity
+^^^^^^^^^^^^^^^^^^^^^
+
+   Interrupts can be made affine to logical CPUs. This is not universally
+   true because there are types of interrupts which are truly per CPU
+   interrupts, e.g. the local timer interrupt. Aside of that multi queue
+   devices affine their interrupts to single CPUs or groups of CPUs per
+   queue without allowing the administrator to control the affinities.
+
+   Moving the interrupts, which can be affinity controlled, away from CPUs
+   which run untrusted guests, reduces the attack vector space.
+
+   Whether the interrupts with are affine to CPUs, which run untrusted
+   guests, provide interesting data for an attacker depends on the system
+   configuration and the scenarios which run on the system. While for some
+   of the interrupts it can be assumed that they won't expose interesting
+   information beyond exposing hints about the host OS memory layout, there
+   is no way to make general assumptions.
+
+   Interrupt affinity can be controlled by the administrator via the
+   /proc/irq/$NR/smp_affinity[_list] files. Limited documentation is
+   available at:
+
+   https://www.kernel.org/doc/Documentation/IRQ-affinity.txt
+
+.. _smt_control:
+
+4. SMT control
+^^^^^^^^^^^^^^
+
+   To prevent the SMT issues of L1TF it might be necessary to disable SMT
+   completely. Disabling SMT can have a significant performance impact, but
+   the impact depends on the hosting scenario and the type of workloads.
+   The impact of disabling SMT needs also to be weighted against the impact
+   of other mitigation solutions like confining guests to dedicated cores.
+
+   The kernel provides a sysfs interface to retrieve the status of SMT and
+   to control it. It also provides a kernel command line interface to
+   control SMT.
+
+   The kernel command line interface consists of the following options:
+
+     =========== ==========================================================
+     nosmt      Affects the bring up of the secondary CPUs during boot. The
+                kernel tries to bring all present CPUs online during the
+                boot process. "nosmt" makes sure that from each physical
+                core only one - the so called primary (hyper) thread is
+                activated. Due to a design flaw of Intel processors related
+                to Machine Check Exceptions the non primary siblings have
+                to be brought up at least partially and are then shut down
+                again.  "nosmt" can be undone via the sysfs interface.
+
+     nosmt=force Has the same effect as "nosmt" but it does not allow to
+                undo the SMT disable via the sysfs interface.
+     =========== ==========================================================
+
+   The sysfs interface provides two files:
+
+   - /sys/devices/system/cpu/smt/control
+   - /sys/devices/system/cpu/smt/active
+
+   /sys/devices/system/cpu/smt/control:
+
+     This file allows to read out the SMT control state and provides the
+     ability to disable or (re)enable SMT. The possible states are:
+
+       ==============  ===================================================
+       on              SMT is supported by the CPU and enabled. All
+                       logical CPUs can be onlined and offlined without
+                       restrictions.
+
+       off             SMT is supported by the CPU and disabled. Only
+                       the so called primary SMT threads can be onlined
+                       and offlined without restrictions. An attempt to
+                       online a non-primary sibling is rejected
+
+       forceoff        Same as 'off' but the state cannot be controlled.
+                       Attempts to write to the control file are rejected.
+
+       notsupported    The processor does not support SMT. It's therefore
+                       not affected by the SMT implications of L1TF.
+                       Attempts to write to the control file are rejected.
+       ==============  ===================================================
+
+     The possible states which can be written into this file to control SMT
+     state are:
+
+     - on
+     - off
+     - forceoff
+
+   /sys/devices/system/cpu/smt/active:
+
+     This file reports whether SMT is enabled and active, i.e. if on any
+     physical core two or more sibling threads are online.
+
+   SMT control is also possible at boot time via the l1tf kernel command
+   line parameter in combination with L1D flush control. See
+   :ref:`mitigation_control_command_line`.
+
+5. Disabling EPT
+^^^^^^^^^^^^^^^^
+
+  Disabling EPT for virtual machines provides full mitigation for L1TF even
+  with SMT enabled, because the effective page tables for guests are
+  managed and sanitized by the hypervisor. Though disabling EPT has a
+  significant performance impact especially when the Meltdown mitigation
+  KPTI is enabled.
+
+  EPT can be disabled in the hypervisor via the 'kvm-intel.ept' parameter.
+
+There is ongoing research and development for new mitigation mechanisms to
+address the performance impact of disabling SMT or EPT.
+
+.. _mitigation_control_command_line:
+
+Mitigation control on the kernel command line
+---------------------------------------------
+
+The kernel command line allows to control the L1TF mitigations at boot
+time with the option "l1tf=". The valid arguments for this option are:
+
+  ============  =============================================================
+  full         Provides all available mitigations for the L1TF
+               vulnerability. Disables SMT and enables all mitigations in
+               the hypervisors, i.e. unconditional L1D flushing
+
+               SMT control and L1D flush control via the sysfs interface
+               is still possible after boot.  Hypervisors will issue a
+               warning when the first VM is started in a potentially
+               insecure configuration, i.e. SMT enabled or L1D flush
+               disabled.
+
+  full,force   Same as 'full', but disables SMT and L1D flush runtime
+               control. Implies the 'nosmt=force' command line option.
+               (i.e. sysfs control of SMT is disabled.)
+
+  flush                Leaves SMT enabled and enables the default hypervisor
+               mitigation, i.e. conditional L1D flushing
+
+               SMT control and L1D flush control via the sysfs interface
+               is still possible after boot.  Hypervisors will issue a
+               warning when the first VM is started in a potentially
+               insecure configuration, i.e. SMT enabled or L1D flush
+               disabled.
+
+  flush,nosmt  Disables SMT and enables the default hypervisor mitigation,
+               i.e. conditional L1D flushing.
+
+               SMT control and L1D flush control via the sysfs interface
+               is still possible after boot.  Hypervisors will issue a
+               warning when the first VM is started in a potentially
+               insecure configuration, i.e. SMT enabled or L1D flush
+               disabled.
+
+  flush,nowarn Same as 'flush', but hypervisors will not warn when a VM is
+               started in a potentially insecure configuration.
+
+  off          Disables hypervisor mitigations and doesn't emit any
+               warnings.
+               It also drops the swap size and available RAM limit restrictions
+               on both hypervisor and bare metal.
+
+  ============  =============================================================
+
+The default is 'flush'. For details about L1D flushing see :ref:`l1d_flush`.
+
+
+.. _mitigation_control_kvm:
+
+Mitigation control for KVM - module parameter
+-------------------------------------------------------------
+
+The KVM hypervisor mitigation mechanism, flushing the L1D cache when
+entering a guest, can be controlled with a module parameter.
+
+The option/parameter is "kvm-intel.vmentry_l1d_flush=". It takes the
+following arguments:
+
+  ============  ==============================================================
+  always       L1D cache flush on every VMENTER.
+
+  cond         Flush L1D on VMENTER only when the code between VMEXIT and
+               VMENTER can leak host memory which is considered
+               interesting for an attacker. This still can leak host memory
+               which allows e.g. to determine the hosts address space layout.
+
+  never                Disables the mitigation
+  ============  ==============================================================
+
+The parameter can be provided on the kernel command line, as a module
+parameter when loading the modules and at runtime modified via the sysfs
+file:
+
+/sys/module/kvm_intel/parameters/vmentry_l1d_flush
+
+The default is 'cond'. If 'l1tf=full,force' is given on the kernel command
+line, then 'always' is enforced and the kvm-intel.vmentry_l1d_flush
+module parameter is ignored and writes to the sysfs file are rejected.
+
+.. _mitigation_selection:
+
+Mitigation selection guide
+--------------------------
+
+1. No virtualization in use
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+   The system is protected by the kernel unconditionally and no further
+   action is required.
+
+2. Virtualization with trusted guests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+   If the guest comes from a trusted source and the guest OS kernel is
+   guaranteed to have the L1TF mitigations in place the system is fully
+   protected against L1TF and no further action is required.
+
+   To avoid the overhead of the default L1D flushing on VMENTER the
+   administrator can disable the flushing via the kernel command line and
+   sysfs control files. See :ref:`mitigation_control_command_line` and
+   :ref:`mitigation_control_kvm`.
+
+
+3. Virtualization with untrusted guests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+3.1. SMT not supported or disabled
+""""""""""""""""""""""""""""""""""
+
+  If SMT is not supported by the processor or disabled in the BIOS or by
+  the kernel, it's only required to enforce L1D flushing on VMENTER.
+
+  Conditional L1D flushing is the default behaviour and can be tuned. See
+  :ref:`mitigation_control_command_line` and :ref:`mitigation_control_kvm`.
+
+3.2. EPT not supported or disabled
+""""""""""""""""""""""""""""""""""
+
+  If EPT is not supported by the processor or disabled in the hypervisor,
+  the system is fully protected. SMT can stay enabled and L1D flushing on
+  VMENTER is not required.
+
+  EPT can be disabled in the hypervisor via the 'kvm-intel.ept' parameter.
+
+3.3. SMT and EPT supported and active
+"""""""""""""""""""""""""""""""""""""
+
+  If SMT and EPT are supported and active then various degrees of
+  mitigations can be employed:
+
+  - L1D flushing on VMENTER:
+
+    L1D flushing on VMENTER is the minimal protection requirement, but it
+    is only potent in combination with other mitigation methods.
+
+    Conditional L1D flushing is the default behaviour and can be tuned. See
+    :ref:`mitigation_control_command_line` and :ref:`mitigation_control_kvm`.
+
+  - Guest confinement:
+
+    Confinement of guests to a single or a group of physical cores which
+    are not running any other processes, can reduce the attack surface
+    significantly, but interrupts, soft interrupts and kernel threads can
+    still expose valuable data to a potential attacker. See
+    :ref:`guest_confinement`.
+
+  - Interrupt isolation:
+
+    Isolating the guest CPUs from interrupts can reduce the attack surface
+    further, but still allows a malicious guest to explore a limited amount
+    of host physical memory. This can at least be used to gain knowledge
+    about the host address space layout. The interrupts which have a fixed
+    affinity to the CPUs which run the untrusted guests can depending on
+    the scenario still trigger soft interrupts and schedule kernel threads
+    which might expose valuable information. See
+    :ref:`interrupt_isolation`.
+
+The above three mitigation methods combined can provide protection to a
+certain degree, but the risk of the remaining attack surface has to be
+carefully analyzed. For full protection the following methods are
+available:
+
+  - Disabling SMT:
+
+    Disabling SMT and enforcing the L1D flushing provides the maximum
+    amount of protection. This mitigation is not depending on any of the
+    above mitigation methods.
+
+    SMT control and L1D flushing can be tuned by the command line
+    parameters 'nosmt', 'l1tf', 'kvm-intel.vmentry_l1d_flush' and at run
+    time with the matching sysfs control files. See :ref:`smt_control`,
+    :ref:`mitigation_control_command_line` and
+    :ref:`mitigation_control_kvm`.
+
+  - Disabling EPT:
+
+    Disabling EPT provides the maximum amount of protection as well. It is
+    not depending on any of the above mitigation methods. SMT can stay
+    enabled and L1D flushing is not required, but the performance impact is
+    significant.
+
+    EPT can be disabled in the hypervisor via the 'kvm-intel.ept'
+    parameter.
+
+3.4. Nested virtual machines
+""""""""""""""""""""""""""""
+
+When nested virtualization is in use, three operating systems are involved:
+the bare metal hypervisor, the nested hypervisor and the nested virtual
+machine.  VMENTER operations from the nested hypervisor into the nested
+guest will always be processed by the bare metal hypervisor. If KVM is the
+bare metal hypervisor it will:
+
+ - Flush the L1D cache on every switch from the nested hypervisor to the
+   nested virtual machine, so that the nested hypervisor's secrets are not
+   exposed to the nested virtual machine;
+
+ - Flush the L1D cache on every switch from the nested virtual machine to
+   the nested hypervisor; this is a complex operation, and flushing the L1D
+   cache avoids that the bare metal hypervisor's secrets are exposed to the
+   nested virtual machine;
+
+ - Instruct the nested hypervisor to not perform any L1D cache flush. This
+   is an optimization to avoid double L1D flushing.
+
+
+.. _default_mitigations:
+
+Default mitigations
+-------------------
+
+  The kernel default mitigations for vulnerable processors are:
+
+  - PTE inversion to protect against malicious user space. This is done
+    unconditionally and cannot be controlled. The swap storage is limited
+    to ~16TB.
+
+  - L1D conditional flushing on VMENTER when EPT is enabled for
+    a guest.
+
+  The kernel does not by default enforce the disabling of SMT, which leaves
+  SMT systems vulnerable when running untrusted guests with EPT enabled.
+
+  The rationale for this choice is:
+
+  - Force disabling SMT can break existing setups, especially with
+    unattended updates.
+
+  - If regular users run untrusted guests on their machine, then L1TF is
+    just an add on to other malware which might be embedded in an untrusted
+    guest, e.g. spam-bots or attacks on the local network.
+
+    There is no technical way to prevent a user from running untrusted code
+    on their machines blindly.
+
+  - It's technically extremely unlikely and from today's knowledge even
+    impossible that L1TF can be exploited via the most popular attack
+    mechanisms like JavaScript because these mechanisms have no way to
+    control PTEs. If this would be possible and not other mitigation would
+    be possible, then the default might be different.
+
+  - The administrators of cloud and hosting setups have to carefully
+    analyze the risk for their scenarios and make the appropriate
+    mitigation choices, which might even vary across their deployed
+    machines and also result in other changes of their overall setup.
+    There is no way for the kernel to provide a sensible default for this
+    kind of scenarios.
diff --git a/Documentation/admin-guide/hw-vuln/mds.rst b/Documentation/admin-guide/hw-vuln/mds.rst
new file mode 100644 (file)
index 0000000..e3a796c
--- /dev/null
@@ -0,0 +1,308 @@
+MDS - Microarchitectural Data Sampling
+======================================
+
+Microarchitectural Data Sampling is a hardware vulnerability which allows
+unprivileged speculative access to data which is available in various CPU
+internal buffers.
+
+Affected processors
+-------------------
+
+This vulnerability affects a wide range of Intel processors. The
+vulnerability is not present on:
+
+   - Processors from AMD, Centaur and other non Intel vendors
+
+   - Older processor models, where the CPU family is < 6
+
+   - Some Atoms (Bonnell, Saltwell, Goldmont, GoldmontPlus)
+
+   - Intel processors which have the ARCH_CAP_MDS_NO bit set in the
+     IA32_ARCH_CAPABILITIES MSR.
+
+Whether a processor is affected or not can be read out from the MDS
+vulnerability file in sysfs. See :ref:`mds_sys_info`.
+
+Not all processors are affected by all variants of MDS, but the mitigation
+is identical for all of them so the kernel treats them as a single
+vulnerability.
+
+Related CVEs
+------------
+
+The following CVE entries are related to the MDS vulnerability:
+
+   ==============  =====  ===================================================
+   CVE-2018-12126  MSBDS  Microarchitectural Store Buffer Data Sampling
+   CVE-2018-12130  MFBDS  Microarchitectural Fill Buffer Data Sampling
+   CVE-2018-12127  MLPDS  Microarchitectural Load Port Data Sampling
+   CVE-2019-11091  MDSUM  Microarchitectural Data Sampling Uncacheable Memory
+   ==============  =====  ===================================================
+
+Problem
+-------
+
+When performing store, load, L1 refill operations, processors write data
+into temporary microarchitectural structures (buffers). The data in the
+buffer can be forwarded to load operations as an optimization.
+
+Under certain conditions, usually a fault/assist caused by a load
+operation, data unrelated to the load memory address can be speculatively
+forwarded from the buffers. Because the load operation causes a fault or
+assist and its result will be discarded, the forwarded data will not cause
+incorrect program execution or state changes. But a malicious operation
+may be able to forward this speculative data to a disclosure gadget which
+allows in turn to infer the value via a cache side channel attack.
+
+Because the buffers are potentially shared between Hyper-Threads cross
+Hyper-Thread attacks are possible.
+
+Deeper technical information is available in the MDS specific x86
+architecture section: :ref:`Documentation/x86/mds.rst <mds>`.
+
+
+Attack scenarios
+----------------
+
+Attacks against the MDS vulnerabilities can be mounted from malicious non
+priviledged user space applications running on hosts or guest. Malicious
+guest OSes can obviously mount attacks as well.
+
+Contrary to other speculation based vulnerabilities the MDS vulnerability
+does not allow the attacker to control the memory target address. As a
+consequence the attacks are purely sampling based, but as demonstrated with
+the TLBleed attack samples can be postprocessed successfully.
+
+Web-Browsers
+^^^^^^^^^^^^
+
+  It's unclear whether attacks through Web-Browsers are possible at
+  all. The exploitation through Java-Script is considered very unlikely,
+  but other widely used web technologies like Webassembly could possibly be
+  abused.
+
+
+.. _mds_sys_info:
+
+MDS system information
+-----------------------
+
+The Linux kernel provides a sysfs interface to enumerate the current MDS
+status of the system: whether the system is vulnerable, and which
+mitigations are active. The relevant sysfs file is:
+
+/sys/devices/system/cpu/vulnerabilities/mds
+
+The possible values in this file are:
+
+  .. list-table::
+
+     * - 'Not affected'
+       - The processor is not vulnerable
+     * - 'Vulnerable'
+       - The processor is vulnerable, but no mitigation enabled
+     * - 'Vulnerable: Clear CPU buffers attempted, no microcode'
+       - The processor is vulnerable but microcode is not updated.
+
+         The mitigation is enabled on a best effort basis. See :ref:`vmwerv`
+     * - 'Mitigation: Clear CPU buffers'
+       - The processor is vulnerable and the CPU buffer clearing mitigation is
+         enabled.
+
+If the processor is vulnerable then the following information is appended
+to the above information:
+
+    ========================  ============================================
+    'SMT vulnerable'          SMT is enabled
+    'SMT mitigated'           SMT is enabled and mitigated
+    'SMT disabled'            SMT is disabled
+    'SMT Host state unknown'  Kernel runs in a VM, Host SMT state unknown
+    ========================  ============================================
+
+.. _vmwerv:
+
+Best effort mitigation mode
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  If the processor is vulnerable, but the availability of the microcode based
+  mitigation mechanism is not advertised via CPUID the kernel selects a best
+  effort mitigation mode.  This mode invokes the mitigation instructions
+  without a guarantee that they clear the CPU buffers.
+
+  This is done to address virtualization scenarios where the host has the
+  microcode update applied, but the hypervisor is not yet updated to expose
+  the CPUID to the guest. If the host has updated microcode the protection
+  takes effect otherwise a few cpu cycles are wasted pointlessly.
+
+  The state in the mds sysfs file reflects this situation accordingly.
+
+
+Mitigation mechanism
+-------------------------
+
+The kernel detects the affected CPUs and the presence of the microcode
+which is required.
+
+If a CPU is affected and the microcode is available, then the kernel
+enables the mitigation by default. The mitigation can be controlled at boot
+time via a kernel command line option. See
+:ref:`mds_mitigation_control_command_line`.
+
+.. _cpu_buffer_clear:
+
+CPU buffer clearing
+^^^^^^^^^^^^^^^^^^^
+
+  The mitigation for MDS clears the affected CPU buffers on return to user
+  space and when entering a guest.
+
+  If SMT is enabled it also clears the buffers on idle entry when the CPU
+  is only affected by MSBDS and not any other MDS variant, because the
+  other variants cannot be protected against cross Hyper-Thread attacks.
+
+  For CPUs which are only affected by MSBDS the user space, guest and idle
+  transition mitigations are sufficient and SMT is not affected.
+
+.. _virt_mechanism:
+
+Virtualization mitigation
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  The protection for host to guest transition depends on the L1TF
+  vulnerability of the CPU:
+
+  - CPU is affected by L1TF:
+
+    If the L1D flush mitigation is enabled and up to date microcode is
+    available, the L1D flush mitigation is automatically protecting the
+    guest transition.
+
+    If the L1D flush mitigation is disabled then the MDS mitigation is
+    invoked explicit when the host MDS mitigation is enabled.
+
+    For details on L1TF and virtualization see:
+    :ref:`Documentation/admin-guide/hw-vuln//l1tf.rst <mitigation_control_kvm>`.
+
+  - CPU is not affected by L1TF:
+
+    CPU buffers are flushed before entering the guest when the host MDS
+    mitigation is enabled.
+
+  The resulting MDS protection matrix for the host to guest transition:
+
+  ============ ===== ============= ============ =================
+   L1TF         MDS   VMX-L1FLUSH   Host MDS     MDS-State
+
+   Don't care   No    Don't care    N/A          Not affected
+
+   Yes          Yes   Disabled      Off          Vulnerable
+
+   Yes          Yes   Disabled      Full         Mitigated
+
+   Yes          Yes   Enabled       Don't care   Mitigated
+
+   No           Yes   N/A           Off          Vulnerable
+
+   No           Yes   N/A           Full         Mitigated
+  ============ ===== ============= ============ =================
+
+  This only covers the host to guest transition, i.e. prevents leakage from
+  host to guest, but does not protect the guest internally. Guests need to
+  have their own protections.
+
+.. _xeon_phi:
+
+XEON PHI specific considerations
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  The XEON PHI processor family is affected by MSBDS which can be exploited
+  cross Hyper-Threads when entering idle states. Some XEON PHI variants allow
+  to use MWAIT in user space (Ring 3) which opens an potential attack vector
+  for malicious user space. The exposure can be disabled on the kernel
+  command line with the 'ring3mwait=disable' command line option.
+
+  XEON PHI is not affected by the other MDS variants and MSBDS is mitigated
+  before the CPU enters a idle state. As XEON PHI is not affected by L1TF
+  either disabling SMT is not required for full protection.
+
+.. _mds_smt_control:
+
+SMT control
+^^^^^^^^^^^
+
+  All MDS variants except MSBDS can be attacked cross Hyper-Threads. That
+  means on CPUs which are affected by MFBDS or MLPDS it is necessary to
+  disable SMT for full protection. These are most of the affected CPUs; the
+  exception is XEON PHI, see :ref:`xeon_phi`.
+
+  Disabling SMT can have a significant performance impact, but the impact
+  depends on the type of workloads.
+
+  See the relevant chapter in the L1TF mitigation documentation for details:
+  :ref:`Documentation/admin-guide/hw-vuln/l1tf.rst <smt_control>`.
+
+
+.. _mds_mitigation_control_command_line:
+
+Mitigation control on the kernel command line
+---------------------------------------------
+
+The kernel command line allows to control the MDS mitigations at boot
+time with the option "mds=". The valid arguments for this option are:
+
+  ============  =============================================================
+  full         If the CPU is vulnerable, enable all available mitigations
+               for the MDS vulnerability, CPU buffer clearing on exit to
+               userspace and when entering a VM. Idle transitions are
+               protected as well if SMT is enabled.
+
+               It does not automatically disable SMT.
+
+  full,nosmt   The same as mds=full, with SMT disabled on vulnerable
+               CPUs.  This is the complete mitigation.
+
+  off          Disables MDS mitigations completely.
+
+  ============  =============================================================
+
+Not specifying this option is equivalent to "mds=full".
+
+
+Mitigation selection guide
+--------------------------
+
+1. Trusted userspace
+^^^^^^^^^^^^^^^^^^^^
+
+   If all userspace applications are from a trusted source and do not
+   execute untrusted code which is supplied externally, then the mitigation
+   can be disabled.
+
+
+2. Virtualization with trusted guests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+   The same considerations as above versus trusted user space apply.
+
+3. Virtualization with untrusted guests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+   The protection depends on the state of the L1TF mitigations.
+   See :ref:`virt_mechanism`.
+
+   If the MDS mitigation is enabled and SMT is disabled, guest to host and
+   guest to guest attacks are prevented.
+
+.. _mds_default_mitigations:
+
+Default mitigations
+-------------------
+
+  The kernel default mitigations for vulnerable processors are:
+
+  - Enable CPU buffer clearing
+
+  The kernel does not by default enforce the disabling of SMT, which leaves
+  SMT systems vulnerable when running untrusted code. The same rationale as
+  for L1TF applies.
+  See :ref:`Documentation/admin-guide/hw-vuln//l1tf.rst <default_mitigations>`.
index 5b8286f..8001917 100644 (file)
@@ -17,14 +17,12 @@ etc.
    kernel-parameters
    devices
 
-This section describes CPU vulnerabilities and provides an overview of the
-possible mitigations along with guidance for selecting mitigations if they
-are configurable at compile, boot or run time.
+This section describes CPU vulnerabilities and their mitigations.
 
 .. toctree::
    :maxdepth: 1
 
-   l1tf
+   hw-vuln/index
 
 Here is a set of documents aimed at users who are trying to track down
 problems and bugs in particular.
index 08df588..52e6fbb 100644 (file)
        ip=             [IP_PNP]
                        See Documentation/filesystems/nfs/nfsroot.txt.
 
+       ipcmni_extend   [KNL] Extend the maximum number of unique System V
+                       IPC identifiers from 32,768 to 16,777,216.
+
        irqaffinity=    [SMP] Set the default irq affinity mask
                        The argument is a cpu list, as described above.
 
 
                        Default is 'flush'.
 
-                       For details see: Documentation/admin-guide/l1tf.rst
+                       For details see: Documentation/admin-guide/hw-vuln/l1tf.rst
 
        l2cr=           [PPC]
 
                        Format: <first>,<last>
                        Specifies range of consoles to be captured by the MDA.
 
+       mds=            [X86,INTEL]
+                       Control mitigation for the Micro-architectural Data
+                       Sampling (MDS) vulnerability.
+
+                       Certain CPUs are vulnerable to an exploit against CPU
+                       internal buffers which can forward information to a
+                       disclosure gadget under certain conditions.
+
+                       In vulnerable processors, the speculatively
+                       forwarded data can be used in a cache side channel
+                       attack, to access data to which the attacker does
+                       not have direct access.
+
+                       This parameter controls the MDS mitigation. The
+                       options are:
+
+                       full       - Enable MDS mitigation on vulnerable CPUs
+                       full,nosmt - Enable MDS mitigation and disable
+                                    SMT on vulnerable CPUs
+                       off        - Unconditionally disable MDS mitigation
+
+                       Not specifying this option is equivalent to
+                       mds=full.
+
+                       For details see: Documentation/admin-guide/hw-vuln/mds.rst
+
        mem=nn[KMG]     [KNL,BOOT] Force usage of a specific amount of memory
                        Amount of memory to be used when the kernel is not able
                        to see the whole system memory or for test.
                                               spec_store_bypass_disable=off [X86,PPC]
                                               ssbd=force-off [ARM64]
                                               l1tf=off [X86]
+                                              mds=off [X86]
 
                        auto (default)
                                Mitigate all CPU vulnerabilities, but leave SMT
                                if needed.  This is for users who always want to
                                be fully mitigated, even if it means losing SMT.
                                Equivalent to: l1tf=flush,nosmt [X86]
+                                              mds=full,nosmt [X86]
 
        mminit_loglevel=
                        [KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this
                        This will also cause panics on machine check exceptions.
                        Useful together with panic=30 to trigger a reboot.
 
+       page_alloc.shuffle=
+                       [KNL] Boolean flag to control whether the page allocator
+                       should randomize its free lists. The randomization may
+                       be automatically enabled if the kernel detects it is
+                       running on a platform with a direct-mapped memory-side
+                       cache, and this parameter can be used to
+                       override/disable that behavior. The state of the flag
+                       can be read from sysfs at:
+                       /sys/module/page_alloc/parameters/shuffle.
+
        page_owner=     [KNL] Boot-time page_owner enabling option.
                        Storage of the information about who allocated
                        each page is disabled in default. With this switch,
                                [[,]s[mp]#### \
                                [[,]b[ios] | a[cpi] | k[bd] | t[riple] | e[fi] | p[ci]] \
                                [[,]f[orce]
-                       Where reboot_mode is one of warm (soft) or cold (hard) or gpio,
+                       Where reboot_mode is one of warm (soft) or cold (hard) or gpio
+                                       (prefix with 'panic_' to set mode for panic
+                                       reboot only),
                              reboot_type is one of bios, acpi, kbd, triple, efi, or pci,
                              reboot_force is either force or not specified,
                              reboot_cpu is s[mp]#### with #### being the processor
                        with /sys/devices/system/xen_memory/xen_memory0/scrub_pages.
                        Default value controlled with CONFIG_XEN_SCRUB_PAGES_DEFAULT.
 
+       xen_timer_slop= [X86-64,XEN]
+                       Set the timer slop (in nanoseconds) for the virtual Xen
+                       timers (default is 100000). This adjusts the minimum
+                       delta of virtualized Xen timers, where lower values
+                       improve timer resolution at the expense of processing
+                       more timer interrupts.
+
        xirc2ps_cs=     [NET,PCMCIA]
                        Format:
                        <irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
diff --git a/Documentation/admin-guide/l1tf.rst b/Documentation/admin-guide/l1tf.rst
deleted file mode 100644 (file)
index 9af9773..0000000
+++ /dev/null
@@ -1,614 +0,0 @@
-L1TF - L1 Terminal Fault
-========================
-
-L1 Terminal Fault is a hardware vulnerability which allows unprivileged
-speculative access to data which is available in the Level 1 Data Cache
-when the page table entry controlling the virtual address, which is used
-for the access, has the Present bit cleared or other reserved bits set.
-
-Affected processors
--------------------
-
-This vulnerability affects a wide range of Intel processors. The
-vulnerability is not present on:
-
-   - Processors from AMD, Centaur and other non Intel vendors
-
-   - Older processor models, where the CPU family is < 6
-
-   - A range of Intel ATOM processors (Cedarview, Cloverview, Lincroft,
-     Penwell, Pineview, Silvermont, Airmont, Merrifield)
-
-   - The Intel XEON PHI family
-
-   - Intel processors which have the ARCH_CAP_RDCL_NO bit set in the
-     IA32_ARCH_CAPABILITIES MSR. If the bit is set the CPU is not affected
-     by the Meltdown vulnerability either. These CPUs should become
-     available by end of 2018.
-
-Whether a processor is affected or not can be read out from the L1TF
-vulnerability file in sysfs. See :ref:`l1tf_sys_info`.
-
-Related CVEs
-------------
-
-The following CVE entries are related to the L1TF vulnerability:
-
-   =============  =================  ==============================
-   CVE-2018-3615  L1 Terminal Fault  SGX related aspects
-   CVE-2018-3620  L1 Terminal Fault  OS, SMM related aspects
-   CVE-2018-3646  L1 Terminal Fault  Virtualization related aspects
-   =============  =================  ==============================
-
-Problem
--------
-
-If an instruction accesses a virtual address for which the relevant page
-table entry (PTE) has the Present bit cleared or other reserved bits set,
-then speculative execution ignores the invalid PTE and loads the referenced
-data if it is present in the Level 1 Data Cache, as if the page referenced
-by the address bits in the PTE was still present and accessible.
-
-While this is a purely speculative mechanism and the instruction will raise
-a page fault when it is retired eventually, the pure act of loading the
-data and making it available to other speculative instructions opens up the
-opportunity for side channel attacks to unprivileged malicious code,
-similar to the Meltdown attack.
-
-While Meltdown breaks the user space to kernel space protection, L1TF
-allows to attack any physical memory address in the system and the attack
-works across all protection domains. It allows an attack of SGX and also
-works from inside virtual machines because the speculation bypasses the
-extended page table (EPT) protection mechanism.
-
-
-Attack scenarios
-----------------
-
-1. Malicious user space
-^^^^^^^^^^^^^^^^^^^^^^^
-
-   Operating Systems store arbitrary information in the address bits of a
-   PTE which is marked non present. This allows a malicious user space
-   application to attack the physical memory to which these PTEs resolve.
-   In some cases user-space can maliciously influence the information
-   encoded in the address bits of the PTE, thus making attacks more
-   deterministic and more practical.
-
-   The Linux kernel contains a mitigation for this attack vector, PTE
-   inversion, which is permanently enabled and has no performance
-   impact. The kernel ensures that the address bits of PTEs, which are not
-   marked present, never point to cacheable physical memory space.
-
-   A system with an up to date kernel is protected against attacks from
-   malicious user space applications.
-
-2. Malicious guest in a virtual machine
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-   The fact that L1TF breaks all domain protections allows malicious guest
-   OSes, which can control the PTEs directly, and malicious guest user
-   space applications, which run on an unprotected guest kernel lacking the
-   PTE inversion mitigation for L1TF, to attack physical host memory.
-
-   A special aspect of L1TF in the context of virtualization is symmetric
-   multi threading (SMT). The Intel implementation of SMT is called
-   HyperThreading. The fact that Hyperthreads on the affected processors
-   share the L1 Data Cache (L1D) is important for this. As the flaw allows
-   only to attack data which is present in L1D, a malicious guest running
-   on one Hyperthread can attack the data which is brought into the L1D by
-   the context which runs on the sibling Hyperthread of the same physical
-   core. This context can be host OS, host user space or a different guest.
-
-   If the processor does not support Extended Page Tables, the attack is
-   only possible, when the hypervisor does not sanitize the content of the
-   effective (shadow) page tables.
-
-   While solutions exist to mitigate these attack vectors fully, these
-   mitigations are not enabled by default in the Linux kernel because they
-   can affect performance significantly. The kernel provides several
-   mechanisms which can be utilized to address the problem depending on the
-   deployment scenario. The mitigations, their protection scope and impact
-   are described in the next sections.
-
-   The default mitigations and the rationale for choosing them are explained
-   at the end of this document. See :ref:`default_mitigations`.
-
-.. _l1tf_sys_info:
-
-L1TF system information
------------------------
-
-The Linux kernel provides a sysfs interface to enumerate the current L1TF
-status of the system: whether the system is vulnerable, and which
-mitigations are active. The relevant sysfs file is:
-
-/sys/devices/system/cpu/vulnerabilities/l1tf
-
-The possible values in this file are:
-
-  ===========================   ===============================
-  'Not affected'               The processor is not vulnerable
-  'Mitigation: PTE Inversion'  The host protection is active
-  ===========================   ===============================
-
-If KVM/VMX is enabled and the processor is vulnerable then the following
-information is appended to the 'Mitigation: PTE Inversion' part:
-
-  - SMT status:
-
-    =====================  ================
-    'VMX: SMT vulnerable'  SMT is enabled
-    'VMX: SMT disabled'    SMT is disabled
-    =====================  ================
-
-  - L1D Flush mode:
-
-    ================================  ====================================
-    'L1D vulnerable'                 L1D flushing is disabled
-
-    'L1D conditional cache flushes'   L1D flush is conditionally enabled
-
-    'L1D cache flushes'                      L1D flush is unconditionally enabled
-    ================================  ====================================
-
-The resulting grade of protection is discussed in the following sections.
-
-
-Host mitigation mechanism
--------------------------
-
-The kernel is unconditionally protected against L1TF attacks from malicious
-user space running on the host.
-
-
-Guest mitigation mechanisms
----------------------------
-
-.. _l1d_flush:
-
-1. L1D flush on VMENTER
-^^^^^^^^^^^^^^^^^^^^^^^
-
-   To make sure that a guest cannot attack data which is present in the L1D
-   the hypervisor flushes the L1D before entering the guest.
-
-   Flushing the L1D evicts not only the data which should not be accessed
-   by a potentially malicious guest, it also flushes the guest
-   data. Flushing the L1D has a performance impact as the processor has to
-   bring the flushed guest data back into the L1D. Depending on the
-   frequency of VMEXIT/VMENTER and the type of computations in the guest
-   performance degradation in the range of 1% to 50% has been observed. For
-   scenarios where guest VMEXIT/VMENTER are rare the performance impact is
-   minimal. Virtio and mechanisms like posted interrupts are designed to
-   confine the VMEXITs to a bare minimum, but specific configurations and
-   application scenarios might still suffer from a high VMEXIT rate.
-
-   The kernel provides two L1D flush modes:
-    - conditional ('cond')
-    - unconditional ('always')
-
-   The conditional mode avoids L1D flushing after VMEXITs which execute
-   only audited code paths before the corresponding VMENTER. These code
-   paths have been verified that they cannot expose secrets or other
-   interesting data to an attacker, but they can leak information about the
-   address space layout of the hypervisor.
-
-   Unconditional mode flushes L1D on all VMENTER invocations and provides
-   maximum protection. It has a higher overhead than the conditional
-   mode. The overhead cannot be quantified correctly as it depends on the
-   workload scenario and the resulting number of VMEXITs.
-
-   The general recommendation is to enable L1D flush on VMENTER. The kernel
-   defaults to conditional mode on affected processors.
-
-   **Note**, that L1D flush does not prevent the SMT problem because the
-   sibling thread will also bring back its data into the L1D which makes it
-   attackable again.
-
-   L1D flush can be controlled by the administrator via the kernel command
-   line and sysfs control files. See :ref:`mitigation_control_command_line`
-   and :ref:`mitigation_control_kvm`.
-
-.. _guest_confinement:
-
-2. Guest VCPU confinement to dedicated physical cores
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-   To address the SMT problem, it is possible to make a guest or a group of
-   guests affine to one or more physical cores. The proper mechanism for
-   that is to utilize exclusive cpusets to ensure that no other guest or
-   host tasks can run on these cores.
-
-   If only a single guest or related guests run on sibling SMT threads on
-   the same physical core then they can only attack their own memory and
-   restricted parts of the host memory.
-
-   Host memory is attackable, when one of the sibling SMT threads runs in
-   host OS (hypervisor) context and the other in guest context. The amount
-   of valuable information from the host OS context depends on the context
-   which the host OS executes, i.e. interrupts, soft interrupts and kernel
-   threads. The amount of valuable data from these contexts cannot be
-   declared as non-interesting for an attacker without deep inspection of
-   the code.
-
-   **Note**, that assigning guests to a fixed set of physical cores affects
-   the ability of the scheduler to do load balancing and might have
-   negative effects on CPU utilization depending on the hosting
-   scenario. Disabling SMT might be a viable alternative for particular
-   scenarios.
-
-   For further information about confining guests to a single or to a group
-   of cores consult the cpusets documentation:
-
-   https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt
-
-.. _interrupt_isolation:
-
-3. Interrupt affinity
-^^^^^^^^^^^^^^^^^^^^^
-
-   Interrupts can be made affine to logical CPUs. This is not universally
-   true because there are types of interrupts which are truly per CPU
-   interrupts, e.g. the local timer interrupt. Aside of that multi queue
-   devices affine their interrupts to single CPUs or groups of CPUs per
-   queue without allowing the administrator to control the affinities.
-
-   Moving the interrupts, which can be affinity controlled, away from CPUs
-   which run untrusted guests, reduces the attack vector space.
-
-   Whether the interrupts with are affine to CPUs, which run untrusted
-   guests, provide interesting data for an attacker depends on the system
-   configuration and the scenarios which run on the system. While for some
-   of the interrupts it can be assumed that they won't expose interesting
-   information beyond exposing hints about the host OS memory layout, there
-   is no way to make general assumptions.
-
-   Interrupt affinity can be controlled by the administrator via the
-   /proc/irq/$NR/smp_affinity[_list] files. Limited documentation is
-   available at:
-
-   https://www.kernel.org/doc/Documentation/IRQ-affinity.txt
-
-.. _smt_control:
-
-4. SMT control
-^^^^^^^^^^^^^^
-
-   To prevent the SMT issues of L1TF it might be necessary to disable SMT
-   completely. Disabling SMT can have a significant performance impact, but
-   the impact depends on the hosting scenario and the type of workloads.
-   The impact of disabling SMT needs also to be weighted against the impact
-   of other mitigation solutions like confining guests to dedicated cores.
-
-   The kernel provides a sysfs interface to retrieve the status of SMT and
-   to control it. It also provides a kernel command line interface to
-   control SMT.
-
-   The kernel command line interface consists of the following options:
-
-     =========== ==========================================================
-     nosmt      Affects the bring up of the secondary CPUs during boot. The
-                kernel tries to bring all present CPUs online during the
-                boot process. "nosmt" makes sure that from each physical
-                core only one - the so called primary (hyper) thread is
-                activated. Due to a design flaw of Intel processors related
-                to Machine Check Exceptions the non primary siblings have
-                to be brought up at least partially and are then shut down
-                again.  "nosmt" can be undone via the sysfs interface.
-
-     nosmt=force Has the same effect as "nosmt" but it does not allow to
-                undo the SMT disable via the sysfs interface.
-     =========== ==========================================================
-
-   The sysfs interface provides two files:
-
-   - /sys/devices/system/cpu/smt/control
-   - /sys/devices/system/cpu/smt/active
-
-   /sys/devices/system/cpu/smt/control:
-
-     This file allows to read out the SMT control state and provides the
-     ability to disable or (re)enable SMT. The possible states are:
-
-       ==============  ===================================================
-       on              SMT is supported by the CPU and enabled. All
-                       logical CPUs can be onlined and offlined without
-                       restrictions.
-
-       off             SMT is supported by the CPU and disabled. Only
-                       the so called primary SMT threads can be onlined
-                       and offlined without restrictions. An attempt to
-                       online a non-primary sibling is rejected
-
-       forceoff        Same as 'off' but the state cannot be controlled.
-                       Attempts to write to the control file are rejected.
-
-       notsupported    The processor does not support SMT. It's therefore
-                       not affected by the SMT implications of L1TF.
-                       Attempts to write to the control file are rejected.
-       ==============  ===================================================
-
-     The possible states which can be written into this file to control SMT
-     state are:
-
-     - on
-     - off
-     - forceoff
-
-   /sys/devices/system/cpu/smt/active:
-
-     This file reports whether SMT is enabled and active, i.e. if on any
-     physical core two or more sibling threads are online.
-
-   SMT control is also possible at boot time via the l1tf kernel command
-   line parameter in combination with L1D flush control. See
-   :ref:`mitigation_control_command_line`.
-
-5. Disabling EPT
-^^^^^^^^^^^^^^^^
-
-  Disabling EPT for virtual machines provides full mitigation for L1TF even
-  with SMT enabled, because the effective page tables for guests are
-  managed and sanitized by the hypervisor. Though disabling EPT has a
-  significant performance impact especially when the Meltdown mitigation
-  KPTI is enabled.
-
-  EPT can be disabled in the hypervisor via the 'kvm-intel.ept' parameter.
-
-There is ongoing research and development for new mitigation mechanisms to
-address the performance impact of disabling SMT or EPT.
-
-.. _mitigation_control_command_line:
-
-Mitigation control on the kernel command line
----------------------------------------------
-
-The kernel command line allows to control the L1TF mitigations at boot
-time with the option "l1tf=". The valid arguments for this option are:
-
-  ============  =============================================================
-  full         Provides all available mitigations for the L1TF
-               vulnerability. Disables SMT and enables all mitigations in
-               the hypervisors, i.e. unconditional L1D flushing
-
-               SMT control and L1D flush control via the sysfs interface
-               is still possible after boot.  Hypervisors will issue a
-               warning when the first VM is started in a potentially
-               insecure configuration, i.e. SMT enabled or L1D flush
-               disabled.
-
-  full,force   Same as 'full', but disables SMT and L1D flush runtime
-               control. Implies the 'nosmt=force' command line option.
-               (i.e. sysfs control of SMT is disabled.)
-
-  flush                Leaves SMT enabled and enables the default hypervisor
-               mitigation, i.e. conditional L1D flushing
-
-               SMT control and L1D flush control via the sysfs interface
-               is still possible after boot.  Hypervisors will issue a
-               warning when the first VM is started in a potentially
-               insecure configuration, i.e. SMT enabled or L1D flush
-               disabled.
-
-  flush,nosmt  Disables SMT and enables the default hypervisor mitigation,
-               i.e. conditional L1D flushing.
-
-               SMT control and L1D flush control via the sysfs interface
-               is still possible after boot.  Hypervisors will issue a
-               warning when the first VM is started in a potentially
-               insecure configuration, i.e. SMT enabled or L1D flush
-               disabled.
-
-  flush,nowarn Same as 'flush', but hypervisors will not warn when a VM is
-               started in a potentially insecure configuration.
-
-  off          Disables hypervisor mitigations and doesn't emit any
-               warnings.
-               It also drops the swap size and available RAM limit restrictions
-               on both hypervisor and bare metal.
-
-  ============  =============================================================
-
-The default is 'flush'. For details about L1D flushing see :ref:`l1d_flush`.
-
-
-.. _mitigation_control_kvm:
-
-Mitigation control for KVM - module parameter
--------------------------------------------------------------
-
-The KVM hypervisor mitigation mechanism, flushing the L1D cache when
-entering a guest, can be controlled with a module parameter.
-
-The option/parameter is "kvm-intel.vmentry_l1d_flush=". It takes the
-following arguments:
-
-  ============  ==============================================================
-  always       L1D cache flush on every VMENTER.
-
-  cond         Flush L1D on VMENTER only when the code between VMEXIT and
-               VMENTER can leak host memory which is considered
-               interesting for an attacker. This still can leak host memory
-               which allows e.g. to determine the hosts address space layout.
-
-  never                Disables the mitigation
-  ============  ==============================================================
-
-The parameter can be provided on the kernel command line, as a module
-parameter when loading the modules and at runtime modified via the sysfs
-file:
-
-/sys/module/kvm_intel/parameters/vmentry_l1d_flush
-
-The default is 'cond'. If 'l1tf=full,force' is given on the kernel command
-line, then 'always' is enforced and the kvm-intel.vmentry_l1d_flush
-module parameter is ignored and writes to the sysfs file are rejected.
-
-
-Mitigation selection guide
---------------------------
-
-1. No virtualization in use
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-   The system is protected by the kernel unconditionally and no further
-   action is required.
-
-2. Virtualization with trusted guests
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-   If the guest comes from a trusted source and the guest OS kernel is
-   guaranteed to have the L1TF mitigations in place the system is fully
-   protected against L1TF and no further action is required.
-
-   To avoid the overhead of the default L1D flushing on VMENTER the
-   administrator can disable the flushing via the kernel command line and
-   sysfs control files. See :ref:`mitigation_control_command_line` and
-   :ref:`mitigation_control_kvm`.
-
-
-3. Virtualization with untrusted guests
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-3.1. SMT not supported or disabled
-""""""""""""""""""""""""""""""""""
-
-  If SMT is not supported by the processor or disabled in the BIOS or by
-  the kernel, it's only required to enforce L1D flushing on VMENTER.
-
-  Conditional L1D flushing is the default behaviour and can be tuned. See
-  :ref:`mitigation_control_command_line` and :ref:`mitigation_control_kvm`.
-
-3.2. EPT not supported or disabled
-""""""""""""""""""""""""""""""""""
-
-  If EPT is not supported by the processor or disabled in the hypervisor,
-  the system is fully protected. SMT can stay enabled and L1D flushing on
-  VMENTER is not required.
-
-  EPT can be disabled in the hypervisor via the 'kvm-intel.ept' parameter.
-
-3.3. SMT and EPT supported and active
-"""""""""""""""""""""""""""""""""""""
-
-  If SMT and EPT are supported and active then various degrees of
-  mitigations can be employed:
-
-  - L1D flushing on VMENTER:
-
-    L1D flushing on VMENTER is the minimal protection requirement, but it
-    is only potent in combination with other mitigation methods.
-
-    Conditional L1D flushing is the default behaviour and can be tuned. See
-    :ref:`mitigation_control_command_line` and :ref:`mitigation_control_kvm`.
-
-  - Guest confinement:
-
-    Confinement of guests to a single or a group of physical cores which
-    are not running any other processes, can reduce the attack surface
-    significantly, but interrupts, soft interrupts and kernel threads can
-    still expose valuable data to a potential attacker. See
-    :ref:`guest_confinement`.
-
-  - Interrupt isolation:
-
-    Isolating the guest CPUs from interrupts can reduce the attack surface
-    further, but still allows a malicious guest to explore a limited amount
-    of host physical memory. This can at least be used to gain knowledge
-    about the host address space layout. The interrupts which have a fixed
-    affinity to the CPUs which run the untrusted guests can depending on
-    the scenario still trigger soft interrupts and schedule kernel threads
-    which might expose valuable information. See
-    :ref:`interrupt_isolation`.
-
-The above three mitigation methods combined can provide protection to a
-certain degree, but the risk of the remaining attack surface has to be
-carefully analyzed. For full protection the following methods are
-available:
-
-  - Disabling SMT:
-
-    Disabling SMT and enforcing the L1D flushing provides the maximum
-    amount of protection. This mitigation is not depending on any of the
-    above mitigation methods.
-
-    SMT control and L1D flushing can be tuned by the command line
-    parameters 'nosmt', 'l1tf', 'kvm-intel.vmentry_l1d_flush' and at run
-    time with the matching sysfs control files. See :ref:`smt_control`,
-    :ref:`mitigation_control_command_line` and
-    :ref:`mitigation_control_kvm`.
-
-  - Disabling EPT:
-
-    Disabling EPT provides the maximum amount of protection as well. It is
-    not depending on any of the above mitigation methods. SMT can stay
-    enabled and L1D flushing is not required, but the performance impact is
-    significant.
-
-    EPT can be disabled in the hypervisor via the 'kvm-intel.ept'
-    parameter.
-
-3.4. Nested virtual machines
-""""""""""""""""""""""""""""
-
-When nested virtualization is in use, three operating systems are involved:
-the bare metal hypervisor, the nested hypervisor and the nested virtual
-machine.  VMENTER operations from the nested hypervisor into the nested
-guest will always be processed by the bare metal hypervisor. If KVM is the
-bare metal hypervisor it will:
-
- - Flush the L1D cache on every switch from the nested hypervisor to the
-   nested virtual machine, so that the nested hypervisor's secrets are not
-   exposed to the nested virtual machine;
-
- - Flush the L1D cache on every switch from the nested virtual machine to
-   the nested hypervisor; this is a complex operation, and flushing the L1D
-   cache avoids that the bare metal hypervisor's secrets are exposed to the
-   nested virtual machine;
-
- - Instruct the nested hypervisor to not perform any L1D cache flush. This
-   is an optimization to avoid double L1D flushing.
-
-
-.. _default_mitigations:
-
-Default mitigations
--------------------
-
-  The kernel default mitigations for vulnerable processors are:
-
-  - PTE inversion to protect against malicious user space. This is done
-    unconditionally and cannot be controlled. The swap storage is limited
-    to ~16TB.
-
-  - L1D conditional flushing on VMENTER when EPT is enabled for
-    a guest.
-
-  The kernel does not by default enforce the disabling of SMT, which leaves
-  SMT systems vulnerable when running untrusted guests with EPT enabled.
-
-  The rationale for this choice is:
-
-  - Force disabling SMT can break existing setups, especially with
-    unattended updates.
-
-  - If regular users run untrusted guests on their machine, then L1TF is
-    just an add on to other malware which might be embedded in an untrusted
-    guest, e.g. spam-bots or attacks on the local network.
-
-    There is no technical way to prevent a user from running untrusted code
-    on their machines blindly.
-
-  - It's technically extremely unlikely and from today's knowledge even
-    impossible that L1TF can be exploited via the most popular attack
-    mechanisms like JavaScript because these mechanisms have no way to
-    control PTEs. If this would be possible and not other mitigation would
-    be possible, then the default might be different.
-
-  - The administrators of cloud and hosting setups have to carefully
-    analyze the risk for their scenarios and make the appropriate
-    mitigation choices, which might even vary across their deployed
-    machines and also result in other changes of their overall setup.
-    There is no way for the kernel to provide a sensible default for this
-    kind of scenarios.
index 71f5d2f..a29c99d 100644 (file)
@@ -147,10 +147,10 @@ Division Functions
 .. kernel-doc:: include/linux/math64.h
    :internal:
 
-.. kernel-doc:: lib/div64.c
+.. kernel-doc:: lib/math/div64.c
    :functions: div_s64_rem div64_u64_rem div64_u64 div64_s64
 
-.. kernel-doc:: lib/gcd.c
+.. kernel-doc:: lib/math/gcd.c
    :export:
 
 UUID/GUID
index 69a7d90..46aae52 100644 (file)
@@ -34,10 +34,6 @@ Configure the kernel with::
         CONFIG_DEBUG_FS=y
         CONFIG_GCOV_KERNEL=y
 
-select the gcc's gcov format, default is autodetect based on gcc version::
-
-        CONFIG_GCOV_FORMAT_AUTODETECT=y
-
 and to get coverage data for the entire kernel::
 
         CONFIG_GCOV_PROFILE_ALL=y
@@ -169,6 +165,20 @@ b) gcov is run on the BUILD machine
       [user@build] gcov -o /tmp/coverage/tmp/out/init main.c
 
 
+Note on compilers
+-----------------
+
+GCC and LLVM gcov tools are not necessarily compatible. Use gcov_ to work with
+GCC-generated .gcno and .gcda files, and use llvm-cov_ for Clang.
+
+.. _gcov: http://gcc.gnu.org/onlinedocs/gcc/Gcov.html
+.. _llvm-cov: https://llvm.org/docs/CommandGuide/llvm-cov.html
+
+Build differences between GCC and Clang gcov are handled by Kconfig. It
+automatically selects the appropriate gcov format depending on the detected
+toolchain.
+
+
 Troubleshooting
 ---------------
 
diff --git a/Documentation/device-mapper/dm-dust.txt b/Documentation/device-mapper/dm-dust.txt
new file mode 100644 (file)
index 0000000..954d402
--- /dev/null
@@ -0,0 +1,272 @@
+dm-dust
+=======
+
+This target emulates the behavior of bad sectors at arbitrary
+locations, and the ability to enable the emulation of the failures
+at an arbitrary time.
+
+This target behaves similarly to a linear target.  At a given time,
+the user can send a message to the target to start failing read
+requests on specific blocks (to emulate the behavior of a hard disk
+drive with bad sectors).
+
+When the failure behavior is enabled (i.e.: when the output of
+"dmsetup status" displays "fail_read_on_bad_block"), reads of blocks
+in the "bad block list" will fail with EIO ("Input/output error").
+
+Writes of blocks in the "bad block list will result in the following:
+
+1. Remove the block from the "bad block list".
+2. Successfully complete the write.
+
+This emulates the "remapped sector" behavior of a drive with bad
+sectors.
+
+Normally, a drive that is encountering bad sectors will most likely
+encounter more bad sectors, at an unknown time or location.
+With dm-dust, the user can use the "addbadblock" and "removebadblock"
+messages to add arbitrary bad blocks at new locations, and the
+"enable" and "disable" messages to modulate the state of whether the
+configured "bad blocks" will be treated as bad, or bypassed.
+This allows the pre-writing of test data and metadata prior to
+simulating a "failure" event where bad sectors start to appear.
+
+Table parameters:
+-----------------
+<device_path> <offset> <blksz>
+
+Mandatory parameters:
+    <device_path>: path to the block device.
+    <offset>: offset to data area from start of device_path
+    <blksz>: block size in bytes
+            (minimum 512, maximum 1073741824, must be a power of 2)
+
+Usage instructions:
+-------------------
+
+First, find the size (in 512-byte sectors) of the device to be used:
+
+$ sudo blockdev --getsz /dev/vdb1
+33552384
+
+Create the dm-dust device:
+(For a device with a block size of 512 bytes)
+$ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 512'
+
+(For a device with a block size of 4096 bytes)
+$ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 4096'
+
+Check the status of the read behavior ("bypass" indicates that all I/O
+will be passed through to the underlying device):
+$ sudo dmsetup status dust1
+0 33552384 dust 252:17 bypass
+
+$ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=128 iflag=direct
+128+0 records in
+128+0 records out
+
+$ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct
+128+0 records in
+128+0 records out
+
+Adding and removing bad blocks:
+-------------------------------
+
+At any time (i.e.: whether the device has the "bad block" emulation
+enabled or disabled), bad blocks may be added or removed from the
+device via the "addbadblock" and "removebadblock" messages:
+
+$ sudo dmsetup message dust1 0 addbadblock 60
+kernel: device-mapper: dust: badblock added at block 60
+
+$ sudo dmsetup message dust1 0 addbadblock 67
+kernel: device-mapper: dust: badblock added at block 67
+
+$ sudo dmsetup message dust1 0 addbadblock 72
+kernel: device-mapper: dust: badblock added at block 72
+
+These bad blocks will be stored in the "bad block list".
+While the device is in "bypass" mode, reads and writes will succeed:
+
+$ sudo dmsetup status dust1
+0 33552384 dust 252:17 bypass
+
+Enabling block read failures:
+-----------------------------
+
+To enable the "fail read on bad block" behavior, send the "enable" message:
+
+$ sudo dmsetup message dust1 0 enable
+kernel: device-mapper: dust: enabling read failures on bad sectors
+
+$ sudo dmsetup status dust1
+0 33552384 dust 252:17 fail_read_on_bad_block
+
+With the device in "fail read on bad block" mode, attempting to read a
+block will encounter an "Input/output error":
+
+$ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=1 skip=67 iflag=direct
+dd: error reading '/dev/mapper/dust1': Input/output error
+0+0 records in
+0+0 records out
+0 bytes copied, 0.00040651 s, 0.0 kB/s
+
+...and writing to the bad blocks will remove the blocks from the list,
+therefore emulating the "remap" behavior of hard disk drives:
+
+$ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct
+128+0 records in
+128+0 records out
+
+kernel: device-mapper: dust: block 60 removed from badblocklist by write
+kernel: device-mapper: dust: block 67 removed from badblocklist by write
+kernel: device-mapper: dust: block 72 removed from badblocklist by write
+kernel: device-mapper: dust: block 87 removed from badblocklist by write
+
+Bad block add/remove error handling:
+------------------------------------
+
+Attempting to add a bad block that already exists in the list will
+result in an "Invalid argument" error, as well as a helpful message:
+
+$ sudo dmsetup message dust1 0 addbadblock 88
+device-mapper: message ioctl on dust1  failed: Invalid argument
+kernel: device-mapper: dust: block 88 already in badblocklist
+
+Attempting to remove a bad block that doesn't exist in the list will
+result in an "Invalid argument" error, as well as a helpful message:
+
+$ sudo dmsetup message dust1 0 removebadblock 87
+device-mapper: message ioctl on dust1  failed: Invalid argument
+kernel: device-mapper: dust: block 87 not found in badblocklist
+
+Counting the number of bad blocks in the bad block list:
+--------------------------------------------------------
+
+To count the number of bad blocks configured in the device, run the
+following message command:
+
+$ sudo dmsetup message dust1 0 countbadblocks
+
+A message will print with the number of bad blocks currently
+configured on the device:
+
+kernel: device-mapper: dust: countbadblocks: 895 badblock(s) found
+
+Querying for specific bad blocks:
+---------------------------------
+
+To find out if a specific block is in the bad block list, run the
+following message command:
+
+$ sudo dmsetup message dust1 0 queryblock 72
+
+The following message will print if the block is in the list:
+device-mapper: dust: queryblock: block 72 found in badblocklist
+
+The following message will print if the block is in the list:
+device-mapper: dust: queryblock: block 72 not found in badblocklist
+
+The "queryblock" message command will work in both the "enabled"
+and "disabled" modes, allowing the verification of whether a block
+will be treated as "bad" without having to issue I/O to the device,
+or having to "enable" the bad block emulation.
+
+Clearing the bad block list:
+----------------------------
+
+To clear the bad block list (without needing to individually run
+a "removebadblock" message command for every block), run the
+following message command:
+
+$ sudo dmsetup message dust1 0 clearbadblocks
+
+After clearing the bad block list, the following message will appear:
+
+kernel: device-mapper: dust: clearbadblocks: badblocks cleared
+
+If there were no bad blocks to clear, the following message will
+appear:
+
+kernel: device-mapper: dust: clearbadblocks: no badblocks found
+
+Message commands list:
+----------------------
+
+Below is a list of the messages that can be sent to a dust device:
+
+Operations on blocks (requires a <blknum> argument):
+
+addbadblock <blknum>
+queryblock <blknum>
+removebadblock <blknum>
+
+...where <blknum> is a block number within range of the device
+  (corresponding to the block size of the device.)
+
+Single argument message commands:
+
+countbadblocks
+clearbadblocks
+disable
+enable
+quiet
+
+Device removal:
+---------------
+
+When finished, remove the device via the "dmsetup remove" command:
+
+$ sudo dmsetup remove dust1
+
+Quiet mode:
+-----------
+
+On test runs with many bad blocks, it may be desirable to avoid
+excessive logging (from bad blocks added, removed, or "remapped").
+This can be done by enabling "quiet mode" via the following message:
+
+$ sudo dmsetup message dust1 0 quiet
+
+This will suppress log messages from add / remove / removed by write
+operations.  Log messages from "countbadblocks" or "queryblock"
+message commands will still print in quiet mode.
+
+The status of quiet mode can be seen by running "dmsetup status":
+
+$ sudo dmsetup status dust1
+0 33552384 dust 252:17 fail_read_on_bad_block quiet
+
+To disable quiet mode, send the "quiet" message again:
+
+$ sudo dmsetup message dust1 0 quiet
+
+$ sudo dmsetup status dust1
+0 33552384 dust 252:17 fail_read_on_bad_block verbose
+
+(The presence of "verbose" indicates normal logging.)
+
+"Why not...?"
+-------------
+
+scsi_debug has a "medium error" mode that can fail reads on one
+specified sector (sector 0x1234, hardcoded in the source code), but
+it uses RAM for the persistent storage, which drastically decreases
+the potential device size.
+
+dm-flakey fails all I/O from all block locations at a specified time
+frequency, and not a given point in time.
+
+When a bad sector occurs on a hard disk drive, reads to that sector
+are failed by the device, usually resulting in an error code of EIO
+("I/O error") or ENODATA ("No data available").  However, a write to
+the sector may succeed, and result in the sector becoming readable
+after the device controller no longer experiences errors reading the
+sector (or after a reallocation of the sector).  However, there may
+be bad sectors that occur on the device in the future, in a different,
+unpredictable location.
+
+This target seeks to provide a device that can exhibit the behavior
+of a bad sector at a known sector location, at a known time, based
+on a large storage device (at least tens of gigabytes, not occupying
+system memory).
index 297251b..d63d78f 100644 (file)
@@ -21,6 +21,13 @@ mode it calculates and verifies the integrity tag internally. In this
 mode, the dm-integrity target can be used to detect silent data
 corruption on the disk or in the I/O path.
 
+There's an alternate mode of operation where dm-integrity uses bitmap
+instead of a journal. If a bit in the bitmap is 1, the corresponding
+region's data and integrity tags are not synchronized - if the machine
+crashes, the unsynchronized regions will be recalculated. The bitmap mode
+is faster than the journal mode, because we don't have to write the data
+twice, but it is also less reliable, because if data corruption happens
+when the machine crashes, it may not be detected.
 
 When loading the target for the first time, the kernel driver will format
 the device. But it will only format the device if the superblock contains
@@ -59,6 +66,10 @@ Target arguments:
                either both data and tag or none of them are written. The
                journaled mode degrades write throughput twice because the
                data have to be written twice.
+       B - bitmap mode - data and metadata are written without any
+               synchronization, the driver maintains a bitmap of dirty
+               regions where data and metadata don't match. This mode can
+               only be used with internal hash.
        R - recovery mode - in this mode, journal is not replayed,
                checksums are not checked and writes to the device are not
                allowed. This mode is useful for data recovery if the
@@ -79,6 +90,10 @@ interleave_sectors:number
        a power of two. If the device is already formatted, the value from
        the superblock is used.
 
+meta_device:device
+       Don't interleave the data and metadata on on device. Use a
+       separate device for metadata.
+
 buffer_sectors:number
        The number of sectors in one buffer. The value is rounded down to
        a power of two.
@@ -146,6 +161,15 @@ block_size:number
        Supported values are 512, 1024, 2048 and 4096 bytes.  If not
        specified the default block size is 512 bytes.
 
+sectors_per_bit:number
+       In the bitmap mode, this parameter specifies the number of
+       512-byte sectors that corresponds to one bitmap bit.
+
+bitmap_flush_interval:number
+       The bitmap flush interval in milliseconds. The metadata buffers
+       are synchronized when this interval expires.
+
+
 The journal mode (D/J), buffer_sectors, journal_watermark, commit_time can
 be changed when reloading the target (load an inactive table and swap the
 tables with suspend and resume). The other arguments should not be changed
@@ -167,7 +191,13 @@ The layout of the formatted block device:
          provides (i.e. the size of the device minus the size of all
          metadata and padding). The user of this target should not send
          bios that access data beyond the "provided data sectors" limit.
-       * flags - a flag is set if journal_mac is used
+       * flags
+         SB_FLAG_HAVE_JOURNAL_MAC - a flag is set if journal_mac is used
+         SB_FLAG_RECALCULATING - recalculating is in progress
+         SB_FLAG_DIRTY_BITMAP - journal area contains the bitmap of dirty
+               blocks
+       * log2(sectors per block)
+       * a position where recalculating finished
 * journal
        The journal is divided into sections, each section contains:
        * metadata area (4kiB), it contains journal entries
index f4d04a0..82edbaa 100644 (file)
@@ -11,3 +11,15 @@ Example:
                reg = <0xffd08000 0x1000>;
                cpu1-start-addr = <0xffd080c4>;
        };
+
+ARM64 - Stratix10
+Required properties:
+- compatible : "altr,sys-mgr-s10"
+- reg : Should contain 1 register range(address and length)
+        for system manager register.
+
+Example:
+        sysmgr@ffd12000 {
+               compatible = "altr,sys-mgr-s10";
+               reg = <0xffd12000 0x228>;
+       };
index 7f40cb5..061f7b9 100644 (file)
@@ -110,6 +110,7 @@ Board compatible values (alphabetically, grouped by SoC):
 
   - "amlogic,u200" (Meson g12a s905d2)
   - "amediatech,x96-max" (Meson g12a s905x2)
+  - "seirobotics,sei510" (Meson g12a s905x2)
 
 Amlogic Meson Firmware registers Interface
 ------------------------------------------
index e61d00e..9fbde40 100644 (file)
@@ -84,7 +84,7 @@ SHDWC SAMA5D2-Compatible Shutdown Controller
 1) shdwc node
 
 required properties:
-- compatible: should be "atmel,sama5d2-shdwc".
+- compatible: should be "atmel,sama5d2-shdwc" or "microchip,sam9x60-shdwc".
 - reg: should contain registers location and length
 - clocks: phandle to input clock.
 - #address-cells: should be one. The cell is the wake-up input index.
@@ -96,6 +96,9 @@ optional properties:
   microseconds. It's usually a board-related property.
 - atmel,wakeup-rtc-timer: boolean to enable Real-Time Clock wake-up.
 
+optional microchip,sam9x60-shdwc properties:
+- atmel,wakeup-rtt-timer: boolean to enable Real-time Timer Wake-up.
+
 The node contains child nodes for each wake-up input that the platform uses.
 
 2) input nodes
index 72d481c..5d7dbab 100644 (file)
@@ -22,9 +22,11 @@ Required properties:
 -------------------
 - compatible:  should be "fsl,imx-scu".
 - mbox-names:  should include "tx0", "tx1", "tx2", "tx3",
-                              "rx0", "rx1", "rx2", "rx3".
-- mboxes:      List of phandle of 4 MU channels for tx and 4 MU channels
-               for rx. All 8 MU channels must be in the same MU instance.
+                              "rx0", "rx1", "rx2", "rx3";
+               include "gip3" if want to support general MU interrupt.
+- mboxes:      List of phandle of 4 MU channels for tx, 4 MU channels for
+               rx, and 1 optional MU channel for general interrupt.
+               All MU channels must be in the same MU instance.
                Cross instances are not allowed. The MU instance can only
                be one of LSIO MU0~M4 for imx8qxp and imx8qm. Users need
                to make sure use the one which is not conflict with other
@@ -34,6 +36,7 @@ Required properties:
                Channel 1 must be "tx1" or "rx1".
                Channel 2 must be "tx2" or "rx2".
                Channel 3 must be "tx3" or "rx3".
+               General interrupt rx channel must be "gip3".
                e.g.
                mboxes = <&lsio_mu1 0 0
                          &lsio_mu1 0 1
@@ -42,10 +45,18 @@ Required properties:
                          &lsio_mu1 1 0
                          &lsio_mu1 1 1
                          &lsio_mu1 1 2
-                         &lsio_mu1 1 3>;
+                         &lsio_mu1 1 3
+                         &lsio_mu1 3 3>;
                See Documentation/devicetree/bindings/mailbox/fsl,mu.txt
                for detailed mailbox binding.
 
+Note: Each mu which supports general interrupt should have an alias correctly
+numbered in "aliases" node.
+e.g.
+aliases {
+       mu1 = &lsio_mu1;
+};
+
 i.MX SCU Client Device Node:
 ============================================================
 
@@ -124,6 +135,10 @@ Required properties:
 
 Example (imx8qxp):
 -------------
+aliases {
+       mu1 = &lsio_mu1;
+};
+
 lsio_mu1: mailbox@5d1c0000 {
        ...
        #mbox-cells = <2>;
@@ -133,7 +148,8 @@ firmware {
        scu {
                compatible = "fsl,imx-scu";
                mbox-names = "tx0", "tx1", "tx2", "tx3",
-                            "rx0", "rx1", "rx2", "rx3";
+                            "rx0", "rx1", "rx2", "rx3",
+                            "gip3";
                mboxes = <&lsio_mu1 0 0
                          &lsio_mu1 0 1
                          &lsio_mu1 0 2
@@ -141,7 +157,8 @@ firmware {
                          &lsio_mu1 1 0
                          &lsio_mu1 1 1
                          &lsio_mu1 1 2
-                         &lsio_mu1 1 3>;
+                         &lsio_mu1 1 3
+                         &lsio_mu1 3 3>;
 
                clk: clk {
                        compatible = "fsl,imx8qxp-clk", "fsl,scu-clk";
index 7e2cd6a..407138e 100644 (file)
@@ -51,6 +51,13 @@ properties:
           - const: i2se,duckbill-2
           - const: fsl,imx28
 
+      - description: i.MX50 based Boards
+        items:
+          - enum:
+              - fsl,imx50-evk
+              - kobo,aura
+          - const: fsl,imx50
+
       - description: i.MX51 Babbage Board
         items:
           - enum:
@@ -67,6 +74,7 @@ properties:
               - fsl,imx53-evk
               - fsl,imx53-qsb
               - fsl,imx53-smd
+              - menlo,m53menlo
           - const: fsl,imx53
 
       - description: i.MX6Q based Boards
@@ -90,6 +98,7 @@ properties:
       - description: i.MX6DL based Boards
         items:
           - enum:
+              - eckelmann,imx6dl-ci4x10
               - fsl,imx6dl-sabreauto      # i.MX6 DualLite/Solo SABRE Automotive Board
               - fsl,imx6dl-sabresd        # i.MX6 DualLite SABRE Smart Device Board
               - technologic,imx6dl-ts4900
@@ -137,10 +146,18 @@ properties:
           - const: fsl,imx6ull # This seems odd. Should be last?
           - const: fsl,imx6ulz
 
+      - description: i.MX7S based Boards
+        items:
+          - enum:
+              - tq,imx7s-mba7             # i.MX7S TQ MBa7 with TQMa7S SoM
+          - const: fsl,imx7s
+
       - description: i.MX7D based Boards
         items:
           - enum:
               - fsl,imx7d-sdb             # i.MX7 SabreSD Board
+              - tq,imx7d-mba7             # i.MX7D TQ MBa7 with TQMa7D SoM
+              - zii,imx7d-rpu2            # ZII RPU2 Board
           - const: fsl,imx7d
 
       - description:
@@ -154,6 +171,12 @@ properties:
           - const: compulab,cl-som-imx7
           - const: fsl,imx7d
 
+      - description: i.MX8MM based Boards
+        items:
+          - enum:
+              - fsl,imx8mm-evk            # i.MX8MM EVK Board
+          - const: fsl,imx8mm
+
       - description: i.MX8QXP based Boards
         items:
           - enum:
@@ -176,6 +199,19 @@ properties:
               - fsl,vf610
               - fsl,vf610m4
 
+      - description: ZII's VF610 based Boards
+        items:
+          - enum:
+              - zii,vf610cfu1      # ZII VF610 CFU1 Board
+              - zii,vf610dev-c     # ZII VF610 Development Board, Rev C
+              - zii,vf610dev-b     # ZII VF610 Development Board, Rev B
+              - zii,vf610scu4-aib  # ZII VF610 SCU4 AIB
+              - zii,vf610dtu       # ZII VF610 SSMB DTU Board
+              - zii,vf610spu3      # ZII VF610 SSMB SPU3 Board
+              - zii,vf610spb4      # ZII VF610 SPB4 Board
+          - const: zii,vf610dev
+          - const: fsl,vf610
+
       - description: LS1012A based Boards
         items:
           - enum:
diff --git a/Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml b/Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
new file mode 100644 (file)
index 0000000..f4f7451
--- /dev/null
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/intel-ixp4xx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Intel IXP4xx Device Tree Bindings
+
+maintainers:
+  - Linus Walleij <linus.walleij@linaro.org>
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+          - enum:
+              - linksys,nslu2
+          - const: intel,ixp42x
+      - items:
+          - enum:
+              - gateworks,gw2358
+          - const: intel,ixp43x
index 2ecc712..1c1e48f 100644 (file)
@@ -92,6 +92,9 @@ SoCs:
 - DRA718
   compatible = "ti,dra718", "ti,dra722", "ti,dra72", "ti,dra7"
 
+- AM5748
+  compatible = "ti,am5748", "ti,dra762", "ti,dra7"
+
 - AM5728
   compatible = "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7"
 
@@ -184,6 +187,9 @@ Boards:
 - AM57XX SBC-AM57x
   compatible = "compulab,sbc-am57x", "compulab,cl-som-am57x", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7"
 
+- AM5748 IDK
+  compatible = "ti,am5748-idk", "ti,am5748", "ti,dra762", "ti,dra7";
+
 - AM5728 IDK
   compatible = "ti,am5728-idk", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7"
 
index 061a03e..5c6bbf1 100644 (file)
@@ -97,6 +97,7 @@ properties:
           - enum:
               - friendlyarm,nanopc-t4
               - friendlyarm,nanopi-m4
+              - friendlyarm,nanopi-neo4
           - const: rockchip,rk3399
 
       - description: GeekBuying GeekBox
@@ -146,7 +147,7 @@ properties:
           - const: google,gru
           - const: rockchip,rk3399
 
-      - description: Google Jaq (Haier Chromebook 11 and more)
+      - description: Google Jaq (Haier Chromebook 11 and more w/ uSD)
         items:
           - const: google,veyron-jaq-rev5
           - const: google,veyron-jaq-rev4
@@ -159,6 +160,12 @@ properties:
 
       - description: Google Jerry (Hisense Chromebook C11 and more)
         items:
+          - const: google,veyron-jerry-rev15
+          - const: google,veyron-jerry-rev14
+          - const: google,veyron-jerry-rev13
+          - const: google,veyron-jerry-rev12
+          - const: google,veyron-jerry-rev11
+          - const: google,veyron-jerry-rev10
           - const: google,veyron-jerry-rev7
           - const: google,veyron-jerry-rev6
           - const: google,veyron-jerry-rev5
@@ -199,6 +206,17 @@ properties:
           - const: google,veyron
           - const: rockchip,rk3288
 
+      - description: Google Mighty (Haier Chromebook 11 and more w/ SD)
+        items:
+          - const: google,veyron-mighty-rev5
+          - const: google,veyron-mighty-rev4
+          - const: google,veyron-mighty-rev3
+          - const: google,veyron-mighty-rev2
+          - const: google,veyron-mighty-rev1
+          - const: google,veyron-mighty
+          - const: google,veyron
+          - const: rockchip,rk3288
+
       - description: Google Minnie (Asus Chromebook Flip C100P)
         items:
           - const: google,veyron-minnie-rev4
@@ -308,6 +326,11 @@ properties:
           - const: netxeon,r89
           - const: rockchip,rk3288
 
+      - description: Orange Pi RK3399 board
+        items:
+          - const: rockchip,rk3399-orangepi
+          - const: rockchip,rk3399
+
       - description: Phytec phyCORE-RK3288 Rapid Development Kit
         items:
           - const: phytec,rk3288-pcm-947
index 99980ae..c92d411 100644 (file)
@@ -5,10 +5,12 @@ Properties:
                  - " st,stm32mp157-syscfg " - for stm32mp157 based SoCs,
                  second value must be always "syscon".
    - reg : offset and length of the register set.
+   - clocks: phandle to the syscfg clock
 
  Example:
          syscfg: syscon@50020000 {
                  compatible = "st,stm32mp157-syscfg", "syscon";
                  reg = <0x50020000 0x400>;
+                 clocks = <&rcc SYSCFG>;
          };
 
diff --git a/Documentation/devicetree/bindings/arm/sunxi.txt b/Documentation/devicetree/bindings/arm/sunxi.txt
deleted file mode 100644 (file)
index 9254cbe..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-Allwinner sunXi Platforms Device Tree Bindings
-
-Each device tree must specify which Allwinner SoC it uses,
-using one of the following compatible strings:
-
-  allwinner,sun4i-a10
-  allwinner,sun5i-a10s
-  allwinner,sun5i-a13
-  allwinner,sun5i-r8
-  allwinner,sun6i-a31
-  allwinner,sun7i-a20
-  allwinner,sun8i-a23
-  allwinner,sun8i-a33
-  allwinner,sun8i-a83t
-  allwinner,sun8i-h2-plus
-  allwinner,sun8i-h3
-  allwinner,sun8i-r40
-  allwinner,sun8i-t3
-  allwinner,sun8i-v3s
-  allwinner,sun9i-a80
-  allwinner,sun50i-a64
-  allwinner,suniv-f1c100s
-  nextthing,gr8
diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
new file mode 100644 (file)
index 0000000..285f4fc
--- /dev/null
@@ -0,0 +1,807 @@
+# SPDX-License-Identifier: (GPL-2.0+ OR X11)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/sunxi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner platforms device tree bindings
+
+maintainers:
+  - Chen-Yu Tsai <wens@csie.org>
+  - Maxime Ripard <maxime.ripard@bootlin.com>
+
+properties:
+  $nodename:
+    const: '/'
+  compatible:
+    oneOf:
+
+      - description: Allwinner A23 Evaluation Board
+        items:
+          - const: allwinner,sun8i-a23-evb
+          - const: allwinner,sun8i-a23
+
+      - description: Allwinner A31 APP4 Evaluation Board
+        items:
+          - const: allwinner,app4-evb1
+          - const: allwinner,sun6i-a31
+
+      - description: Allwinner A83t Homlet Evaluation Board v2
+        items:
+          - const: allwinner,h8homlet-v2
+          - const: allwinner,sun8i-a83t
+
+      - description: Allwinner GA10H Quad Core Tablet v1.1
+        items:
+          - const: allwinner,ga10h-v1.1
+          - const: allwinner,sun8i-a33
+
+      - description: Allwinner GT90H Tablet v4
+        items:
+          - const: allwinner,gt90h-v4
+          - const: allwinner,sun8i-a23
+
+      - description: Allwinner R16 EVB (Parrot)
+        items:
+          - const: allwinner,parrot
+          - const: allwinner,sun8i-a33
+
+      - description: Amarula A64 Relic
+        items:
+          - const: amarula,a64-relic
+          - const: allwinner,sun50i-a64
+
+      - description: Auxtek T003 A10s HDMI TV Stick
+        items:
+          - const: allwinner,auxtek-t003
+          - const: allwinner,sun5i-a10s
+
+      - description: Auxtek T004 A10s HDMI TV Stick
+        items:
+          - const: allwinner,auxtek-t004
+          - const: allwinner,sun5i-a10s
+
+      - description: BA10 TV Box
+        items:
+          - const: allwinner,ba10-tvbox
+          - const: allwinner,sun4i-a10
+
+      - description: BananaPi
+        items:
+          - const: lemaker,bananapi
+          - const: allwinner,sun7i-a20
+
+      - description: BananaPi M1 Plus
+        items:
+          - const: sinovoip,bpi-m1-plus
+          - const: allwinner,sun7i-a20
+
+      - description: BananaPi M2
+        items:
+          - const: sinovoip,bpi-m2
+          - const: allwinner,sun6i-a31s
+
+      - description: BananaPi M2 Berry
+        items:
+          - const: sinovoip,bpi-m2-berry
+          - const: allwinner,sun8i-r40
+
+      - description: BananaPi M2 Plus
+        items:
+          - const: sinovoip,bpi-m2-plus
+          - const: allwinner,sun8i-h3
+
+      - description: BananaPi M2 Plus
+        items:
+          - const: sinovoip,bpi-m2-plus
+          - const: allwinner,sun50i-h5
+
+      - description: BananaPi M2 Plus v1.2
+        items:
+          - const: bananapi,bpi-m2-plus-v1.2
+          - const: allwinner,sun8i-h3
+
+      - description: BananaPi M2 Plus v1.2
+        items:
+          - const: bananapi,bpi-m2-plus-v1.2
+          - const: allwinner,sun50i-h5
+
+      - description: BananaPi M2 Magic
+        items:
+          - const: sinovoip,bananapi-m2m
+          - const: allwinner,sun8i-a33
+
+      - description: BananaPi M2 Ultra
+        items:
+          - const: sinovoip,bpi-m2-ultra
+          - const: allwinner,sun8i-r40
+
+      - description: BananaPi M2 Zero
+        items:
+          - const: sinovoip,bpi-m2-zero
+          - const: allwinner,sun8i-h2-plus
+
+      - description: BananaPi M3
+        items:
+          - const: sinovoip,bpi-m3
+          - const: allwinner,sun8i-a83t
+
+      - description: BananaPi M64
+        items:
+          - const: sinovoip,bananapi-m64
+          - const: allwinner,sun50i-a64
+
+      - description: BananaPro
+        items:
+          - const: lemaker,bananapro
+          - const: allwinner,sun7i-a20
+
+      - description: Beelink GS1
+        items:
+          - const: azw,beelink-gs1
+          - const: allwinner,sun50i-h6
+
+      - description: Beelink X2
+        items:
+          - const: roofull,beelink-x2
+          - const: allwinner,sun8i-h3
+
+      - description: Chuwi V7 CW0825
+        items:
+          - const: chuwi,v7-cw0825
+          - const: allwinner,sun4i-a10
+
+      - description: Colorfly E708 Q1 Tablet
+        items:
+          - const: colorfly,e708-q1
+          - const: allwinner,sun6i-a31s
+
+      - description: CSQ CS908 Set Top Box
+        items:
+          - const: csq,cs908
+          - const: allwinner,sun6i-a31s
+
+      - description: Cubietech Cubieboard
+        items:
+          - const: cubietech,a10-cubieboard
+          - const: allwinner,sun4i-a10
+
+      - description: Cubietech Cubieboard2
+        items:
+          - const: cubietech,cubieboard2
+          - const: allwinner,sun7i-a20
+
+      - description: Cubietech Cubieboard4
+        items:
+          - const: cubietech,a80-cubieboard4
+          - const: allwinner,sun9i-a80
+
+      - description: Cubietech Cubietruck
+        items:
+          - const: cubietech,cubietruck
+          - const: allwinner,sun7i-a20
+
+      - description: Cubietech Cubietruck Plus
+        items:
+          - const: cubietech,cubietruck-plus
+          - const: allwinner,sun8i-a83t
+
+      - description: Difrnce DIT4350
+        items:
+          - const: difrnce,dit4350
+          - const: allwinner,sun5i-a13
+
+      - description: Dserve DSRV9703C
+        items:
+          - const: dserve,dsrv9703c
+          - const: allwinner,sun4i-a10
+
+      - description: Empire Electronix D709 Tablet
+        items:
+          - const: empire-electronix,d709
+          - const: allwinner,sun5i-a13
+
+      - description: Empire Electronix M712 Tablet
+        items:
+          - const: empire-electronix,m712
+          - const: allwinner,sun5i-a13
+
+      - description: FriendlyARM NanoPi A64
+        items:
+          - const: friendlyarm,nanopi-a64
+          - const: allwinner,sun50i-a64
+
+      - description: FriendlyARM NanoPi M1
+        items:
+          - const: friendlyarm,nanopi-m1
+          - const: allwinner,sun8i-h3
+
+      - description: FriendlyARM NanoPi M1 Plus
+        items:
+          - const: friendlyarm,nanopi-m1-plus
+          - const: allwinner,sun8i-h3
+
+      - description: FriendlyARM NanoPi Neo
+        items:
+          - const: friendlyarm,nanopi-neo
+          - const: allwinner,sun8i-h3
+
+      - description: FriendlyARM NanoPi Neo 2
+        items:
+          - const: friendlyarm,nanopi-neo2
+          - const: allwinner,sun50i-h5
+
+      - description: FriendlyARM NanoPi Neo Air
+        items:
+          - const: friendlyarm,nanopi-neo-air
+          - const: allwinner,sun8i-h3
+
+      - description: FriendlyARM NanoPi Neo Plus2
+        items:
+          - const: friendlyarm,nanopi-neo-plus2
+          - const: allwinner,sun50i-h5
+
+      - description: Gemei G9 Tablet
+        items:
+          - const: gemei,g9
+          - const: allwinner,sun4i-a10
+
+      - description: Hyundai A7HD
+        items:
+          - const: hyundai,a7hd
+          - const: allwinner,sun4i-a10
+
+      - description: HSG H702
+        items:
+          - const: hsg,h702
+          - const: allwinner,sun5i-a13
+
+      - description: I12 TV Box
+        items:
+          - const: allwinner,i12-tvbox
+          - const: allwinner,sun7i-a20
+
+      - description: ICNova A20 SWAC
+        items:
+          - const: swac,icnova-a20-swac
+          - const: incircuit,icnova-a20
+          - const: allwinner,sun7i-a20
+
+      - description: INet-1
+        items:
+          - const: inet-tek,inet1
+          - const: allwinner,sun4i-a10
+
+      - description: iNet-86DZ Rev 01
+        items:
+          - const: primux,inet86dz
+          - const: allwinner,sun8i-a23
+
+      - description: iNet-9F Rev 03
+        items:
+          - const: inet-tek,inet9f-rev03
+          - const: allwinner,sun4i-a10
+
+      - description: iNet-97F Rev 02
+        items:
+          - const: primux,inet97fv2
+          - const: allwinner,sun4i-a10
+
+      - description: iNet-98V Rev 02
+        items:
+          - const: primux,inet98v-rev2
+          - const: allwinner,sun5i-a13
+
+      - description: iNet D978 Rev 02 Tablet
+        items:
+          - const: primux,inet-d978-rev2
+          - const: allwinner,sun8i-a33
+
+      - description: iNet Q972 Tablet
+        items:
+          - const: inet-tek,inet-q972
+          - const: allwinner,sun6i-a31s
+
+      - description: Itead Ibox A20
+        items:
+          - const: itead,itead-ibox-a20
+          - const: allwinner,sun7i-a20
+
+      - description: Itead Iteaduino Plus A10
+        items:
+          - const: itead,iteaduino-plus-a10
+          - const: allwinner,sun4i-a10
+
+      - description: Jesurun Q5
+        items:
+          - const: jesurun,q5
+          - const: allwinner,sun4i-a10
+
+      - description: Lamobo R1
+        items:
+          - const: lamobo,lamobo-r1
+          - const: allwinner,sun7i-a20
+
+      - description: Libre Computer Board ALL-H3-CC H2+
+        items:
+          - const: libretech,all-h3-cc-h2-plus
+          - const: allwinner,sun8i-h2-plus
+
+      - description: Libre Computer Board ALL-H3-CC H3
+        items:
+          - const: libretech,all-h3-cc-h3
+          - const: allwinner,sun8i-h3
+
+      - description: Libre Computer Board ALL-H3-CC H5
+        items:
+          - const: libretech,all-h3-cc-h5
+          - const: allwinner,sun50i-h5
+
+      - description: Lichee Pi One
+        items:
+          - const: licheepi,licheepi-one
+          - const: allwinner,sun5i-a13
+
+      - description: Lichee Pi Zero
+        items:
+          - const: licheepi,licheepi-zero
+          - const: allwinner,sun8i-v3s
+
+      - description: Lichee Pi Zero (with Dock)
+        items:
+          - const: licheepi,licheepi-zero-dock
+          - const: licheepi,licheepi-zero
+          - const: allwinner,sun8i-v3s
+
+      - description: Linksprite PCDuino
+        items:
+          - const: linksprite,a10-pcduino
+          - const: allwinner,sun4i-a10
+
+      - description: Linksprite PCDuino2
+        items:
+          - const: linksprite,a10-pcduino2
+          - const: allwinner,sun4i-a10
+
+      - description: Linksprite PCDuino3
+        items:
+          - const: linksprite,pcduino3
+          - const: allwinner,sun7i-a20
+
+      - description: Linksprite PCDuino3 Nano
+        items:
+          - const: linksprite,pcduino3-nano
+          - const: allwinner,sun7i-a20
+
+      - description: HAOYU Electronics Marsboard A10
+        items:
+          - const: haoyu,a10-marsboard
+          - const: allwinner,sun4i-a10
+
+      - description: MapleBoard MP130
+        items:
+          - const: mapleboard,mp130
+          - const: allwinner,sun8i-h3
+
+      - description: Mele A1000
+        items:
+          - const: mele,a1000
+          - const: allwinner,sun4i-a10
+
+      - description: Mele A1000G Quad Set Top Box
+        items:
+          - const: mele,a1000g-quad
+          - const: allwinner,sun6i-a31
+
+      - description: Mele I7 Quad Set Top Box
+        items:
+          - const: mele,i7
+          - const: allwinner,sun6i-a31
+
+      - description: Mele M3
+        items:
+          - const: mele,m3
+          - const: allwinner,sun7i-a20
+
+      - description: Mele M9 Set Top Box
+        items:
+          - const: mele,m9
+          - const: allwinner,sun6i-a31
+
+      - description: Merrii A20 Hummingboard
+        items:
+          - const: merrii,a20-hummingbird
+          - const: allwinner,sun7i-a20
+
+      - description: Merrii A31 Hummingboard
+        items:
+          - const: merrii,a31-hummingbird
+          - const: allwinner,sun6i-a31
+
+      - description: Merrii A80 Optimus
+        items:
+          - const: merrii,a80-optimus
+          - const: allwinner,sun9i-a80
+
+      - description: Miniand Hackberry
+        items:
+          - const: miniand,hackberry
+          - const: allwinner,sun4i-a10
+
+      - description: MK802
+        items:
+          - const: allwinner,mk802
+          - const: allwinner,sun4i-a10
+
+      - description: MK802-A10s
+        items:
+          - const: allwinner,a10s-mk802
+          - const: allwinner,sun5i-a10s
+
+      - description: MK802-II
+        items:
+          - const: allwinner,mk802ii
+          - const: allwinner,sun4i-a10
+
+      - description: MK808c
+        items:
+          - const: allwinner,mk808c
+          - const: allwinner,sun7i-a20
+
+      - description: MSI Primo81 Tablet
+        items:
+          - const: msi,primo81
+          - const: allwinner,sun6i-a31s
+
+      - description: Emlid Neutis N5 Developper Board
+        items:
+          - const: emlid,neutis-n5-devboard
+          - const: emlid,neutis-n5
+          - const: allwinner,sun50i-h5
+
+      - description: NextThing Co. CHIP
+        items:
+          - const: nextthing,chip
+          - const: allwinner,sun5i-r8
+          - const: allwinner,sun5i-a13
+
+      - description: NextThing Co. CHIP Pro
+        items:
+          - const: nextthing,chip-pro
+          - const: nextthing,gr8
+
+      - description: NextThing Co. GR8 Evaluation Board
+        items:
+          - const: nextthing,gr8-evb
+          - const: nextthing,gr8
+
+      - description: Nintendo NES Classic
+        items:
+          - const: nintendo,nes-classic
+          - const: allwinner,sun8i-r16
+          - const: allwinner,sun8i-a33
+
+      - description: Nintendo Super NES Classic
+        items:
+          - const: nintendo,super-nes-classic
+          - const: nintendo,nes-classic
+          - const: allwinner,sun8i-r16
+          - const: allwinner,sun8i-a33
+
+      - description: Oceanic 5inMFD (5205)
+        items:
+          - const: oceanic,5205-5inmfd
+          - const: allwinner,sun50i-a64
+
+      - description: Olimex A10-OlinuXino LIME
+        items:
+          - const: olimex,a10-olinuxino-lime
+          - const: allwinner,sun4i-a10
+
+      - description: Olimex A10s-OlinuXino Micro
+        items:
+          - const: olimex,a10s-olinuxino-micro
+          - const: allwinner,sun5i-a10s
+
+      - description: Olimex A13-OlinuXino
+        items:
+          - const: olimex,a13-olinuxino
+          - const: allwinner,sun5i-a13
+
+      - description: Olimex A13-OlinuXino Micro
+        items:
+          - const: olimex,a13-olinuxino-micro
+          - const: allwinner,sun5i-a13
+
+      - description: Olimex A20-Olimex SOM Evaluation Board
+        items:
+          - const: olimex,a20-olimex-som-evb
+          - const: allwinner,sun7i-a20
+
+      - description: Olimex A20-Olimex SOM Evaluation Board (with eMMC)
+        items:
+          - const: olimex,a20-olimex-som-evb-emmc
+          - const: allwinner,sun7i-a20
+
+      - description: Olimex A20-OlinuXino LIME
+        items:
+          - const: olimex,a20-olinuxino-lime
+          - const: allwinner,sun7i-a20
+
+      - description: Olimex A20-OlinuXino LIME2
+        items:
+          - const: olimex,a20-olinuxino-lime2
+          - const: allwinner,sun7i-a20
+
+      - description: Olimex A20-OlinuXino LIME2 (with eMMC)
+        items:
+          - const: olimex,a20-olinuxino-lime2-emmc
+          - const: allwinner,sun7i-a20
+
+      - description: Olimex A20-OlinuXino Micro
+        items:
+          - const: olimex,a20-olinuxino-micro
+          - const: allwinner,sun7i-a20
+
+      - description: Olimex A20-OlinuXino Micro (with eMMC)
+        items:
+          - const: olimex,a20-olinuxino-micro-emmc
+          - const: allwinner,sun7i-a20
+
+      - description: Olimex A20-SOM204 Evaluation Board
+        items:
+          - const: olimex,a20-olimex-som204-evb
+          - const: allwinner,sun7i-a20
+
+      - description: Olimex A20-SOM204 Evaluation Board (with eMMC)
+        items:
+          - const: olimex,a20-olimex-som204-evb-emmc
+          - const: allwinner,sun7i-a20
+
+      - description: Olimex A33-OlinuXino
+        items:
+          - const: olimex,a33-olinuxino
+          - const: allwinner,sun8i-a33
+
+      - description: Olimex A64-OlinuXino
+        items:
+          - const: olimex,a64-olinuxino
+          - const: allwinner,sun50i-a64
+
+      - description: Olimex A64 Teres-I
+        items:
+          - const: olimex,a64-teres-i
+          - const: allwinner,sun50i-a64
+
+      - description: Pine64
+        items:
+          - const: pine64,pine64
+          - const: allwinner,sun50i-a64
+
+      - description: Pine64+
+        items:
+          - const: pine64,pine64-plus
+          - const: allwinner,sun50i-a64
+
+      - description: Pine64 PineH64
+        items:
+          - const: pine64,pine-h64
+          - const: allwinner,sun50i-h6
+
+      - description: Pine64 LTS
+        items:
+          - const: pine64,pine64-lts
+          - const: allwinner,sun50i-r18
+          - const: allwinner,sun50i-a64
+
+      - description: Pine64 Pinebook
+        items:
+          - const: pine64,pinebook
+          - const: allwinner,sun50i-a64
+
+      - description: Pine64 SoPine Baseboard
+        items:
+          - const: pine64,sopine-baseboard
+          - const: pine64,sopine
+          - const: allwinner,sun50i-a64
+
+      - description: PineRiver Mini X-Plus
+        items:
+          - const: pineriver,mini-xplus
+          - const: allwinner,sun4i-a10
+
+      - description: Point of View Protab2-IPS9
+        items:
+          - const: pov,protab2-ips9
+          - const: allwinner,sun4i-a10
+
+      - description: Polaroid MID2407PXE03 Tablet
+        items:
+          - const: polaroid,mid2407pxe03
+          - const: allwinner,sun8i-a23
+
+      - description: Polaroid MID2809PXE04 Tablet
+        items:
+          - const: polaroid,mid2809pxe04
+          - const: allwinner,sun8i-a23
+
+      - description: Q8 A13 Tablet
+        items:
+          - const: allwinner,q8-a13
+          - const: allwinner,sun5i-a13
+
+      - description: Q8 A23 Tablet
+        items:
+          - const: allwinner,q8-a23
+          - const: allwinner,sun8i-a23
+
+      - description: Q8 A33 Tablet
+        items:
+          - const: allwinner,q8-a33
+          - const: allwinner,sun8i-a33
+
+      - description: Qihua CQA3T BV3
+        items:
+          - const: qihua,t3-cqa3t-bv3
+          - const: allwinner,sun8i-t3
+          - const: allwinner,sun8i-r40
+
+      - description: R7 A10s HDMI TV Stick
+        items:
+          - const: allwinner,r7-tv-dongle
+          - const: allwinner,sun5i-a10s
+
+      - description: RerVision H3-DVK
+        items:
+          - const: rervision,h3-dvk
+          - const: allwinner,sun8i-h3
+
+      - description: Sinlinx SinA31s Core Board
+        items:
+          - const: sinlinx,sina31s
+          - const: allwinner,sun6i-a31s
+
+      - description: Sinlinx SinA31s Development Board
+        items:
+          - const: sinlinx,sina31s-sdk
+          - const: allwinner,sun6i-a31s
+
+      - description: Sinlinx SinA33
+        items:
+          - const: sinlinx,sina33
+          - const: allwinner,sun8i-a33
+
+      - description: TBS A711 Tablet
+        items:
+          - const: tbs-biometrics,a711
+          - const: allwinner,sun8i-a83t
+
+      - description: Utoo P66
+        items:
+          - const: utoo,p66
+          - const: allwinner,sun5i-a13
+
+      - description: Wexler TAB7200
+        items:
+          - const: wexler,tab7200
+          - const: allwinner,sun7i-a20
+
+      - description: WITS A31 Colombus Evaluation Board
+        items:
+          - const: wits,colombus
+          - const: allwinner,sun6i-a31
+
+      - description: WITS Pro A20 DKT
+        items:
+          - const: wits,pro-a20-dkt
+          - const: allwinner,sun7i-a20
+
+      - description: Wobo i5
+        items:
+          - const: wobo,a10s-wobo-i5
+          - const: allwinner,sun5i-a10s
+
+      - description: Yones TopTech BS1078 v2 Tablet
+        items:
+          - const: yones-toptech,bs1078-v2
+          - const: allwinner,sun6i-a31s
+
+      - description: Xunlong OrangePi
+        items:
+          - const: xunlong,orangepi
+          - const: allwinner,sun7i-a20
+
+      - description: Xunlong OrangePi 2
+        items:
+          - const: xunlong,orangepi-2
+          - const: allwinner,sun8i-h3
+
+      - description: Xunlong OrangePi 3
+        items:
+          - const: xunlong,orangepi-3
+          - const: allwinner,sun50i-h6
+
+      - description: Xunlong OrangePi Lite
+        items:
+          - const: xunlong,orangepi-lite
+          - const: allwinner,sun8i-h3
+
+      - description: Xunlong OrangePi Lite2
+        items:
+          - const: xunlong,orangepi-lite2
+          - const: allwinner,sun50i-h6
+
+      - description: Xunlong OrangePi Mini
+        items:
+          - const: xunlong,orangepi-mini
+          - const: allwinner,sun7i-a20
+
+      - description: Xunlong OrangePi One
+        items:
+          - const: xunlong,orangepi-one
+          - const: allwinner,sun8i-h3
+
+      - description: Xunlong OrangePi One Plus
+        items:
+          - const: xunlong,orangepi-one-plus
+          - const: allwinner,sun50i-h6
+
+      - description: Xunlong OrangePi PC
+        items:
+          - const: xunlong,orangepi-pc
+          - const: allwinner,sun8i-h3
+
+      - description: Xunlong OrangePi PC 2
+        items:
+          - const: xunlong,orangepi-pc2
+          - const: allwinner,sun50i-h5
+
+      - description: Xunlong OrangePi PC Plus
+        items:
+          - const: xunlong,orangepi-pc-plus
+          - const: allwinner,sun8i-h3
+
+      - description: Xunlong OrangePi Plus
+        items:
+          - const: xunlong,orangepi-plus
+          - const: allwinner,sun8i-h3
+
+      - description: Xunlong OrangePi Plus 2E
+        items:
+          - const: xunlong,orangepi-plus2e
+          - const: allwinner,sun8i-h3
+
+      - description: Xunlong OrangePi Prime
+        items:
+          - const: xunlong,orangepi-prime
+          - const: allwinner,sun50i-h5
+
+      - description: Xunlong OrangePi R1
+        items:
+          - const: xunlong,orangepi-r1
+          - const: allwinner,sun8i-h2-plus
+
+      - description: Xunlong OrangePi Win
+        items:
+          - const: xunlong,orangepi-win
+          - const: allwinner,sun50i-a64
+
+      - description: Xunlong OrangePi Zero
+        items:
+          - const: xunlong,orangepi-zero
+          - const: allwinner,sun8i-h2-plus
+
+      - description: Xunlong OrangePi Zero Plus
+        items:
+          - const: xunlong,orangepi-zero-plus
+          - const: allwinner,sun50i-h5
+
+      - description: Xunlong OrangePi Zero Plus2
+        items:
+          - const: xunlong,orangepi-zero-plus2
+          - const: allwinner,sun50i-h5
+
+      - description: Xunlong OrangePi Zero Plus2
+        items:
+          - const: xunlong,orangepi-zero-plus2-h3
+          - const: allwinner,sun8i-h3
index 85a23f5..233eb82 100644 (file)
@@ -94,6 +94,8 @@ Optional properties:
 
 - ti,no-idle-on-init   interconnect target module should not be idled at init
 
+- ti,no-idle           interconnect target module should not be idled
+
 Example: Single instance of MUSB controller on omap4 using interconnect ranges
 using offsets from l4_cfg second segment (0x4a000000 + 0x80000 = 0x4a0ab000):
 
@@ -131,6 +133,6 @@ using offsets from l4_cfg second segment (0x4a000000 + 0x80000 = 0x4a0ab000):
                };
        };
 
-Note that other SoCs, such as am335x can have multipe child devices. On am335x
+Note that other SoCs, such as am335x can have multiple child devices. On am335x
 there are two MUSB instances, two USB PHY instances, and a single CPPI41 DMA
-instance as children of a single interconnet target module.
+instance as children of a single interconnect target module.
diff --git a/Documentation/devicetree/bindings/clock/xlnx,zynqmp-clk.txt b/Documentation/devicetree/bindings/clock/xlnx,zynqmp-clk.txt
new file mode 100644 (file)
index 0000000..391ee1a
--- /dev/null
@@ -0,0 +1,63 @@
+--------------------------------------------------------------------------
+Device Tree Clock bindings for the Zynq Ultrascale+ MPSoC controlled using
+Zynq MPSoC firmware interface
+--------------------------------------------------------------------------
+The clock controller is a h/w block of Zynq Ultrascale+ MPSoC clock
+tree. It reads required input clock frequencies from the devicetree and acts
+as clock provider for all clock consumers of PS clocks.
+
+See clock_bindings.txt for more information on the generic clock bindings.
+
+Required properties:
+ - #clock-cells:       Must be 1
+ - compatible:         Must contain:   "xlnx,zynqmp-clk"
+ - clocks:             List of clock specifiers which are external input
+                       clocks to the given clock controller. Please refer
+                       the next section to find the input clocks for a
+                       given controller.
+ - clock-names:                List of clock names which are exteral input clocks
+                       to the given clock controller. Please refer to the
+                       clock bindings for more details.
+
+Input clocks for zynqmp Ultrascale+ clock controller:
+
+The Zynq UltraScale+ MPSoC has one primary and four alternative reference clock
+inputs. These required clock inputs are:
+ - pss_ref_clk (PS reference clock)
+ - video_clk (reference clock for video system )
+ - pss_alt_ref_clk (alternative PS reference clock)
+ - aux_ref_clk
+ - gt_crx_ref_clk (transceiver reference clock)
+
+The following strings are optional parameters to the 'clock-names' property in
+order to provide an optional (E)MIO clock source:
+ - swdt0_ext_clk
+ - swdt1_ext_clk
+ - gem0_emio_clk
+ - gem1_emio_clk
+ - gem2_emio_clk
+ - gem3_emio_clk
+ - mio_clk_XX          # with XX = 00..77
+ - mio_clk_50_or_51    #for the mux clock to gem tsu from 50 or 51
+
+
+Output clocks are registered based on clock information received
+from firmware. Output clocks indexes are mentioned in
+include/dt-bindings/clock/xlnx-zynqmp-clk.h.
+
+-------
+Example
+-------
+
+firmware {
+       zynqmp_firmware: zynqmp-firmware {
+               compatible = "xlnx,zynqmp-firmware";
+               method = "smc";
+               zynqmp_clk: clock-controller {
+                       #clock-cells = <1>;
+                       compatible = "xlnx,zynqmp-clk";
+                       clocks = <&pss_ref_clk>, <&video_clk>, <&pss_alt_ref_clk>, <&aux_ref_clk>, <&gt_crx_ref_clk>;
+                       clock-names = "pss_ref_clk", "video_clk", "pss_alt_ref_clk","aux_ref_clk", "gt_crx_ref_clk";
+               };
+       };
+};
index 3c9a57a..9d8bbac 100644 (file)
@@ -9,6 +9,7 @@ Required properties:
       "fsl,imx53-sdma"
       "fsl,imx6q-sdma"
       "fsl,imx7d-sdma"
+      "fsl,imx8mq-sdma"
   The -to variants should be preferred since they allow to determine the
   correct ROM script addresses needed for the driver to work without additional
   firmware.
diff --git a/Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml b/Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml
new file mode 100644 (file)
index 0000000..8cb136c
--- /dev/null
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2019 Linaro Ltd.
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/firmware/intel-ixp4xx-network-processing-engine.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Intel IXP4xx Network Processing Engine
+
+maintainers:
+  - Linus Walleij <linus.walleij@linaro.org>
+
+description: |
+  On the IXP4xx SoCs, the Network Processing Engine (NPE) is a small
+  processor that can load a firmware to perform offloading of networking
+  and crypto tasks. It also manages the MDIO bus to the ethernet PHYs
+  on the IXP4xx platform. All IXP4xx platforms have three NPEs at
+  consecutive memory locations. They are all included in the same
+  device node since they are not independent of each other.
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+          - const: intel,ixp4xx-network-processing-engine
+
+  reg:
+    minItems: 3
+    maxItems: 3
+    items:
+      - description: NPE0 register range
+      - description: NPE1 register range
+      - description: NPE2 register range
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+    npe@c8006000 {
+         compatible = "intel,ixp4xx-network-processing-engine";
+         reg = <0xc8006000 0x1000>, <0xc8007000 0x1000>, <0xc8008000 0x1000>;
+    };
index 614bac5..a4fe136 100644 (file)
@@ -17,53 +17,6 @@ Required properties:
                  - "smc" : SMC #0, following the SMCCC
                  - "hvc" : HVC #0, following the SMCCC
 
---------------------------------------------------------------------------
-Device Tree Clock bindings for the Zynq Ultrascale+ MPSoC controlled using
-Zynq MPSoC firmware interface
---------------------------------------------------------------------------
-The clock controller is a h/w block of Zynq Ultrascale+ MPSoC clock
-tree. It reads required input clock frequencies from the devicetree and acts
-as clock provider for all clock consumers of PS clocks.
-
-See clock_bindings.txt for more information on the generic clock bindings.
-
-Required properties:
- - #clock-cells:       Must be 1
- - compatible:         Must contain:   "xlnx,zynqmp-clk"
- - clocks:             List of clock specifiers which are external input
-                       clocks to the given clock controller. Please refer
-                       the next section to find the input clocks for a
-                       given controller.
- - clock-names:                List of clock names which are exteral input clocks
-                       to the given clock controller. Please refer to the
-                       clock bindings for more details.
-
-Input clocks for zynqmp Ultrascale+ clock controller:
-
-The Zynq UltraScale+ MPSoC has one primary and four alternative reference clock
-inputs. These required clock inputs are:
- - pss_ref_clk (PS reference clock)
- - video_clk (reference clock for video system )
- - pss_alt_ref_clk (alternative PS reference clock)
- - aux_ref_clk
- - gt_crx_ref_clk (transceiver reference clock)
-
-The following strings are optional parameters to the 'clock-names' property in
-order to provide an optional (E)MIO clock source:
- - swdt0_ext_clk
- - swdt1_ext_clk
- - gem0_emio_clk
- - gem1_emio_clk
- - gem2_emio_clk
- - gem3_emio_clk
- - mio_clk_XX          # with XX = 00..77
- - mio_clk_50_or_51    #for the mux clock to gem tsu from 50 or 51
-
-
-Output clocks are registered based on clock information received
-from firmware. Output clocks indexes are mentioned in
-include/dt-bindings/clock/xlnx,zynqmp-clk.h.
-
 -------
 Example
 -------
@@ -72,11 +25,6 @@ firmware {
        zynqmp_firmware: zynqmp-firmware {
                compatible = "xlnx,zynqmp-firmware";
                method = "smc";
-               zynqmp_clk: clock-controller {
-                       #clock-cells = <1>;
-                       compatible = "xlnx,zynqmp-clk";
-                       clocks = <&pss_ref_clk>, <&video_clk>, <&pss_alt_ref_clk>, <&aux_ref_clk>, <&gt_crx_ref_clk>;
-                       clock-names = "pss_ref_clk", "video_clk", "pss_alt_ref_clk","aux_ref_clk", "gt_crx_ref_clk";
-               };
+               ...
        };
 };
diff --git a/Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.txt b/Documentation/devicetree/bindings/fpga/xlnx,zynqmp-pcap-fpga.txt
new file mode 100644 (file)
index 0000000..3052bf6
--- /dev/null
@@ -0,0 +1,25 @@
+Devicetree bindings for Zynq Ultrascale MPSoC FPGA Manager.
+The ZynqMP SoC uses the PCAP (Processor configuration Port) to configure the
+Programmable Logic (PL). The configuration uses  the firmware interface.
+
+Required properties:
+- compatible: should contain "xlnx,zynqmp-pcap-fpga"
+
+Example for full FPGA configuration:
+
+       fpga-region0 {
+               compatible = "fpga-region";
+               fpga-mgr = <&zynqmp_pcap>;
+               #address-cells = <0x1>;
+               #size-cells = <0x1>;
+       };
+
+       firmware {
+               zynqmp_firmware: zynqmp-firmware {
+                       compatible = "xlnx,zynqmp-firmware";
+                       method = "smc";
+                       zynqmp_pcap: pcap {
+                               compatible = "xlnx,zynqmp-pcap-fpga";
+                       };
+               };
+       };
index 18a2cde..1b1a741 100644 (file)
@@ -37,6 +37,20 @@ Optional properties:
 - operating-points-v2 : Refer to Documentation/devicetree/bindings/opp/opp.txt
   for details.
 
+- resets : Phandle of the GPU reset line.
+
+Vendor-specific bindings
+------------------------
+
+The Mali GPU is integrated very differently from one SoC to
+another. In order to accomodate those differences, you have the option
+to specify one more vendor-specific compatible, among:
+
+- "amlogic,meson-gxm-mali"
+  Required properties:
+  - resets : Should contain phandles of :
+    + GPU reset line
+    + GPU APB glue reset line
 
 Example for a Mali-T760:
 
index 6ced829..41b7676 100644 (file)
@@ -21,8 +21,6 @@ Optional properties:
 Example:
        fan0: pwm-fan {
                compatible = "pwm-fan";
-               cooling-min-state = <0>;
-               cooling-max-state = <3>;
                #cooling-cells = <2>;
                pwms = <&pwm 0 10000 0>;
                cooling-levels = <0 102 170 230>;
index 5c184b9..f1f3a55 100644 (file)
@@ -10,6 +10,7 @@ Required properties:
 - clocks: The root clock of the ADC controller
 - clock-names: Must contain "adc", matching entry in the clocks property
 - vref-supply: The regulator supply ADC reference voltage
+- #io-channel-cells: Must be 1 as per ../iio-bindings.txt
 
 Example:
 adc1: adc@30610000 {
@@ -19,4 +20,5 @@ adc1: adc@30610000 {
        clocks = <&clks IMX7D_ADC_ROOT_CLK>;
        clock-names = "adc";
        vref-supply = <&reg_vcc_3v3_mcu>;
+       #io-channel-cells = <1>;
 };
index c81993f..c878768 100644 (file)
@@ -13,6 +13,7 @@ VADC node:
     Definition: Should contain "qcom,spmi-vadc".
                 Should contain "qcom,spmi-adc5" for PMIC5 ADC driver.
                 Should contain "qcom,spmi-adc-rev2" for PMIC rev2 ADC driver.
+                Should contain "qcom,pms405-adc" for PMS405 PMIC
 
 - reg:
     Usage: required
diff --git a/Documentation/devicetree/bindings/input/gpio-vibrator.yaml b/Documentation/devicetree/bindings/input/gpio-vibrator.yaml
new file mode 100644 (file)
index 0000000..903475f
--- /dev/null
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/bindings/input/gpio-vibrator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: GPIO vibrator
+
+maintainers:
+  - Luca Weiss <luca@z3ntu.xyz>
+
+description: |+
+  Registers a GPIO device as vibrator, where the on/off capability is controlled by a GPIO.
+
+properties:
+  compatible:
+    const: gpio-vibrator
+
+  enable-gpios:
+    maxItems: 1
+
+  vcc-supply:
+    description: Regulator that provides power
+
+required:
+  - compatible
+  - enable-gpios
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    vibrator {
+        compatible = "gpio-vibrator";
+        enable-gpios = <&msmgpio 86 GPIO_ACTIVE_HIGH>;
+        vcc-supply = <&pm8941_l18>;
+    };
index bcf62f8..2b075a0 100644 (file)
@@ -8,6 +8,7 @@ Required Properties:
 - reg: Physical base address of the controller and length of memory mapped
   region.
 - interrupts: The interrupt number to the cpu.
+- clocks: phandle to clock controller plus clock-specifier pair
 - nxp,debounce-delay-ms: Debounce delay in ms
 - nxp,scan-delay-ms: Repeated scan period in ms
 - linux,keymap: the key-code to be reported when the key is pressed
@@ -22,7 +23,9 @@ Example:
        key@40050000 {
                compatible = "nxp,lpc3220-key";
                reg = <0x40050000 0x1000>;
-               interrupts = <54 0>;
+               clocks = <&clk LPC32XX_CLK_KEY>;
+               interrupt-parent = <&sic1>;
+               interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
                keypad,num-rows = <1>;
                keypad,num-columns = <1>;
                nxp,debounce-delay-ms = <3>;
diff --git a/Documentation/devicetree/bindings/input/max77650-onkey.txt b/Documentation/devicetree/bindings/input/max77650-onkey.txt
new file mode 100644 (file)
index 0000000..477dc74
--- /dev/null
@@ -0,0 +1,26 @@
+Onkey driver for MAX77650 PMIC from Maxim Integrated.
+
+This module is part of the MAX77650 MFD device. For more details
+see Documentation/devicetree/bindings/mfd/max77650.txt.
+
+The onkey controller is represented as a sub-node of the PMIC node on
+the device tree.
+
+Required properties:
+--------------------
+- compatible:          Must be "maxim,max77650-onkey".
+
+Optional properties:
+- linux,code:          The key-code to be reported when the key is pressed.
+                       Defaults to KEY_POWER.
+- maxim,onkey-slide:   The system's button is a slide switch, not the default
+                       push button.
+
+Example:
+--------
+
+       onkey {
+               compatible = "maxim,max77650-onkey";
+               linux,code = <KEY_END>;
+               maxim,onkey-slide;
+       };
diff --git a/Documentation/devicetree/bindings/input/microchip,qt1050.txt b/Documentation/devicetree/bindings/input/microchip,qt1050.txt
new file mode 100644 (file)
index 0000000..80e75f9
--- /dev/null
@@ -0,0 +1,78 @@
+Microchip AT42QT1050 Five-channel Touch Sensor IC
+
+The AT42QT1050 (QT1050) is a QTouchADC sensor device. The device can sense from
+one to five keys, dependent on mode. The QT1050 includes all signal processing
+functions necessary to provide stable sensing under a wide variety of changing
+conditions, and the outputs are fully debounced.
+
+The touchkey device node should be placed inside an I2C bus node.
+
+Required properties:
+- compatible: Must be "microchip,qt1050"
+- reg: The I2C address of the device
+- interrupts: The sink for the touchpad's IRQ output,
+  see ../interrupt-controller/interrupts.txt
+
+Optional properties:
+- wakeup-source: touch keys can be used as a wakeup source
+
+Each button (key) is represented as a sub-node:
+
+Each not specified key or key with linux,code set to KEY_RESERVED gets disabled
+in HW.
+
+Subnode properties:
+- linux,code: Keycode to emit.
+- reg: The key number. Valid values: 0, 1, 2, 3, 4.
+
+Optional subnode-properties:
+
+If a optional property is missing or has a invalid value the default value is
+taken.
+
+- microchip,pre-charge-time-ns:
+  Each touchpad need some time to precharge. The value depends on the mechanical
+  layout.
+  Valid value range: 0 - 637500; values must be a multiple of 2500;
+  default is 0.
+- microchip,average-samples:
+  Number of data samples which are averaged for each read.
+  Valid values: 1, 4, 16, 64, 256, 1024, 4096, 16384; default is 1.
+- microchip,average-scaling:
+  The scaling factor which is used to scale the average-samples.
+  Valid values: 1, 2, 4, 8, 16, 32, 64, 128; default is 1.
+- microchip,threshold:
+  Number of counts to register a touch detection.
+  Valid value range: 0 - 255; default is 20.
+
+Example:
+QT1050 with 3 non continuous keys, key2 and key4 are disabled.
+
+touchkeys@41 {
+       compatible = "microchip,qt1050";
+       reg = <0x41>;
+       interrupt-parent = <&gpio0>;
+       interrupts = <17 IRQ_TYPE_EDGE_FALLING>;
+
+       up@0 {
+               reg = <0>;
+               linux,code = <KEY_UP>;
+               microchip,average-samples = <64>;
+               microchip,average-scaling = <16>;
+               microchip,pre-charge-time-ns = <10000>;
+       };
+
+       right@1 {
+               reg = <1>;
+               linux,code = <KEY_RIGHT>;
+               microchip,average-samples = <64>;
+               microchip,average-scaling = <8>;
+       };
+
+       down@3 {
+               reg = <3>;
+               linux,code = <KEY_DOWN>;
+               microchip,average-samples = <256>;
+               microchip,average-scaling = <16>;
+       };
+};
index 1458c31..496125c 100644 (file)
@@ -2,12 +2,14 @@ Allwinner sun4i low res adc attached tablet keys
 ------------------------------------------------
 
 Required properties:
- - compatible: "allwinner,sun4i-a10-lradc-keys"
+ - compatible: should be one of the following string:
+               "allwinner,sun4i-a10-lradc-keys"
+               "allwinner,sun8i-a83t-r-lradc"
  - reg: mmio address range of the chip
  - interrupts: interrupt to which the chip is connected
  - vref-supply: powersupply for the lradc reference voltage
 
-Each key is represented as a sub-node of "allwinner,sun4i-a10-lradc-keys":
+Each key is represented as a sub-node of the compatible mentioned above:
 
 Required subnode-properties:
        - label: Descriptive name of the key.
index 8cf0b4d..fc03ea4 100644 (file)
@@ -3,6 +3,7 @@ Device tree bindings for Goodix GT9xx series touchscreen controller
 Required properties:
 
  - compatible          : Should be "goodix,gt1151"
+                                or "goodix,gt5663"
                                 or "goodix,gt5688"
                                 or "goodix,gt911"
                                 or "goodix,gt9110"
@@ -19,6 +20,8 @@ Optional properties:
  - irq-gpios           : GPIO pin used for IRQ. The driver uses the
                          interrupt gpio pin as output to reset the device.
  - reset-gpios         : GPIO pin used for reset
+ - AVDD28-supply       : Analog power supply regulator on AVDD28 pin
+ - VDDIO-supply                : GPIO power supply regulator on VDDIO pin
  - touchscreen-inverted-x
  - touchscreen-inverted-y
  - touchscreen-size-x
diff --git a/Documentation/devicetree/bindings/input/touchscreen/iqs5xx.txt b/Documentation/devicetree/bindings/input/touchscreen/iqs5xx.txt
new file mode 100644 (file)
index 0000000..efa0820
--- /dev/null
@@ -0,0 +1,80 @@
+Azoteq IQS550/572/525 Trackpad/Touchscreen Controller
+
+Required properties:
+
+- compatible                   : Must be equal to one of the following:
+                                 "azoteq,iqs550"
+                                 "azoteq,iqs572"
+                                 "azoteq,iqs525"
+
+- reg                          : I2C slave address for the device.
+
+- interrupts                   : GPIO to which the device's active-high RDY
+                                 output is connected (see [0]).
+
+- reset-gpios                  : GPIO to which the device's active-low NRST
+                                 input is connected (see [1]).
+
+Optional properties:
+
+- touchscreen-min-x            : See [2].
+
+- touchscreen-min-y            : See [2].
+
+- touchscreen-size-x           : See [2]. If this property is omitted, the
+                                 maximum x-coordinate is specified by the
+                                 device's "X Resolution" register.
+
+- touchscreen-size-y           : See [2]. If this property is omitted, the
+                                 maximum y-coordinate is specified by the
+                                 device's "Y Resolution" register.
+
+- touchscreen-max-pressure     : See [2]. Pressure is expressed as the sum of
+                                 the deltas across all channels impacted by a
+                                 touch event. A channel's delta is calculated
+                                 as its count value minus a reference, where
+                                 the count value is inversely proportional to
+                                 the channel's capacitance.
+
+- touchscreen-fuzz-x           : See [2].
+
+- touchscreen-fuzz-y           : See [2].
+
+- touchscreen-fuzz-pressure    : See [2].
+
+- touchscreen-inverted-x       : See [2]. Inversion is applied relative to that
+                                 which may already be specified by the device's
+                                 FLIP_X and FLIP_Y register fields.
+
+- touchscreen-inverted-y       : See [2]. Inversion is applied relative to that
+                                 which may already be specified by the device's
+                                 FLIP_X and FLIP_Y register fields.
+
+- touchscreen-swapped-x-y      : See [2]. Swapping is applied relative to that
+                                 which may already be specified by the device's
+                                 SWITCH_XY_AXIS register field.
+
+[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+[1]: Documentation/devicetree/bindings/gpio/gpio.txt
+[2]: Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt
+
+Example:
+
+       &i2c1 {
+               /* ... */
+
+               touchscreen@74 {
+                       compatible = "azoteq,iqs550";
+                       reg = <0x74>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <17 4>;
+                       reset-gpios = <&gpio 27 1>;
+
+                       touchscreen-size-x = <640>;
+                       touchscreen-size-y = <480>;
+
+                       touchscreen-max-pressure = <16000>;
+               };
+
+               /* ... */
+       };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml b/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
new file mode 100644 (file)
index 0000000..bae10e2
--- /dev/null
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2018 Linaro Ltd.
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/interrupt/intel-ixp4xx-interrupt.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Intel IXP4xx XScale Networking Processors Interrupt Controller
+
+maintainers:
+  - Linus Walleij <linus.walleij@linaro.org>
+
+description: |
+  This interrupt controller is found in the Intel IXP4xx processors.
+  Some processors have 32 interrupts, some have up to 64 interrupts.
+  The exact number of interrupts is determined from the compatible
+  string.
+
+  The distinct IXP4xx families with different interrupt controller
+  variations are IXP42x, IXP43x, IXP45x and IXP46x. Those four
+  families were the only ones to reach the developer and consumer
+  market.
+
+properties:
+  compatible:
+    items:
+      - enum:
+        - intel,ixp42x-interrupt
+        - intel,ixp43x-interrupt
+        - intel,ixp45x-interrupt
+        - intel,ixp46x-interrupt
+
+  reg:
+    maxItems: 1
+
+  interrupt-controller: true
+
+  '#interrupt-cells':
+    const: 2
+
+required:
+  - compatible
+  - reg
+  - interrupt-controller
+  - '#interrupt-cells'
+
+examples:
+  - |
+    intcon: interrupt-controller@c8003000 {
+        compatible = "intel,ixp43x-interrupt";
+        reg = <0xc8003000 0x100>;
+        interrupt-controller;
+        #interrupt-cells = <2>;
+    };
index c5d5891..0e312fe 100644 (file)
@@ -1,15 +1,18 @@
-+Mediatek MT65xx/MT67xx/MT81xx sysirq
+MediaTek sysirq
 
-Mediatek SOCs sysirq support controllable irq inverter for each GIC SPI
+MediaTek SOCs sysirq support controllable irq inverter for each GIC SPI
 interrupt.
 
 Required properties:
 - compatible: should be
+       "mediatek,mt8516-sysirq", "mediatek,mt6577-sysirq": for MT8516
+       "mediatek,mt8183-sysirq", "mediatek,mt6577-sysirq": for MT8183
        "mediatek,mt8173-sysirq", "mediatek,mt6577-sysirq": for MT8173
        "mediatek,mt8135-sysirq", "mediatek,mt6577-sysirq": for MT8135
        "mediatek,mt8127-sysirq", "mediatek,mt6577-sysirq": for MT8127
        "mediatek,mt7622-sysirq", "mediatek,mt6577-sysirq": for MT7622
        "mediatek,mt7623-sysirq", "mediatek,mt6577-sysirq": for MT7623
+       "mediatek,mt7629-sysirq", "mediatek,mt6577-sysirq": for MT7629
        "mediatek,mt6795-sysirq", "mediatek,mt6577-sysirq": for MT6795
        "mediatek,mt6797-sysirq", "mediatek,mt6577-sysirq": for MT6797
        "mediatek,mt6765-sysirq", "mediatek,mt6577-sysirq": for MT6765
diff --git a/Documentation/devicetree/bindings/leds/backlight/lm3630a-backlight.yaml b/Documentation/devicetree/bindings/leds/backlight/lm3630a-backlight.yaml
new file mode 100644 (file)
index 0000000..4d61fe0
--- /dev/null
@@ -0,0 +1,129 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/backlight/lm3630a-backlight.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI LM3630A High-Efficiency Dual-String White LED
+
+maintainers:
+  - Lee Jones <lee.jones@linaro.org>
+  - Daniel Thompson <daniel.thompson@linaro.org>
+  - Jingoo Han <jingoohan1@gmail.com>
+
+description: |
+  The LM3630A is a current-mode boost converter which supplies the power and
+  controls the current in up to two strings of 10 LEDs per string.
+  https://www.ti.com/product/LM3630A
+
+properties:
+  compatible:
+    const: ti,lm3630a
+
+  reg:
+    maxItems: 1
+
+  ti,linear-mapping-mode:
+    description: |
+      Enable linear mapping mode. If disabled, then it will use exponential
+      mapping mode in which the ramp up/down appears to have a more uniform
+      transition to the human eye.
+    type: boolean
+
+required:
+  - compatible
+  - reg
+
+patternProperties:
+  "^led@[01]$":
+    type: object
+    description: |
+      Properties for a string of connected LEDs.
+
+    properties:
+      reg:
+        description: |
+          The control bank that is used to program the two current sinks. The
+          LM3630A has two control banks (A and B) and are represented as 0 or 1
+          in this property. The two current sinks can be controlled
+          independently with both banks, or bank A can be configured to control
+          both sinks with the led-sources property.
+        maxItems: 1
+        minimum: 0
+        maximum: 1
+
+      label:
+        maxItems: 1
+
+      led-sources:
+        allOf:
+          - minItems: 1
+            maxItems: 2
+            items:
+              minimum: 0
+              maximum: 1
+
+      default-brightness:
+        description: Default brightness level on boot.
+        minimum: 0
+        maximum: 255
+
+      max-brightness:
+        description: Maximum brightness that is allowed during runtime.
+        minimum: 0
+        maximum: 255
+
+    required:
+      - reg
+
+    additionalProperties: false
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        led-controller@38 {
+                compatible = "ti,lm3630a";
+                reg = <0x38>;
+
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                led@0 {
+                        reg = <0>;
+                        led-sources = <0 1>;
+                        label = "lcd-backlight";
+                        default-brightness = <200>;
+                        max-brightness = <255>;
+                };
+        };
+    };
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        led-controller@38 {
+                compatible = "ti,lm3630a";
+                reg = <0x38>;
+
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                led@0 {
+                        reg = <0>;
+                        default-brightness = <150>;
+                        ti,linear-mapping-mode;
+                };
+
+                led@1 {
+                        reg = <1>;
+                        default-brightness = <225>;
+                        ti,linear-mapping-mode;
+                };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/leds/leds-max77650.txt b/Documentation/devicetree/bindings/leds/leds-max77650.txt
new file mode 100644 (file)
index 0000000..3a67115
--- /dev/null
@@ -0,0 +1,57 @@
+LED driver for MAX77650 PMIC from Maxim Integrated.
+
+This module is part of the MAX77650 MFD device. For more details
+see Documentation/devicetree/bindings/mfd/max77650.txt.
+
+The LED controller is represented as a sub-node of the PMIC node on
+the device tree.
+
+This device has three current sinks.
+
+Required properties:
+--------------------
+- compatible:          Must be "maxim,max77650-led"
+- #address-cells:      Must be <1>.
+- #size-cells:         Must be <0>.
+
+Each LED is represented as a sub-node of the LED-controller node. Up to
+three sub-nodes can be defined.
+
+Required properties of the sub-node:
+------------------------------------
+
+- reg:                 Must be <0>, <1> or <2>.
+
+Optional properties of the sub-node:
+------------------------------------
+
+- label:               See Documentation/devicetree/bindings/leds/common.txt
+- linux,default-trigger: See Documentation/devicetree/bindings/leds/common.txt
+
+For more details, please refer to the generic GPIO DT binding document
+<devicetree/bindings/gpio/gpio.txt>.
+
+Example:
+--------
+
+       leds {
+               compatible = "maxim,max77650-led";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               led@0 {
+                       reg = <0>;
+                       label = "blue:usr0";
+               };
+
+               led@1 {
+                       reg = <1>;
+                       label = "red:usr1";
+                       linux,default-trigger = "heartbeat";
+               };
+
+               led@2 {
+                       reg = <2>;
+                       label = "green:usr2";
+               };
+       };
diff --git a/Documentation/devicetree/bindings/memory-controllers/fsl/mmdc.txt b/Documentation/devicetree/bindings/memory-controllers/fsl/mmdc.txt
new file mode 100644 (file)
index 0000000..bcc36c5
--- /dev/null
@@ -0,0 +1,35 @@
+Freescale Multi Mode DDR controller (MMDC)
+
+Required properties :
+- compatible : should be one of following:
+       for i.MX6Q/i.MX6DL:
+       - "fsl,imx6q-mmdc";
+       for i.MX6QP:
+       - "fsl,imx6qp-mmdc", "fsl,imx6q-mmdc";
+       for i.MX6SL:
+       - "fsl,imx6sl-mmdc", "fsl,imx6q-mmdc";
+       for i.MX6SLL:
+       - "fsl,imx6sll-mmdc", "fsl,imx6q-mmdc";
+       for i.MX6SX:
+       - "fsl,imx6sx-mmdc", "fsl,imx6q-mmdc";
+       for i.MX6UL/i.MX6ULL/i.MX6ULZ:
+       - "fsl,imx6ul-mmdc", "fsl,imx6q-mmdc";
+       for i.MX7ULP:
+       - "fsl,imx7ulp-mmdc", "fsl,imx6q-mmdc";
+- reg : address and size of MMDC DDR controller registers
+
+Optional properties :
+- clocks : the clock provided by the SoC to access the MMDC registers
+
+Example :
+       mmdc0: memory-controller@21b0000 { /* MMDC0 */
+               compatible = "fsl,imx6q-mmdc";
+               reg = <0x021b0000 0x4000>;
+               clocks = <&clks IMX6QDL_CLK_MMDC_P0_IPG>;
+       };
+
+       mmdc1: memory-controller@21b4000 { /* MMDC1 */
+               compatible = "fsl,imx6q-mmdc";
+               reg = <0x021b4000 0x4000>;
+               status = "disabled";
+       };
index 3f643ef..5f8880c 100644 (file)
@@ -7,6 +7,7 @@ Required properties:
    "atmel,sama5d2-hlcdc"
    "atmel,sama5d3-hlcdc"
    "atmel,sama5d4-hlcdc"
+   "microchip,sam9x60-hlcdc"
  - reg: base address and size of the HLCDC device registers.
  - clock-names: the name of the 3 clocks requested by the HLCDC device.
    Should contain "periph_clk", "sys_clk" and "slow_clk".
index 004b015..3bf92ad 100644 (file)
@@ -19,6 +19,8 @@ And these documents for the required sub-node binding details:
   [4] Clock: ../clock/cirrus,lochnagar.txt
   [5] Pinctrl: ../pinctrl/cirrus,lochnagar.txt
   [6] Regulator: ../regulator/cirrus,lochnagar.txt
+  [7] Sound: ../sound/cirrus,lochnagar.txt
+  [8] Hardware Monitor: ../hwmon/cirrus,lochnagar.txt
 
 Required properties:
 
@@ -41,6 +43,11 @@ Optional sub-nodes:
   - Bindings for the regulator components, see [6]. Only available on
     Lochnagar 2.
 
+  - lochnagar-sc : Binding for the sound card components, see [7].
+                   Only available on Lochnagar 2.
+  - lochnagar-hwmon : Binding for the hardware monitor components, see [8].
+                      Only available on Lochnagar 2.
+
 Optional properties:
 
   - present-gpios : Host present line, indicating the presence of a
@@ -65,4 +72,14 @@ lochnagar: lochnagar@22 {
                compatible = "cirrus,lochnagar-pinctrl";
                ...
        };
+
+       lochnagar-sc {
+               compatible = "cirrus,lochnagar2-soundcard";
+               ...
+       };
+
+       lochnagar-hwmon {
+               compatible = "cirrus,lochnagar2-hwmon";
+               ...
+       };
 };
index 9c16d51..5a642a5 100644 (file)
@@ -4,7 +4,8 @@ Required properties:
 -------------------
 - compatible: Must be one of
                "maxim,max77620"
-               "maxim,max20024".
+               "maxim,max20024"
+               "maxim,max77663"
 - reg: I2C device address.
 
 Optional properties:
@@ -17,6 +18,11 @@ Optional properties:
                        IRQ numbers for different interrupt source of MAX77620
                        are defined at dt-bindings/mfd/max77620.h.
 
+- system-power-controller: Indicates that this PMIC is controlling the
+                          system power, see [1] for more details.
+
+[1] Documentation/devicetree/bindings/power/power-controller.txt
+
 Optional subnodes and their properties:
 =======================================
 
@@ -105,6 +111,7 @@ Optional properties:
 Here supported time periods by device in microseconds are as follows:
 MAX77620 supports 40, 80, 160, 320, 640, 1280, 2560 and 5120 microseconds.
 MAX20024 supports 20, 40, 80, 160, 320, 640, 1280 and 2540 microseconds.
+MAX77663 supports 20, 40, 80, 160, 320, 640, 1280 and 2540 microseconds.
 
 -maxim,power-ok-control: configure map power ok bit
                        1: Enables POK(Power OK) to control nRST_IO and GPIO1
diff --git a/Documentation/devicetree/bindings/mfd/max77650.txt b/Documentation/devicetree/bindings/mfd/max77650.txt
new file mode 100644 (file)
index 0000000..b529d8d
--- /dev/null
@@ -0,0 +1,46 @@
+MAX77650 ultra low-power PMIC from Maxim Integrated.
+
+Required properties:
+-------------------
+- compatible:          Must be "maxim,max77650"
+- reg:                 I2C device address.
+- interrupts:          The interrupt on the parent the controller is
+                       connected to.
+- interrupt-controller: Marks the device node as an interrupt controller.
+- #interrupt-cells:    Must be <2>.
+
+- gpio-controller:     Marks the device node as a gpio controller.
+- #gpio-cells:         Must be <2>. The first cell is the pin number and
+                       the second cell is used to specify the gpio active
+                       state.
+
+Optional properties:
+--------------------
+gpio-line-names:       Single string containing the name of the GPIO line.
+
+The GPIO-controller module is represented as part of the top-level PMIC
+node. The device exposes a single GPIO line.
+
+For device-tree bindings of other sub-modules (regulator, power supply,
+LEDs and onkey) refer to the binding documents under the respective
+sub-system directories.
+
+For more details on GPIO bindings, please refer to the generic GPIO DT
+binding document <devicetree/bindings/gpio/gpio.txt>.
+
+Example:
+--------
+
+       pmic@48 {
+               compatible = "maxim,max77650";
+               reg = <0x48>;
+
+               interrupt-controller;
+               interrupt-parent = <&gpio2>;
+               #interrupt-cells = <2>;
+               interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+
+               gpio-controller;
+               #gpio-cells = <2>;
+               gpio-line-names = "max77650-charger";
+       };
diff --git a/Documentation/devicetree/bindings/mfd/stmfx.txt b/Documentation/devicetree/bindings/mfd/stmfx.txt
new file mode 100644 (file)
index 0000000..f0c2f7f
--- /dev/null
@@ -0,0 +1,28 @@
+STMicroelectonics Multi-Function eXpander (STMFX) Core bindings
+
+ST Multi-Function eXpander (STMFX) is a slave controller using I2C for
+communication with the main MCU. Its main features are GPIO expansion, main
+MCU IDD measurement (IDD is the amount of current that flows through VDD) and
+resistive touchscreen controller.
+
+Required properties:
+- compatible: should be "st,stmfx-0300".
+- reg: I2C slave address of the device.
+- interrupts: interrupt specifier triggered by MFX_IRQ_OUT signal.
+  Please refer to ../interrupt-controller/interrupt.txt
+
+Optional properties:
+- drive-open-drain: configure MFX_IRQ_OUT as open drain.
+- vdd-supply: phandle of the regulator supplying STMFX.
+
+Example:
+
+       stmfx: stmfx@42 {
+               compatible = "st,stmfx-0300";
+               reg = <0x42>;
+               interrupts = <8 IRQ_TYPE_EDGE_RISING>;
+               interrupt-parent = <&gpioi>;
+               vdd-supply = <&v3v3>;
+       };
+
+Please refer to ../pinctrl/pinctrl-stmfx.txt for STMFX GPIO expander function bindings.
index 980394d..86ca786 100644 (file)
@@ -104,8 +104,8 @@ lm3632@11 {
        regulators {
                compatible = "ti,lm363x-regulator";
 
-               ti,lcm-en1-gpio = <&pioC 0 GPIO_ACTIVE_HIGH>; /* PC0 */
-               ti,lcm-en2-gpio = <&pioC 1 GPIO_ACTIVE_HIGH>; /* PC1 */
+               enable-gpios = <&pioC 0 GPIO_ACTIVE_HIGH>,
+                              <&pioC 1 GPIO_ACTIVE_HIGH>;
 
                vboost {
                        regulator-name = "lcd_boost";
diff --git a/Documentation/devicetree/bindings/misc/intel,ixp4xx-queue-manager.yaml b/Documentation/devicetree/bindings/misc/intel,ixp4xx-queue-manager.yaml
new file mode 100644 (file)
index 0000000..d2313b1
--- /dev/null
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2019 Linaro Ltd.
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/misc/intel-ixp4xx-ahb-queue-manager.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Intel IXP4xx AHB Queue Manager
+
+maintainers:
+  - Linus Walleij <linus.walleij@linaro.org>
+
+description: |
+  The IXP4xx AHB Queue Manager maintains queues as circular buffers in
+  an 8KB embedded SRAM along with hardware pointers. It is used by both
+  the XScale processor and the NPEs (Network Processing Units) in the
+  IXP4xx for accelerating queues, especially for networking. Clients pick
+  queues from the queue manager with foo-queue = <&qmgr N> where the
+  &qmgr is a phandle to the queue manager and N is the queue resource
+  number. The queue resources available and their specific purpose
+  on a certain IXP4xx system will vary.
+
+properties:
+  compatible:
+    items:
+      - const: intel,ixp4xx-ahb-queue-manager
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    items:
+      - description: Interrupt for queues 0-31
+      - description: Interrupt for queues 32-63
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    qmgr: queue-manager@60000000 {
+         compatible = "intel,ixp4xx-ahb-queue-manager";
+         reg = <0x60000000 0x4000>;
+         interrupts = <3 IRQ_TYPE_LEVEL_HIGH>, <4 IRQ_TYPE_LEVEL_HIGH>;
+    };
index 07242d1..36c4bea 100644 (file)
@@ -13,6 +13,8 @@ Required Properties:
 
 * compatible: should be one of the following.
   - "hisilicon,hi3660-dw-mshc": for controllers with hi3660 specific extensions.
+  - "hisilicon,hi3670-dw-mshc", "hisilicon,hi3660-dw-mshc": for controllers
+     with hi3670 specific extensions.
   - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extensions.
   - "hisilicon,hi6220-dw-mshc": for controllers with hi6220 specific extensions.
 
index 3a65aab..6262c2f 100644 (file)
@@ -139,9 +139,9 @@ Optional properties:
                        sub-module attached to this interface.
 
 The MAC address will be determined using the optional properties defined in
-ethernet.txt, as provided by the of_get_mac_address API and only if efuse-mac
-is set to 0. If any of the optional MAC address properties are not present,
-then the driver will use random MAC address.
+ethernet.txt and only if efuse-mac is set to 0. If all of the optional MAC
+address properties are not present, then the driver will use a random MAC
+address.
 
 Example binding:
 
index 7466550..7e675da 100644 (file)
@@ -16,8 +16,8 @@ Optional properties:
 - ieee80211-freq-limit: See ieee80211.txt
 - mediatek,mtd-eeprom: Specify a MTD partition + offset containing EEPROM data
 
-The driver is using of_get_mac_address API, so the MAC address can be as well
-be set with corresponding optional properties defined in net/ethernet.txt.
+The MAC address can as well be set with corresponding optional properties
+defined in net/ethernet.txt.
 
 Optional nodes:
 - led: Properties for a connected LED
index c124f9b..5561a1c 100644 (file)
@@ -4,8 +4,11 @@ Required properties:
 - compatible:
        "snps,dw-pcie" for RC mode;
        "snps,dw-pcie-ep" for EP mode;
-- reg: Should contain the configuration address space.
-- reg-names: Must be "config" for the PCIe configuration space.
+- reg: For designware cores version < 4.80 contains the configuration
+       address space. For designware core version >= 4.80, contains
+       the configuration and ATU address space
+- reg-names: Must be "config" for the PCIe configuration space and "atu" for
+            the ATU address space.
     (The old way of getting the configuration address space from "ranges"
     is deprecated and should be avoided.)
 - num-lanes: number of lanes to use
index 2030ee0..47202a2 100644 (file)
@@ -11,16 +11,24 @@ described here as well as properties that are not applicable.
 
 Required Properties:-
 
-compatibility: "ti,keystone-pcie"
-reg:   index 1 is the base address and length of DW application registers.
-       index 2 is the base address and length of PCI device ID register.
+compatibility: Should be "ti,keystone-pcie" for RC on Keystone2 SoC
+              Should be "ti,am654-pcie-rc" for RC on AM654x SoC
+reg: Three register ranges as listed in the reg-names property
+reg-names: "dbics" for the DesignWare PCIe registers, "app" for the
+          TI specific application registers, "config" for the
+          configuration space address
 
 pcie_msi_intc : Interrupt controller device node for MSI IRQ chip
        interrupt-cells: should be set to 1
        interrupts: GIC interrupt lines connected to PCI MSI interrupt lines
+       (required if the compatible is "ti,keystone-pcie")
+msi-map: As specified in Documentation/devicetree/bindings/pci/pci-msi.txt
+        (required if the compatible is "ti,am654-pcie-rc".
 
 ti,syscon-pcie-id : phandle to the device control module required to set device
                    id and vendor id.
+ti,syscon-pcie-mode : phandle to the device control module required to configure
+                     PCI in either RC mode or EP mode.
 
  Example:
        pcie_msi_intc: msi-interrupt-controller {
@@ -61,3 +69,47 @@ Optional properties:-
 DesignWare DT Properties not applicable for Keystone PCI
 
 1. pcie_bus clock-names not used.  Instead, a phandle to phys is used.
+
+AM654 PCIe Endpoint
+===================
+
+Required Properties:-
+
+compatibility: Should be "ti,am654-pcie-ep" for EP on AM654x SoC
+reg: Four register ranges as listed in the reg-names property
+reg-names: "dbics" for the DesignWare PCIe registers, "app" for the
+          TI specific application registers, "atu" for the
+          Address Translation Unit configuration registers and
+          "addr_space" used to map remote RC address space
+num-ib-windows: As specified in
+               Documentation/devicetree/bindings/pci/designware-pcie.txt
+num-ob-windows: As specified in
+               Documentation/devicetree/bindings/pci/designware-pcie.txt
+num-lanes: As specified in
+          Documentation/devicetree/bindings/pci/designware-pcie.txt
+power-domains: As documented by the generic PM domain bindings in
+              Documentation/devicetree/bindings/power/power_domain.txt.
+ti,syscon-pcie-mode: phandle to the device control module required to configure
+                     PCI in either RC mode or EP mode.
+
+Optional properties:-
+
+phys: list of PHY specifiers (used by generic PHY framework)
+phy-names: must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
+               number of lanes as specified in *num-lanes* property.
+("phys" and "phy-names" DT bindings are specified in
+Documentation/devicetree/bindings/phy/phy-bindings.txt)
+interrupts: platform interrupt for error interrupts.
+
+pcie-ep {
+       compatible = "ti,am654-pcie-ep";
+       reg =  <0x5500000 0x1000>, <0x5501000 0x1000>,
+              <0x10000000 0x8000000>, <0x5506000 0x1000>;
+       reg-names = "app", "dbics", "addr_space", "atu";
+       power-domains = <&k3_pds 120>;
+       ti,syscon-pcie-mode = <&pcie0_mode>;
+       num-lanes = <1>;
+       num-ib-windows = <16>;
+       num-ob-windows = <16>;
+       interrupts = <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>;
+};
index c77981c..92c01db 100644 (file)
@@ -24,3 +24,53 @@ driver implementation may support the following properties:
    unsupported link speed, for instance, trying to do training for
    unsupported link speed, etc.  Must be '4' for gen4, '3' for gen3, '2'
    for gen2, and '1' for gen1. Any other values are invalid.
+
+PCI-PCI Bridge properties
+-------------------------
+
+PCIe root ports and switch ports may be described explicitly in the device
+tree, as children of the host bridge node. Even though those devices are
+discoverable by probing, it might be necessary to describe properties that
+aren't provided by standard PCIe capabilities.
+
+Required properties:
+
+- reg:
+   Identifies the PCI-PCI bridge. As defined in the IEEE Std 1275-1994
+   document, it is a five-cell address encoded as (phys.hi phys.mid
+   phys.lo size.hi size.lo). phys.hi should contain the device's BDF as
+   0b00000000 bbbbbbbb dddddfff 00000000. The other cells should be zero.
+
+   The bus number is defined by firmware, through the standard bridge
+   configuration mechanism. If this port is a switch port, then firmware
+   allocates the bus number and writes it into the Secondary Bus Number
+   register of the bridge directly above this port. Otherwise, the bus
+   number of a root port is the first number in the bus-range property,
+   defaulting to zero.
+
+   If firmware leaves the ARI Forwarding Enable bit set in the bridge
+   above this port, then phys.hi contains the 8-bit function number as
+   0b00000000 bbbbbbbb ffffffff 00000000. Note that the PCIe specification
+   recommends that firmware only leaves ARI enabled when it knows that the
+   OS is ARI-aware.
+
+Optional properties:
+
+- external-facing:
+   When present, the port is external-facing. All bridges and endpoints
+   downstream of this port are external to the machine. The OS can, for
+   example, use this information to identify devices that cannot be
+   trusted with relaxed DMA protection, as users could easily attach
+   malicious devices to this port.
+
+Example:
+
+pcie@10000000 {
+       compatible = "pci-host-ecam-generic";
+       ...
+       pcie@0008 {
+               /* Root port 00:01.0 is external-facing */
+               reg = <0x00000800 0 0 0 0>;
+               external-facing;
+       };
+};
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-stmfx.txt
new file mode 100644 (file)
index 0000000..c1b4c18
--- /dev/null
@@ -0,0 +1,116 @@
+STMicroelectronics Multi-Function eXpander (STMFX) GPIO expander bindings
+
+ST Multi-Function eXpander (STMFX) offers up to 24 GPIOs expansion.
+Please refer to ../mfd/stmfx.txt for STMFX Core bindings.
+
+Required properties:
+- compatible: should be "st,stmfx-0300-pinctrl".
+- #gpio-cells: should be <2>, the first cell is the GPIO number and the second
+  cell is the gpio flags in accordance with <dt-bindings/gpio/gpio.h>.
+- gpio-controller: marks the device as a GPIO controller.
+- #interrupt-cells: should be <2>, the first cell is the GPIO number and the
+  second cell is the interrupt flags in accordance with
+  <dt-bindings/interrupt-controller/irq.h>.
+- interrupt-controller: marks the device as an interrupt controller.
+- gpio-ranges: specifies the mapping between gpio controller and pin
+  controller pins. Check "Concerning gpio-ranges property" below.
+Please refer to ../gpio/gpio.txt.
+
+Please refer to pinctrl-bindings.txt for pin configuration.
+
+Required properties for pin configuration sub-nodes:
+- pins: list of pins to which the configuration applies.
+
+Optional properties for pin configuration sub-nodes (pinconf-generic ones):
+- bias-disable: disable any bias on the pin.
+- bias-pull-up: the pin will be pulled up.
+- bias-pull-pin-default: use the pin-default pull state.
+- bias-pull-down: the pin will be pulled down.
+- drive-open-drain: the pin will be driven with open drain.
+- drive-push-pull: the pin will be driven actively high and low.
+- output-high: the pin will be configured as an output driving high level.
+- output-low: the pin will be configured as an output driving low level.
+
+Note that STMFX pins[15:0] are called "gpio[15:0]", and STMFX pins[23:16] are
+called "agpio[7:0]". Example, to refer to pin 18 of STMFX, use "agpio2".
+
+Concerning gpio-ranges property:
+- if all STMFX pins[24:0] are available (no other STMFX function in use), you
+  should use gpio-ranges = <&stmfx_pinctrl 0 0 24>;
+- if agpio[3:0] are not available (STMFX Touchscreen function in use), you
+  should use gpio-ranges = <&stmfx_pinctrl 0 0 16>, <&stmfx_pinctrl 20 20 4>;
+- if agpio[7:4] are not available (STMFX IDD function in use), you
+  should use gpio-ranges = <&stmfx_pinctrl 0 0 20>;
+
+
+Example:
+
+       stmfx: stmfx@42 {
+               ...
+
+               stmfx_pinctrl: stmfx-pin-controller {
+                       compatible = "st,stmfx-0300-pinctrl";
+                       #gpio-cells = <2>;
+                       #interrupt-cells = <2>;
+                       gpio-controller;
+                       interrupt-controller;
+                       gpio-ranges = <&stmfx_pinctrl 0 0 24>;
+
+                       joystick_pins: joystick {
+                               pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4";
+                               drive-push-pull;
+                               bias-pull-up;
+                       };
+               };
+       };
+
+Example of STMFX GPIO consumers:
+
+       joystick {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-0 = <&joystick_pins>;
+               pinctrl-names = "default";
+               button-0 {
+                       label = "JoySel";
+                       linux,code = <KEY_ENTER>;
+                       interrupt-parent = <&stmfx_pinctrl>;
+                       interrupts = <0 IRQ_TYPE_EDGE_RISING>;
+               };
+               button-1 {
+                       label = "JoyDown";
+                       linux,code = <KEY_DOWN>;
+                       interrupt-parent = <&stmfx_pinctrl>;
+                       interrupts = <1 IRQ_TYPE_EDGE_RISING>;
+               };
+               button-2 {
+                       label = "JoyLeft";
+                       linux,code = <KEY_LEFT>;
+                       interrupt-parent = <&stmfx_pinctrl>;
+                       interrupts = <2 IRQ_TYPE_EDGE_RISING>;
+               };
+               button-3 {
+                       label = "JoyRight";
+                       linux,code = <KEY_RIGHT>;
+                       interrupt-parent = <&stmfx_pinctrl>;
+                       interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+               };
+               button-4 {
+                       label = "JoyUp";
+                       linux,code = <KEY_UP>;
+                       interrupt-parent = <&stmfx_pinctrl>;
+                       interrupts = <4 IRQ_TYPE_EDGE_RISING>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               orange {
+                       gpios = <&stmfx_pinctrl 17 1>;
+               };
+
+               blue {
+                       gpios = <&stmfx_pinctrl 19 1>;
+               };
+       }
index 1cd050b..0fdc3dd 100644 (file)
@@ -16,7 +16,9 @@ Device Tree Bindings:
 ---------------------
 
 Required properties:
-- compatible: should be "amlogic,meson-gx-pwrc-vpu" for the Meson GX SoCs
+- compatible: should be one of the following :
+       - "amlogic,meson-gx-pwrc-vpu" for the Meson GX SoCs
+       - "amlogic,meson-g12a-pwrc-vpu" for the Meson G12A SoCs
 - #power-domain-cells: should be 0
 - amlogic,hhi-sysctrl: phandle to the HHI sysctrl node
 - resets: phandles to the reset lines needed for this power demain sequence
index 1190631..e23dea8 100644 (file)
@@ -3,13 +3,20 @@ Generic SYSCON mapped register reset driver
 This is a generic reset driver using syscon to map the reset register.
 The reset is generally performed with a write to the reset register
 defined by the register map pointed by syscon reference plus the offset
-with the mask defined in the reboot node.
+with the value and mask defined in the reboot node.
 
 Required properties:
 - compatible: should contain "syscon-reboot"
 - regmap: this is phandle to the register map node
 - offset: offset in the register map for the reboot register (in bytes)
-- mask: the reset value written to the reboot register (32 bit access)
+- value: the reset value written to the reboot register (32 bit access)
+
+Optional properties:
+- mask: update only the register bits defined by the mask (32 bit)
+
+Legacy usage:
+If a node doesn't contain a value property but contains a mask property, the
+mask property is used as the value.
 
 Default will be little endian mode, 32 bit access only.
 
index ba8d35f..b2d4968 100644 (file)
@@ -4,6 +4,7 @@ Required Properties:
 -compatible: One of: "x-powers,axp202-usb-power-supply"
                      "x-powers,axp221-usb-power-supply"
                      "x-powers,axp223-usb-power-supply"
+                    "x-powers,axp813-usb-power-supply"
 
 The AXP223 PMIC shares most of its behaviour with the AXP221 but has slight
 variations such as the former being able to set the VBUS power supply max
index adbb5dc..0fb33b2 100644 (file)
@@ -14,13 +14,17 @@ Required properties :
      usb-cdp (USB charging downstream port)
      usb-aca (USB accessory charger adapter)
 
+Optional properties:
+ - charge-status-gpios: GPIO indicating whether a battery is charging.
+
 Example:
 
        usb_charger: charger {
                compatible = "gpio-charger";
                charger-type = "usb-sdp";
-               gpios = <&gpf0 2 0 0 0>;
-       }
+               gpios = <&gpd 28 GPIO_ACTIVE_LOW>;
+               charge-status-gpios = <&gpc 27 GPIO_ACTIVE_LOW>;
+       };
 
        battery {
                power-supplies = <&usb_charger>;
diff --git a/Documentation/devicetree/bindings/power/supply/ingenic,battery.txt b/Documentation/devicetree/bindings/power/supply/ingenic,battery.txt
new file mode 100644 (file)
index 0000000..66430bf
--- /dev/null
@@ -0,0 +1,31 @@
+* Ingenic JZ47xx battery bindings
+
+Required properties:
+
+- compatible: Must be "ingenic,jz4740-battery".
+- io-channels: phandle and IIO specifier pair to the IIO device.
+  Format described in iio-bindings.txt.
+- monitored-battery: phandle to a "simple-battery" compatible node.
+
+The "monitored-battery" property must be a phandle to a node using the format
+described in battery.txt, with the following properties being required:
+
+- voltage-min-design-microvolt: Drained battery voltage.
+- voltage-max-design-microvolt: Fully charged battery voltage.
+
+Example:
+
+#include <dt-bindings/iio/adc/ingenic,adc.h>
+
+simple_battery: battery {
+       compatible = "simple-battery";
+       voltage-min-design-microvolt = <3600000>;
+       voltage-max-design-microvolt = <4200000>;
+};
+
+ingenic_battery {
+       compatible = "ingenic,jz4740-battery";
+       io-channels = <&adc INGENIC_ADC_BATTERY>;
+       io-channel-names = "battery";
+       monitored-battery = <&simple_battery>;
+};
diff --git a/Documentation/devicetree/bindings/power/supply/lt3651-charger.txt b/Documentation/devicetree/bindings/power/supply/lt3651-charger.txt
new file mode 100644 (file)
index 0000000..40811ff
--- /dev/null
@@ -0,0 +1,29 @@
+Analog Devices LT3651 Charger Power Supply bindings: lt3651-charger
+
+Required properties:
+- compatible: Should contain one of the following:
+ * "lltc,ltc3651-charger", (DEPRECATED: Use "lltc,lt3651-charger")
+ * "lltc,lt3651-charger"
+ - lltc,acpr-gpios: Connect to ACPR output. See remark below.
+
+Optional properties:
+ - lltc,fault-gpios: Connect to FAULT output. See remark below.
+ - lltc,chrg-gpios: Connect to CHRG output. See remark below.
+
+The lt3651 outputs are open-drain type and active low. The driver assumes the
+GPIO reports "active" when the output is asserted, so if the pins have been
+connected directly, the GPIO flags should be set to active low also.
+
+The driver will attempt to aquire interrupts for all GPIOs to detect changes in
+line state. If the system is not capabale of providing interrupts, the driver
+cannot report changes and userspace will need to periodically read the sysfs
+attributes to detect changes.
+
+Example:
+
+       charger: battery-charger {
+               compatible = "lltc,lt3651-charger";
+               lltc,acpr-gpios = <&gpio0 68 GPIO_ACTIVE_LOW>;
+               lltc,fault-gpios = <&gpio0 64 GPIO_ACTIVE_LOW>;
+               lltc,chrg-gpios = <&gpio0 63 GPIO_ACTIVE_LOW>;
+       };
diff --git a/Documentation/devicetree/bindings/power/supply/ltc3651-charger.txt b/Documentation/devicetree/bindings/power/supply/ltc3651-charger.txt
deleted file mode 100644 (file)
index 71f2840..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-ltc3651-charger
-
-Required properties:
- - compatible: "lltc,ltc3651-charger"
- - lltc,acpr-gpios: Connect to ACPR output. See remark below.
-
-Optional properties:
- - lltc,fault-gpios: Connect to FAULT output. See remark below.
- - lltc,chrg-gpios: Connect to CHRG output. See remark below.
-
-The ltc3651 outputs are open-drain type and active low. The driver assumes the
-GPIO reports "active" when the output is asserted, so if the pins have been
-connected directly, the GPIO flags should be set to active low also.
-
-The driver will attempt to aquire interrupts for all GPIOs to detect changes in
-line state. If the system is not capabale of providing interrupts, the driver
-cannot report changes and userspace will need to periodically read the sysfs
-attributes to detect changes.
-
-Example:
-
-       charger: battery-charger {
-               compatible = "lltc,ltc3651-charger";
-               lltc,acpr-gpios = <&gpio0 68 GPIO_ACTIVE_LOW>;
-               lltc,fault-gpios = <&gpio0 64 GPIO_ACTIVE_LOW>;
-               lltc,chrg-gpios = <&gpio0 63 GPIO_ACTIVE_LOW>;
-       };
diff --git a/Documentation/devicetree/bindings/power/supply/max77650-charger.txt b/Documentation/devicetree/bindings/power/supply/max77650-charger.txt
new file mode 100644 (file)
index 0000000..e6d0fb6
--- /dev/null
@@ -0,0 +1,28 @@
+Battery charger driver for MAX77650 PMIC from Maxim Integrated.
+
+This module is part of the MAX77650 MFD device. For more details
+see Documentation/devicetree/bindings/mfd/max77650.txt.
+
+The charger is represented as a sub-node of the PMIC node on the device tree.
+
+Required properties:
+--------------------
+- compatible:          Must be "maxim,max77650-charger"
+
+Optional properties:
+--------------------
+- input-voltage-min-microvolt: Minimum CHGIN regulation voltage. Must be one
+                               of: 4000000, 4100000, 4200000, 4300000,
+                               4400000, 4500000, 4600000, 4700000.
+- input-current-limit-microamp:        CHGIN input current limit (in microamps). Must
+                               be one of: 95000, 190000, 285000, 380000,
+                               475000.
+
+Example:
+--------
+
+       charger {
+               compatible = "maxim,max77650-charger";
+               input-voltage-min-microvolt = <4200000>;
+               input-current-limit-microamp = <285000>;
+       };
diff --git a/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt
new file mode 100644 (file)
index 0000000..1d284ad
--- /dev/null
@@ -0,0 +1,27 @@
+Microchip UCS1002 USB Port Power Controller
+
+Required properties:
+- compatible           : Should be "microchip,ucs1002";
+- reg                  : I2C slave address
+
+Optional properties:
+- interrupts           : A list of interrupts lines present (could be either
+                         corresponding to A_DET# pin, ALERT# pin, or both)
+- interrupt-names      : A list of interrupt names. Should contain (if
+                         present):
+                         - "a_det" for line connected to A_DET# pin
+                         - "alert" for line connected to ALERT# pin
+                         Both are expected to be IRQ_TYPE_EDGE_BOTH
+Example:
+
+&i2c3 {
+       charger@32 {
+               compatible = "microchip,ucs1002";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_ucs1002_pins>;
+               reg = <0x32>;
+               interrupts-extended = <&gpio5 2 IRQ_TYPE_EDGE_BOTH>,
+                                     <&gpio3 21 IRQ_TYPE_EDGE_BOTH>;
+               interrupt-names = "a_det", "alert";
+       };
+};
index c8901b3..8d87d6b 100644 (file)
@@ -2,4 +2,4 @@ OLPC battery
 ~~~~~~~~~~~~
 
 Required properties:
-  - compatible : "olpc,xo1-battery"
+  - compatible : "olpc,xo1-battery" or "olpc,xo1.5-battery"
index 3683874..9012a2a 100644 (file)
@@ -7,6 +7,10 @@ Required properties:
 - compatible: should be "pps-gpio"
 - gpios: one PPS GPIO in the format described by ../gpio/gpio.txt
 
+Additional required properties for the PPS ECHO functionality:
+- echo-gpios: one PPS ECHO GPIO in the format described by ../gpio/gpio.txt
+- echo-active-ms: duration in ms of the active portion of the echo pulse
+
 Optional properties:
 - assert-falling-edge: when present, assert is indicated by a falling edge
                        (instead of by a rising edge)
@@ -19,5 +23,8 @@ Example:
                gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
                assert-falling-edge;
 
+               echo-gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+               echo-active-ms = <100>;
+
                compatible = "pps-gpio";
        };
index 2bf3344..2df4bdd 100644 (file)
@@ -5,11 +5,12 @@ Please also refer to reset.txt in this directory for common reset
 controller binding usage.
 
 The reset controller registers are part of the system-ctl block on
-hi3660 SoC.
+hi3660 and hi3670 SoCs.
 
 Required properties:
-- compatible: should be
-                "hisilicon,hi3660-reset"
+- compatible: should be one of the following:
+                "hisilicon,hi3660-reset" for HI3660
+                "hisilicon,hi3670-reset", "hisilicon,hi3660-reset" for HI3670
 - hisi,rst-syscon: phandle of the reset's syscon.
 - #reset-cells : Specifies the number of cells needed to encode a
   reset source.  The type shall be a <u32> and the value shall be 2.
index bcfb131..c6b5262 100644 (file)
@@ -1,4 +1,4 @@
-* Mediatek Universal Asynchronous Receiver/Transmitter (UART)
+* MediaTek Universal Asynchronous Receiver/Transmitter (UART)
 
 Required properties:
 - compatible should contain:
@@ -13,10 +13,12 @@ Required properties:
   * "mediatek,mt6797-uart" for MT6797 compatible UARTS
   * "mediatek,mt7622-uart" for MT7622 compatible UARTS
   * "mediatek,mt7623-uart" for MT7623 compatible UARTS
+  * "mediatek,mt7629-uart" for MT7629 compatible UARTS
   * "mediatek,mt8127-uart" for MT8127 compatible UARTS
   * "mediatek,mt8135-uart" for MT8135 compatible UARTS
   * "mediatek,mt8173-uart" for MT8173 compatible UARTS
   * "mediatek,mt8183-uart", "mediatek,mt6577-uart" for MT8183 compatible UARTS
+  * "mediatek,mt8516-uart" for MT8516 compatible UARTS
   * "mediatek,mt6577-uart" for MT6577 and all of the above
 
 - reg: The base address of the UART register bank.
index 5a2ef17..7a32404 100644 (file)
@@ -25,6 +25,7 @@ Required properties in pwrap device node.
        "mediatek,mt8135-pwrap" for MT8135 SoCs
        "mediatek,mt8173-pwrap" for MT8173 SoCs
        "mediatek,mt8183-pwrap" for MT8183 SoCs
+       "mediatek,mt8516-pwrap" for MT8516 SoCs
 - interrupts: IRQ for pwrap in SOC
 - reg-names: Must include the following entries:
   "pwrap": Main registers base
index d6fe16f..876693a 100644 (file)
@@ -23,6 +23,7 @@ Required properties:
        - "mediatek,mt7622-scpsys"
        - "mediatek,mt7623-scpsys", "mediatek,mt2701-scpsys": For MT7623 SoC
        - "mediatek,mt7623a-scpsys": For MT7623A SoC
+       - "mediatek,mt7629-scpsys", "mediatek,mt7622-scpsys": For MT7629 SoC
        - "mediatek,mt8173-scpsys"
 - #power-domain-cells: Must be 1
 - reg: Address range of the SCPSYS unit
@@ -33,8 +34,8 @@ Required properties:
        Required clocks for MT2701 or MT7623: "mm", "mfg", "ethif"
        Required clocks for MT2712: "mm", "mfg", "venc", "jpgdec", "audio", "vdec"
        Required clocks for MT6797: "mm", "mfg", "vdec"
-       Required clocks for MT7622: "hif_sel"
-       Required clocks for MT7622A: "ethif"
+       Required clocks for MT7622 or MT7629: "hif_sel"
+       Required clocks for MT7623A: "ethif"
        Required clocks for MT8173: "mm", "mfg", "venc", "venc_lt"
 
 Optional properties:
diff --git a/Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt b/Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt
new file mode 100644 (file)
index 0000000..703979d
--- /dev/null
@@ -0,0 +1,33 @@
+Amazon's Annapurna Labs Thermal Sensor
+
+Simple thermal device that allows temperature reading by a single MMIO
+transaction.
+
+Required properties:
+- compatible: "amazon,al-thermal".
+- reg: The physical base address and length of the sensor's registers.
+- #thermal-sensor-cells: Must be 1. See ./thermal.txt for a description.
+
+Example:
+       thermal: thermal {
+               compatible = "amazon,al-thermal";
+               reg = <0x0 0x05002860 0x0 0x1>;
+               #thermal-sensor-cells = <0x1>;
+       };
+
+       thermal-zones {
+               thermal-z0 {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+                       thermal-sensors = <&thermal 0>;
+                       trips {
+                               critical {
+                                       temperature = <105000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
+
+               };
+       };
+
index b6c0ae5..f02f385 100644 (file)
@@ -52,13 +52,47 @@ Required properties :
         Must set as following values:
         TEGRA_SOCTHERM_THROT_LEVEL_LOW, TEGRA_SOCTHERM_THROT_LEVEL_MED
         TEGRA_SOCTHERM_THROT_LEVEL_HIGH, TEGRA_SOCTHERM_THROT_LEVEL_NONE
+      - nvidia,gpu-throt-level: This property is for Tegra124 and Tegra210.
+        It is the level of pulse skippers, which used to throttle clock
+        frequencies. It indicates gpu clock throttling depth and can be
+        programmed to any of the following values which represent a throttling
+        percentage:
+        TEGRA_SOCTHERM_THROT_LEVEL_NONE (0%)
+        TEGRA_SOCTHERM_THROT_LEVEL_LOW (50%),
+        TEGRA_SOCTHERM_THROT_LEVEL_MED (75%),
+        TEGRA_SOCTHERM_THROT_LEVEL_HIGH (85%).
       - #cooling-cells: Should be 1. This cooling device only support on/off state.
         See ./thermal.txt for a description of this property.
 
+      Optional properties: The following properties are T210 specific and
+      valid only for OCx throttle events.
+      - nvidia,count-threshold: Specifies the number of OC events that are
+        required for triggering an interrupt. Interrupts are not triggered if
+        the property is missing. A value of 0 will interrupt on every OC alarm.
+      - nvidia,polarity-active-low: Configures the polarity of the OC alaram
+        signal. If present, this means assert low, otherwise assert high.
+      - nvidia,alarm-filter: Number of clocks to filter event. When the filter
+        expires (which means the OC event has not occurred for a long time),
+        the counter is cleared and filter is rearmed. Default value is 0.
+      - nvidia,throttle-period-us: Specifies the number of uSec for which
+        throttling is engaged after the OC event is deasserted. Default value
+        is 0.
+
+Optional properties:
+- nvidia,thermtrips : When present, this property specifies the temperature at
+  which the soctherm hardware will assert the thermal trigger signal to the
+  Power Management IC, which can be configured to reset or shutdown the device.
+  It is an array of pairs where each pair represents a tsensor id followed by a
+  temperature in milli Celcius. In the absence of this property the critical
+  trip point will be used for thermtrip temperature.
+
 Note:
-- the "critical" type trip points will be set to SOC_THERM hardware as the
-shut down temperature. Once the temperature of this thermal zone is higher
-than it, the system will be shutdown or reset by hardware.
+- the "critical" type trip points will be used to set the temperature at which
+the SOC_THERM hardware will assert a thermal trigger if the "nvidia,thermtrips"
+property is missing. When the thermtrips property is present, the breach of a
+critical trip point is reported back to the thermal framework to implement
+software shutdown.
+
 - the "hot" type trip points will be set to SOC_THERM hardware as the throttle
 temperature. Once the the temperature of this thermal zone is higher
 than it, it will trigger the HW throttle event.
@@ -79,25 +113,32 @@ Example :
 
                #thermal-sensor-cells = <1>;
 
+               nvidia,thermtrips = <TEGRA124_SOCTHERM_SENSOR_CPU 102500
+                                    TEGRA124_SOCTHERM_SENSOR_GPU 103000>;
+
                throttle-cfgs {
                        /*
                         * When the "heavy" cooling device triggered,
-                        * the HW will skip cpu clock's pulse in 85% depth
+                        * the HW will skip cpu clock's pulse in 85% depth,
+                        * skip gpu clock's pulse in 85% level
                         */
                        throttle_heavy: heavy {
                                nvidia,priority = <100>;
                                nvidia,cpu-throt-percent = <85>;
+                               nvidia,gpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_HIGH>;
 
                                #cooling-cells = <1>;
                        };
 
                        /*
                         * When the "light" cooling device triggered,
-                        * the HW will skip cpu clock's pulse in 50% depth
+                        * the HW will skip cpu clock's pulse in 50% depth,
+                        * skip gpu clock's pulse in 50% level
                         */
                        throttle_light: light {
                                nvidia,priority = <80>;
                                nvidia,cpu-throt-percent = <50>;
+                               nvidia,gpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_LOW>;
 
                                #cooling-cells = <1>;
                        };
@@ -107,6 +148,17 @@ Example :
                         * arbiter will select the highest priority as the final throttle
                         * settings to skip cpu pulse.
                         */
+
+                       throttle_oc1: oc1 {
+                               nvidia,priority = <50>;
+                               nvidia,polarity-active-low;
+                               nvidia,count-threshold = <100>;
+                               nvidia,alarm-filter = <5100000>;
+                               nvidia,throttle-period-us = <0>;
+                               nvidia,cpu-throt-percent = <75>;
+                               nvidia,gpu-throt-level =
+                                               <TEGRA_SOCTHERM_THROT_LEVEL_MED>;
+                        };
                };
        };
 
index 1d9e8cf..673cc18 100644 (file)
@@ -6,11 +6,14 @@ Required properties:
     - "qcom,msm8916-tsens" (MSM8916)
     - "qcom,msm8974-tsens" (MSM8974)
     - "qcom,msm8996-tsens" (MSM8996)
+    - "qcom,qcs404-tsens", "qcom,tsens-v1" (QCS404)
     - "qcom,msm8998-tsens", "qcom,tsens-v2" (MSM8998)
     - "qcom,sdm845-tsens", "qcom,tsens-v2" (SDM845)
   The generic "qcom,tsens-v2" property must be used as a fallback for any SoC
   with version 2 of the TSENS IP. MSM8996 is the only exception because the
   generic property did not exist when support was added.
+  Similarly, the generic "qcom,tsens-v1" property must be used as a fallback for
+  any SoC with version 1 of the TSENS IP.
 
 - reg: Address range of the thermal registers.
   New platforms containing v2.x.y of the TSENS IP must specify the SROT and TM
@@ -39,3 +42,14 @@ tsens0: thermal-sensor@c263000 {
                #qcom,sensors = <13>;
                #thermal-sensor-cells = <1>;
        };
+
+Example 3 (for any platform containing v1 of the TSENS IP):
+tsens: thermal-sensor@4a9000 {
+               compatible = "qcom,qcs404-tsens", "qcom,tsens-v1";
+               reg = <0x004a9000 0x1000>, /* TM */
+                     <0x004a8000 0x1000>; /* SROT */
+               nvmem-cells = <&tsens_caldata>;
+               nvmem-cell-names = "calib";
+               #qcom,sensors = <10>;
+               #thermal-sensor-cells = <1>;
+       };
index 43d744e..c6aac9b 100644 (file)
@@ -2,6 +2,7 @@
 
 Required properties:
 - compatible : should be "rockchip,<name>-tsadc"
+   "rockchip,px30-tsadc":   found on PX30 SoCs
    "rockchip,rv1108-tsadc": found on RV1108 SoCs
    "rockchip,rk3228-tsadc": found on RK3228 SoCs
    "rockchip,rk3288-tsadc": found on RK3288 SoCs
index d723555..691a09d 100644 (file)
@@ -8,16 +8,22 @@ temperature using voltage-temperature lookup table.
 Required properties:
 ===================
 - compatible:               Must be "generic-adc-thermal".
+- #thermal-sensor-cells:     Should be 1. See ./thermal.txt for a description
+                            of this property.
+Optional properties:
+===================
 - temperature-lookup-table:  Two dimensional array of Integer; lookup table
                             to map the relation between ADC value and
                             temperature. When ADC is read, the value is
                             looked up on the table to get the equivalent
                             temperature.
+
                             The first value of the each row of array is the
                             temperature in milliCelsius and second value of
                             the each row of array is the ADC read value.
-- #thermal-sensor-cells:     Should be 1. See ./thermal.txt for a description
-                            of this property.
+
+                            If not specified, driver assumes the ADC channel
+                            gives milliCelsius directly.
 
 Example :
 #include <dt-bindings/thermal/thermal.h>
diff --git a/Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml b/Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
new file mode 100644 (file)
index 0000000..a36a074
--- /dev/null
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2018 Linaro Ltd.
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/timer/intel-ixp4xx-timer.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Intel IXP4xx XScale Networking Processors Timers
+
+maintainers:
+  - Linus Walleij <linus.walleij@linaro.org>
+
+description: This timer is found in the Intel IXP4xx processors.
+
+properties:
+  compatible:
+    items:
+      - const: intel,ixp4xx-timer
+
+  reg:
+    description: Should contain registers location and length
+
+  interrupts:
+    minItems: 1
+    maxItems: 2
+    items:
+      - description: Timer 1 interrupt
+      - description: Timer 2 interrupt
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    timer@c8005000 {
+        compatible = "intel,ixp4xx-timer";
+        reg = <0xc8005000 0x100>;
+        interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+    };
index ff7c567..74c3ead 100644 (file)
@@ -17,6 +17,7 @@ Required properties:
        * "mediatek,mt8127-timer" for MT8127 compatible timers (GPT)
        * "mediatek,mt8135-timer" for MT8135 compatible timers (GPT)
        * "mediatek,mt8173-timer" for MT8173 compatible timers (GPT)
+       * "mediatek,mt8516-timer" for MT8516 compatible timers (GPT)
        * "mediatek,mt6577-timer" for MT6577 and all above compatible timers (GPT)
 
        For those SoCs that use SYST
index 56bccde..a747204 100644 (file)
@@ -11,6 +11,7 @@ Required properties:
                          the appropriate jedec string:
                            "qcom,msm8994-ufshc", "qcom,ufshc", "jedec,ufs-2.0"
                            "qcom,msm8996-ufshc", "qcom,ufshc", "jedec,ufs-2.0"
+                           "qcom,msm8998-ufshc", "qcom,ufshc", "jedec,ufs-2.0"
                            "qcom,sdm845-ufshc", "qcom,ufshc", "jedec,ufs-2.0"
 - interrupts        : <interrupt mapping for UFS host controller IRQ>
 - reg               : <registers mapping>
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
deleted file mode 100644 (file)
index 9ed3999..0000000
+++ /dev/null
@@ -1,468 +0,0 @@
-Device tree binding vendor prefix registry.  Keep list in alphabetical order.
-
-This isn't an exhaustive list, but you should add new prefixes to it before
-using them to avoid name-space collisions.
-
-abilis Abilis Systems
-abracon        Abracon Corporation
-actions        Actions Semiconductor Co., Ltd.
-active-semi    Active-Semi International Inc
-ad     Avionic Design GmbH
-adafruit       Adafruit Industries, LLC
-adapteva       Adapteva, Inc.
-adaptrum       Adaptrum, Inc.
-adh    AD Holdings Plc.
-adi    Analog Devices, Inc.
-advantech      Advantech Corporation
-aeroflexgaisler        Aeroflex Gaisler AB
-al     Annapurna Labs
-allo   Allo.com
-allwinner      Allwinner Technology Co., Ltd.
-alphascale     AlphaScale Integrated Circuits Systems, Inc.
-altr   Altera Corp.
-amarula        Amarula Solutions
-amazon Amazon.com, Inc.
-amcc   Applied Micro Circuits Corporation (APM, formally AMCC)
-amd    Advanced Micro Devices (AMD), Inc.
-amediatech     Shenzhen Amediatech Technology Co., Ltd
-amlogic        Amlogic, Inc.
-ampire Ampire Co., Ltd.
-ams    AMS AG
-amstaos        AMS-Taos Inc.
-analogix       Analogix Semiconductor, Inc.
-andestech      Andes Technology Corporation
-apm    Applied Micro Circuits Corporation (APM)
-aptina Aptina Imaging
-arasan Arasan Chip Systems
-archermind ArcherMind Technology (Nanjing) Co., Ltd.
-arctic Arctic Sand
-arcx   arcx Inc. / Archronix Inc.
-aries  Aries Embedded GmbH
-arm    ARM Ltd.
-armadeus       ARMadeus Systems SARL
-arrow  Arrow Electronics
-artesyn        Artesyn Embedded Technologies Inc.
-asahi-kasei    Asahi Kasei Corp.
-aspeed ASPEED Technology Inc.
-asus   AsusTek Computer Inc.
-atlas  Atlas Scientific LLC
-atmel  Atmel Corporation
-auo    AU Optronics Corporation
-auvidea Auvidea GmbH
-avago  Avago Technologies
-avia   avia semiconductor
-avic   Shanghai AVIC Optoelectronics Co., Ltd.
-avnet  Avnet, Inc.
-axentia        Axentia Technologies AB
-axis   Axis Communications AB
-bananapi BIPAI KEJI LIMITED
-bhf    Beckhoff Automation GmbH & Co. KG
-bitmain        Bitmain Technologies
-boe    BOE Technology Group Co., Ltd.
-bosch  Bosch Sensortec GmbH
-boundary       Boundary Devices Inc.
-brcm   Broadcom Corporation
-buffalo        Buffalo, Inc.
-bticino Bticino International
-calxeda        Calxeda
-capella        Capella Microsystems, Inc
-cascoda        Cascoda, Ltd.
-catalyst       Catalyst Semiconductor, Inc.
-cavium Cavium, Inc.
-cdns   Cadence Design Systems Inc.
-cdtech CDTech(H.K.) Electronics Limited
-ceva   Ceva, Inc.
-chipidea       Chipidea, Inc
-chipone                ChipOne
-chipspark      ChipSPARK
-chrp   Common Hardware Reference Platform
-chunghwa       Chunghwa Picture Tubes Ltd.
-ciaa   Computadora Industrial Abierta Argentina
-cirrus Cirrus Logic, Inc.
-cloudengines   Cloud Engines, Inc.
-cnm    Chips&Media, Inc.
-cnxt   Conexant Systems, Inc.
-compulab       CompuLab Ltd.
-cortina        Cortina Systems, Inc.
-cosmic Cosmic Circuits
-crane  Crane Connectivity Solutions
-creative       Creative Technology Ltd
-crystalfontz   Crystalfontz America, Inc.
-csky   Hangzhou C-SKY Microsystems Co., Ltd
-cubietech      Cubietech, Ltd.
-cypress        Cypress Semiconductor Corporation
-cznic  CZ.NIC, z.s.p.o.
-dallas Maxim Integrated Products (formerly Dallas Semiconductor)
-dataimage      DataImage, Inc.
-davicom        DAVICOM Semiconductor, Inc.
-delta  Delta Electronics, Inc.
-denx   Denx Software Engineering
-devantech      Devantech, Ltd.
-dh     DH electronics GmbH
-digi   Digi International Inc.
-digilent       Diglent, Inc.
-dioo   Dioo Microcircuit Co., Ltd
-dlc    DLC Display Co., Ltd.
-dlg    Dialog Semiconductor
-dlink  D-Link Corporation
-dmo    Data Modul AG
-domintech      Domintech Co., Ltd.
-dongwoon       Dongwoon Anatech
-dptechnics     DPTechnics
-dragino        Dragino Technology Co., Limited
-ea     Embedded Artists AB
-ebs-systart EBS-SYSTART GmbH
-ebv    EBV Elektronik
-eckelmann      Eckelmann AG
-edt    Emerging Display Technologies
-eeti   eGalax_eMPIA Technology Inc
-elan   Elan Microelectronic Corp.
-elgin  Elgin S/A.
-embest Shenzhen Embest Technology Co., Ltd.
-emlid  Emlid, Ltd.
-emmicro        EM Microelectronic
-emtrion        emtrion GmbH
-endless        Endless Mobile, Inc.
-energymicro    Silicon Laboratories (formerly Energy Micro AS)
-engicam        Engicam S.r.l.
-epcos  EPCOS AG
-epfl   Ecole Polytechnique Fédérale de Lausanne
-epson  Seiko Epson Corp.
-est    ESTeem Wireless Modems
-ettus  NI Ettus Research
-eukrea  Eukréa Electromatique
-everest        Everest Semiconductor Co. Ltd.
-everspin       Everspin Technologies, Inc.
-exar   Exar Corporation
-excito Excito
-ezchip EZchip Semiconductor
-facebook       Facebook
-fairphone      Fairphone B.V.
-faraday        Faraday Technology Corporation
-fastrax        Fastrax Oy
-fcs    Fairchild Semiconductor
-feiyang        Shenzhen Fly Young Technology Co.,LTD.
-firefly        Firefly
-focaltech      FocalTech Systems Co.,Ltd
-friendlyarm    Guangzhou FriendlyARM Computer Tech Co., Ltd
-fsl    Freescale Semiconductor
-fujitsu        Fujitsu Ltd.
-gateworks      Gateworks Corporation
-gcw Game Consoles Worldwide
-ge     General Electric Company
-geekbuying     GeekBuying
-gef    GE Fanuc Intelligent Platforms Embedded Systems, Inc.
-GEFanuc        GE Fanuc Intelligent Platforms Embedded Systems, Inc.
-geniatech      Geniatech, Inc.
-giantec        Giantec Semiconductor, Inc.
-giantplus      Giantplus Technology Co., Ltd.
-globalscale    Globalscale Technologies, Inc.
-globaltop      GlobalTop Technology, Inc.
-gmt    Global Mixed-mode Technology, Inc.
-goodix Shenzhen Huiding Technology Co., Ltd.
-google Google, Inc.
-grinn  Grinn
-grmn   Garmin Limited
-gumstix        Gumstix, Inc.
-gw     Gateworks Corporation
-hannstar       HannStar Display Corporation
-haoyu  Haoyu Microelectronic Co. Ltd.
-hardkernel     Hardkernel Co., Ltd
-hideep HiDeep Inc.
-himax  Himax Technologies, Inc.
-hisilicon      Hisilicon Limited.
-hit    Hitachi Ltd.
-hitex  Hitex Development Tools
-holt   Holt Integrated Circuits, Inc.
-honeywell      Honeywell
-hp     Hewlett Packard
-holtek Holtek Semiconductor, Inc.
-hwacom HwaCom Systems Inc.
-i2se   I2SE GmbH
-ibm    International Business Machines (IBM)
-icplus IC Plus Corp.
-idt    Integrated Device Technologies, Inc.
-ifi    Ingenieurburo Fur Ic-Technologie (I/F/I)
-ilitek ILI Technology Corporation (ILITEK)
-img    Imagination Technologies Ltd.
-infineon Infineon Technologies
-inforce        Inforce Computing
-ingenic        Ingenic Semiconductor
-innolux        Innolux Corporation
-inside-secure  INSIDE Secure
-intel  Intel Corporation
-intercontrol   Inter Control Group
-invensense     InvenSense Inc.
-inversepath    Inverse Path
-iom    Iomega Corporation
-isee   ISEE 2007 S.L.
-isil   Intersil
-issi   Integrated Silicon Solutions Inc.
-itead  ITEAD Intelligent Systems Co.Ltd
-iwave  iWave Systems Technologies Pvt. Ltd.
-jdi    Japan Display Inc.
-jedec  JEDEC Solid State Technology Association
-jianda Jiandangjing Technology Co., Ltd.
-karo   Ka-Ro electronics GmbH
-keithkoep      Keith & Koep GmbH
-keymile        Keymile GmbH
-khadas Khadas
-kiebackpeter    Kieback & Peter GmbH
-kinetic Kinetic Technologies
-kingdisplay    King & Display Technology Co., Ltd.
-kingnovel      Kingnovel Technology Co., Ltd.
-kionix Kionix, Inc.
-koe    Kaohsiung Opto-Electronics Inc.
-kosagi Sutajio Ko-Usagi PTE Ltd.
-kyo    Kyocera Corporation
-lacie  LaCie
-laird  Laird PLC
-lantiq Lantiq Semiconductor
-lattice        Lattice Semiconductor
-lego   LEGO Systems A/S
-lemaker        Shenzhen LeMaker Technology Co., Ltd.
-lenovo Lenovo Group Ltd.
-lg     LG Corporation
-libretech      Shenzhen Libre Technology Co., Ltd
-licheepi       Lichee Pi
-linaro Linaro Limited
-linksys        Belkin International, Inc. (Linksys)
-linux  Linux-specific binding
-linx   Linx Technologies
-lltc   Linear Technology Corporation
-logicpd        Logic PD, Inc.
-lsi    LSI Corp. (LSI Logic)
-lwn    Liebherr-Werk Nenzing GmbH
-macnica        Macnica Americas
-marvell        Marvell Technology Group Ltd.
-maxbotix       MaxBotix Inc.
-maxim  Maxim Integrated Products
-mbvl   Mobiveil Inc.
-mcube  mCube
-meas   Measurement Specialties
-mediatek       MediaTek Inc.
-megachips      MegaChips
-mele   Shenzhen MeLE Digital Technology Ltd.
-melexis        Melexis N.V.
-melfas MELFAS Inc.
-mellanox       Mellanox Technologies
-memsic MEMSIC Inc.
-merrii Merrii Technology Co., Ltd.
-micrel Micrel Inc.
-microchip      Microchip Technology Inc.
-microcrystal   Micro Crystal AG
-micron Micron Technology Inc.
-mikroe         MikroElektronika d.o.o.
-minix  MINIX Technology Ltd.
-miramems       MiraMEMS Sensing Technology Co., Ltd.
-mitsubishi     Mitsubishi Electric Corporation
-mosaixtech     Mosaix Technologies, Inc.
-motorola       Motorola, Inc.
-moxa   Moxa Inc.
-mpl    MPL AG
-mqmaker        mqmaker Inc.
-mscc   Microsemi Corporation
-msi    Micro-Star International Co. Ltd.
-mti    Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
-multi-inno     Multi-Inno Technology Co.,Ltd
-mundoreader    Mundo Reader S.L.
-murata Murata Manufacturing Co., Ltd.
-mxicy  Macronix International Co., Ltd.
-myir   MYIR Tech Limited
-national       National Semiconductor
-nec    NEC LCD Technologies, Ltd.
-neonode                Neonode Inc.
-netgear        NETGEAR
-netlogic       Broadcom Corporation (formerly NetLogic Microsystems)
-netron-dy      Netron DY
-netxeon                Shenzhen Netxeon Technology CO., LTD
-nexbox Nexbox
-nextthing      Next Thing Co.
-newhaven       Newhaven Display International
-ni     National Instruments
-nintendo       Nintendo
-nlt    NLT Technologies, Ltd.
-nokia  Nokia
-nordic Nordic Semiconductor
-novtech NovTech, Inc.
-nutsboard      NutsBoard
-nuvoton        Nuvoton Technology Corporation
-nvd    New Vision Display
-nvidia NVIDIA
-nxp    NXP Semiconductors
-okaya  Okaya Electric America, Inc.
-oki    Oki Electric Industry Co., Ltd.
-olimex OLIMEX Ltd.
-olpc   One Laptop Per Child
-onion  Onion Corporation
-onnn   ON Semiconductor Corp.
-ontat  On Tat Industrial Company
-opalkelly      Opal Kelly Incorporated
-opencores      OpenCores.org
-openrisc       OpenRISC.io
-option Option NV
-oranth Shenzhen Oranth Technology Co., Ltd.
-ORCL   Oracle Corporation
-orisetech      Orise Technology
-ortustech      Ortus Technology Co., Ltd.
-osddisplays    OSD Displays
-ovti   OmniVision Technologies
-oxsemi Oxford Semiconductor, Ltd.
-panasonic      Panasonic Corporation
-parade Parade Technologies Inc.
-pda    Precision Design Associates, Inc.
-pericom        Pericom Technology Inc.
-pervasive      Pervasive Displays, Inc.
-phicomm PHICOMM Co., Ltd.
-phytec PHYTEC Messtechnik GmbH
-picochip       Picochip Ltd
-pine64 Pine64
-pixcir  PIXCIR MICROELECTRONICS Co., Ltd
-plantower Plantower Co., Ltd
-plathome       Plat'Home Co., Ltd.
-plda   PLDA
-plx    Broadcom Corporation (formerly PLX Technology)
-pni    PNI Sensor Corporation
-portwell       Portwell Inc.
-poslab Poslab Technology Co., Ltd.
-powervr        PowerVR (deprecated, use img)
-probox2        PROBOX2 (by W2COMP Co., Ltd.)
-pulsedlight    PulsedLight, Inc
-qca    Qualcomm Atheros, Inc.
-qcom   Qualcomm Technologies, Inc
-qemu   QEMU, a generic and open source machine emulator and virtualizer
-qi     Qi Hardware
-qiaodian       QiaoDian XianShi Corporation
-qnap   QNAP Systems, Inc.
-radxa  Radxa
-raidsonic      RaidSonic Technology GmbH
-ralink Mediatek/Ralink Technology Corp.
-ramtron        Ramtron International
-raspberrypi    Raspberry Pi Foundation
-raydium        Raydium Semiconductor Corp.
-rda    Unisoc Communications, Inc.
-realtek Realtek Semiconductor Corp.
-renesas        Renesas Electronics Corporation
-richtek        Richtek Technology Corporation
-ricoh  Ricoh Co. Ltd.
-rikomagic      Rikomagic Tech Corp. Ltd
-riscv  RISC-V Foundation
-rockchip       Fuzhou Rockchip Electronics Co., Ltd
-rocktech       ROCKTECH DISPLAYS LIMITED
-rohm   ROHM Semiconductor Co., Ltd
-ronbo   Ronbo Electronics
-roofull        Shenzhen Roofull Technology Co, Ltd
-samsung        Samsung Semiconductor
-samtec Samtec/Softing company
-sancloud       Sancloud Ltd
-sandisk        Sandisk Corporation
-sbs    Smart Battery System
-schindler      Schindler
-seagate        Seagate Technology PLC
-semtech        Semtech Corporation
-sensirion      Sensirion AG
-sff    Small Form Factor Committee
-sgd    Solomon Goldentek Display Corporation
-sgx    SGX Sensortech
-sharp  Sharp Corporation
-shimafuji      Shimafuji Electric, Inc.
-si-en  Si-En Technology Ltd.
-sifive SiFive, Inc.
-sigma  Sigma Designs, Inc.
-sii    Seiko Instruments, Inc.
-sil    Silicon Image
-silabs Silicon Laboratories
-silead Silead Inc.
-silergy        Silergy Corp.
-siliconmitus   Silicon Mitus, Inc.
-simtek
-sirf   SiRF Technology, Inc.
-sis    Silicon Integrated Systems Corp.
-sitronix       Sitronix Technology Corporation
-skyworks       Skyworks Solutions, Inc.
-smsc   Standard Microsystems Corporation
-snps   Synopsys, Inc.
-socionext      Socionext Inc.
-solidrun       SolidRun
-solomon        Solomon Systech Limited
-sony   Sony Corporation
-spansion       Spansion Inc.
-sprd   Spreadtrum Communications Inc.
-sst    Silicon Storage Technology, Inc.
-st     STMicroelectronics
-starry Starry Electronic Technology (ShenZhen) Co., LTD
-startek        Startek
-ste    ST-Ericsson
-stericsson     ST-Ericsson
-summit Summit microelectronics
-sunchip        Shenzhen Sunchip Technology Co., Ltd
-SUNW   Sun Microsystems, Inc
-swir   Sierra Wireless
-syna   Synaptics Inc.
-synology       Synology, Inc.
-tbs    TBS Technologies
-tbs-biometrics Touchless Biometric Systems AG
-tcg    Trusted Computing Group
-tcl    Toby Churchill Ltd.
-technexion     TechNexion
-technologic    Technologic Systems
-tempo  Tempo Semiconductor
-techstar       Shenzhen Techstar Electronics Co., Ltd.
-terasic        Terasic Inc.
-thine  THine Electronics, Inc.
-ti     Texas Instruments
-tianma Tianma Micro-electronics Co., Ltd.
-tlm    Trusted Logic Mobility
-tmt    Tecon Microprocessor Technologies, LLC.
-topeet  Topeet
-toradex        Toradex AG
-toshiba        Toshiba Corporation
-toumaz Toumaz
-tpk    TPK U.S.A. LLC
-tplink TP-LINK Technologies Co., Ltd.
-tpo    TPO
-tronfy Tronfy
-tronsmart      Tronsmart
-truly  Truly Semiconductors Limited
-tsd    Theobroma Systems Design und Consulting GmbH
-tyan   Tyan Computer Corporation
-u-blox u-blox
-ucrobotics     uCRobotics
-ubnt   Ubiquiti Networks
-udoo   Udoo
-uniwest        United Western Technologies Corp (UniWest)
-upisemi        uPI Semiconductor Corp.
-urt    United Radiant Technology Corporation
-usi    Universal Scientific Industrial Co., Ltd.
-v3     V3 Semiconductor
-vamrs  Vamrs Ltd.
-variscite      Variscite Ltd.
-via    VIA Technologies, Inc.
-virtio Virtual I/O Device Specification, developed by the OASIS consortium
-vishay Vishay Intertechnology, Inc
-vitesse        Vitesse Semiconductor Corporation
-vivante        Vivante Corporation
-vocore VoCore Studio
-voipac Voipac Technologies s.r.o.
-vot    Vision Optical Technology Co., Ltd.
-wd     Western Digital Corp.
-wetek  WeTek Electronics, limited.
-wexler Wexler
-whwave  Shenzhen whwave Electronics, Inc.
-wi2wi  Wi2Wi, Inc.
-winbond Winbond Electronics corp.
-winstar        Winstar Display Corp.
-wlf    Wolfson Microelectronics
-wm     Wondermedia Technologies, Inc.
-x-powers       X-Powers
-xes    Extreme Engineering Solutions (X-ES)
-xillybus       Xillybus Ltd.
-xlnx   Xilinx
-xunlong        Shenzhen Xunlong Software CO.,Limited
-ysoft  Y Soft Corporation a.s.
-zarlink        Zarlink Semiconductor
-zeitec ZEITEC Semiconductor Co., LTD.
-zidoo  Shenzhen Zidoo Technology Co., Ltd.
-zii    Zodiac Inflight Innovations
-zte    ZTE Corp.
-zyxel  ZyXEL Communications Corp.
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
new file mode 100644 (file)
index 0000000..33a65a4
--- /dev/null
@@ -0,0 +1,977 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/vendor-prefixes.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Devicetree Vendor Prefix Registry
+
+maintainers:
+  - Rob Herring <robh@kernel.org>
+
+select: true
+
+properties: {}
+
+patternProperties:
+  # Prefixes which are not vendors, but followed the pattern
+  # DO NOT ADD NEW PROPERTIES TO THIS LIST
+  "^(at25|devbus|dmacap|dsa|exynos|gpio-fan|gpio|gpmc|hdmi|i2c-gpio),.*": true
+  "^(keypad|m25p|max8952|max8997|max8998|mpmc),.*": true
+  "^(pinctrl-single|#pinctrl-single|PowerPC),.*": true
+  "^(pl022|pxa-mmc|rcar_sound|rotary-encoder|s5m8767|sdhci),.*": true
+  "^(simple-audio-card|simple-graph-card|st-plgpio|st-spics|ts),.*": true
+
+  # Keep list in alphabetical order.
+  "^abilis,.*":
+    description: Abilis Systems
+  "^abracon,.*":
+    description: Abracon Corporation
+  "^actions,.*":
+    description: Actions Semiconductor Co., Ltd.
+  "^active-semi,.*":
+    description: Active-Semi International Inc
+  "^ad,.*":
+    description: Avionic Design GmbH
+  "^adafruit,.*":
+    description: Adafruit Industries, LLC
+  "^adapteva,.*":
+    description: Adapteva, Inc.
+  "^adaptrum,.*":
+    description: Adaptrum, Inc.
+  "^adh,.*":
+    description: AD Holdings Plc.
+  "^adi,.*":
+    description: Analog Devices, Inc.
+  "^advantech,.*":
+    description: Advantech Corporation
+  "^aeroflexgaisler,.*":
+    description: Aeroflex Gaisler AB
+  "^al,.*":
+    description: Annapurna Labs
+  "^allo,.*":
+    description: Allo.com
+  "^allwinner,.*":
+    description: Allwinner Technology Co., Ltd.
+  "^alphascale,.*":
+    description: AlphaScale Integrated Circuits Systems, Inc.
+  "^altr,.*":
+    description: Altera Corp.
+  "^amarula,.*":
+    description: Amarula Solutions
+  "^amazon,.*":
+    description: Amazon.com, Inc.
+  "^amcc,.*":
+    description: Applied Micro Circuits Corporation (APM, formally AMCC)
+  "^amd,.*":
+    description: Advanced Micro Devices (AMD), Inc.
+  "^amediatech,.*":
+    description: Shenzhen Amediatech Technology Co., Ltd
+  "^amlogic,.*":
+    description: Amlogic, Inc.
+  "^ampire,.*":
+    description: Ampire Co., Ltd.
+  "^ams,.*":
+    description: AMS AG
+  "^amstaos,.*":
+    description: AMS-Taos Inc.
+  "^analogix,.*":
+    description: Analogix Semiconductor, Inc.
+  "^andestech,.*":
+    description: Andes Technology Corporation
+  "^apm,.*":
+    description: Applied Micro Circuits Corporation (APM)
+  "^aptina,.*":
+    description: Aptina Imaging
+  "^arasan,.*":
+    description: Arasan Chip Systems
+  "^archermind,.*":
+    description: ArcherMind Technology (Nanjing) Co., Ltd.
+  "^arctic,.*":
+    description: Arctic Sand
+  "^arcx,.*":
+    description: arcx Inc. / Archronix Inc.
+  "^aries,.*":
+    description: Aries Embedded GmbH
+  "^arm,.*":
+    description: ARM Ltd.
+  "^armadeus,.*":
+    description: ARMadeus Systems SARL
+  "^arrow,.*":
+    description: Arrow Electronics
+  "^artesyn,.*":
+    description: Artesyn Embedded Technologies Inc.
+  "^asahi-kasei,.*":
+    description: Asahi Kasei Corp.
+  "^aspeed,.*":
+    description: ASPEED Technology Inc.
+  "^asus,.*":
+    description: AsusTek Computer Inc.
+  "^atlas,.*":
+    description: Atlas Scientific LLC
+  "^atmel,.*":
+    description: Atmel Corporation
+  "^auo,.*":
+    description: AU Optronics Corporation
+  "^auvidea,.*":
+    description: Auvidea GmbH
+  "^avago,.*":
+    description: Avago Technologies
+  "^avia,.*":
+    description: avia semiconductor
+  "^avic,.*":
+    description: Shanghai AVIC Optoelectronics Co., Ltd.
+  "^avnet,.*":
+    description: Avnet, Inc.
+  "^axentia,.*":
+    description: Axentia Technologies AB
+  "^axis,.*":
+    description: Axis Communications AB
+  "^azoteq,.*":
+    description: Azoteq (Pty) Ltd
+  "^azw,.*":
+    description: Shenzhen AZW Technology Co., Ltd.
+  "^bananapi,.*":
+    description: BIPAI KEJI LIMITED
+  "^bhf,.*":
+    description: Beckhoff Automation GmbH & Co. KG
+  "^bitmain,.*":
+    description: Bitmain Technologies
+  "^boe,.*":
+    description: BOE Technology Group Co., Ltd.
+  "^bosch,.*":
+    description: Bosch Sensortec GmbH
+  "^boundary,.*":
+    description: Boundary Devices Inc.
+  "^brcm,.*":
+    description: Broadcom Corporation
+  "^buffalo,.*":
+    description: Buffalo, Inc.
+  "^bticino,.*":
+    description: Bticino International
+  "^calxeda,.*":
+    description: Calxeda
+  "^capella,.*":
+    description: Capella Microsystems, Inc
+  "^cascoda,.*":
+    description: Cascoda, Ltd.
+  "^catalyst,.*":
+    description: Catalyst Semiconductor, Inc.
+  "^cavium,.*":
+    description: Cavium, Inc.
+  "^cdns,.*":
+    description: Cadence Design Systems Inc.
+  "^cdtech,.*":
+    description: CDTech(H.K.) Electronics Limited
+  "^ceva,.*":
+    description: Ceva, Inc.
+  "^chipidea,.*":
+    description: Chipidea, Inc
+  "^chipone,.*":
+    description: ChipOne
+  "^chipspark,.*":
+    description: ChipSPARK
+  "^chrp,.*":
+    description: Common Hardware Reference Platform
+  "^chunghwa,.*":
+    description: Chunghwa Picture Tubes Ltd.
+  "^ciaa,.*":
+    description: Computadora Industrial Abierta Argentina
+  "^cirrus,.*":
+    description: Cirrus Logic, Inc.
+  "^cloudengines,.*":
+    description: Cloud Engines, Inc.
+  "^cnm,.*":
+    description: Chips&Media, Inc.
+  "^cnxt,.*":
+    description: Conexant Systems, Inc.
+  "^compulab,.*":
+    description: CompuLab Ltd.
+  "^cortina,.*":
+    description: Cortina Systems, Inc.
+  "^cosmic,.*":
+    description: Cosmic Circuits
+  "^crane,.*":
+    description: Crane Connectivity Solutions
+  "^creative,.*":
+    description: Creative Technology Ltd
+  "^crystalfontz,.*":
+    description: Crystalfontz America, Inc.
+  "^csky,.*":
+    description: Hangzhou C-SKY Microsystems Co., Ltd
+  "^cubietech,.*":
+    description: Cubietech, Ltd.
+  "^cypress,.*":
+    description: Cypress Semiconductor Corporation
+  "^cznic,.*":
+    description: CZ.NIC, z.s.p.o.
+  "^dallas,.*":
+    description: Maxim Integrated Products (formerly Dallas Semiconductor)
+  "^dataimage,.*":
+    description: DataImage, Inc.
+  "^davicom,.*":
+    description: DAVICOM Semiconductor, Inc.
+  "^delta,.*":
+    description: Delta Electronics, Inc.
+  "^denx,.*":
+    description: Denx Software Engineering
+  "^devantech,.*":
+    description: Devantech, Ltd.
+  "^dh,.*":
+    description: DH electronics GmbH
+  "^digi,.*":
+    description: Digi International Inc.
+  "^digilent,.*":
+    description: Diglent, Inc.
+  "^dioo,.*":
+    description: Dioo Microcircuit Co., Ltd
+  "^dlc,.*":
+    description: DLC Display Co., Ltd.
+  "^dlg,.*":
+    description: Dialog Semiconductor
+  "^dlink,.*":
+    description: D-Link Corporation
+  "^dmo,.*":
+    description: Data Modul AG
+  "^domintech,.*":
+    description: Domintech Co., Ltd.
+  "^dongwoon,.*":
+    description: Dongwoon Anatech
+  "^dptechnics,.*":
+    description: DPTechnics
+  "^dragino,.*":
+    description: Dragino Technology Co., Limited
+  "^ea,.*":
+    description: Embedded Artists AB
+  "^ebs-systart,.*":
+    description: EBS-SYSTART GmbH
+  "^ebv,.*":
+    description: EBV Elektronik
+  "^eckelmann,.*":
+    description: Eckelmann AG
+  "^edt,.*":
+    description: Emerging Display Technologies
+  "^eeti,.*":
+    description: eGalax_eMPIA Technology Inc
+  "^elan,.*":
+    description: Elan Microelectronic Corp.
+  "^elgin,.*":
+    description: Elgin S/A.
+  "^embest,.*":
+    description: Shenzhen Embest Technology Co., Ltd.
+  "^emlid,.*":
+    description: Emlid, Ltd.
+  "^emmicro,.*":
+    description: EM Microelectronic
+  "^emtrion,.*":
+    description: emtrion GmbH
+  "^endless,.*":
+    description: Endless Mobile, Inc.
+  "^energymicro,.*":
+    description: Silicon Laboratories (formerly Energy Micro AS)
+  "^engicam,.*":
+    description: Engicam S.r.l.
+  "^epcos,.*":
+    description: EPCOS AG
+  "^epfl,.*":
+    description: Ecole Polytechnique Fédérale de Lausanne
+  "^epson,.*":
+    description: Seiko Epson Corp.
+  "^est,.*":
+    description: ESTeem Wireless Modems
+  "^ettus,.*":
+    description: NI Ettus Research
+  "^eukrea,.*":
+    description: Eukréa Electromatique
+  "^everest,.*":
+    description: Everest Semiconductor Co. Ltd.
+  "^everspin,.*":
+    description: Everspin Technologies, Inc.
+  "^exar,.*":
+    description: Exar Corporation
+  "^excito,.*":
+    description: Excito
+  "^ezchip,.*":
+    description: EZchip Semiconductor
+  "^facebook,.*":
+    description: Facebook
+  "^fairphone,.*":
+    description: Fairphone B.V.
+  "^faraday,.*":
+    description: Faraday Technology Corporation
+  "^fastrax,.*":
+    description: Fastrax Oy
+  "^fcs,.*":
+    description: Fairchild Semiconductor
+  "^feiyang,.*":
+    description: Shenzhen Fly Young Technology Co.,LTD.
+  "^firefly,.*":
+    description: Firefly
+  "^focaltech,.*":
+    description: FocalTech Systems Co.,Ltd
+  "^friendlyarm,.*":
+    description: Guangzhou FriendlyARM Computer Tech Co., Ltd
+  "^fsl,.*":
+    description: Freescale Semiconductor
+  "^fujitsu,.*":
+    description: Fujitsu Ltd.
+  "^gateworks,.*":
+    description: Gateworks Corporation
+  "^gcw,.*":
+    description: Game Consoles Worldwide
+  "^ge,.*":
+    description: General Electric Company
+  "^geekbuying,.*":
+    description: GeekBuying
+  "^gef,.*":
+    description: GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+  "^GEFanuc,.*":
+    description: GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+  "^geniatech,.*":
+    description: Geniatech, Inc.
+  "^giantec,.*":
+    description: Giantec Semiconductor, Inc.
+  "^giantplus,.*":
+    description: Giantplus Technology Co., Ltd.
+  "^globalscale,.*":
+    description: Globalscale Technologies, Inc.
+  "^globaltop,.*":
+    description: GlobalTop Technology, Inc.
+  "^gmt,.*":
+    description: Global Mixed-mode Technology, Inc.
+  "^goodix,.*":
+    description: Shenzhen Huiding Technology Co., Ltd.
+  "^google,.*":
+    description: Google, Inc.
+  "^grinn,.*":
+    description: Grinn
+  "^grmn,.*":
+    description: Garmin Limited
+  "^gumstix,.*":
+    description: Gumstix, Inc.
+  "^gw,.*":
+    description: Gateworks Corporation
+  "^hannstar,.*":
+    description: HannStar Display Corporation
+  "^haoyu,.*":
+    description: Haoyu Microelectronic Co. Ltd.
+  "^hardkernel,.*":
+    description: Hardkernel Co., Ltd
+  "^hideep,.*":
+    description: HiDeep Inc.
+  "^himax,.*":
+    description: Himax Technologies, Inc.
+  "^hisilicon,.*":
+    description: Hisilicon Limited.
+  "^hit,.*":
+    description: Hitachi Ltd.
+  "^hitex,.*":
+    description: Hitex Development Tools
+  "^holt,.*":
+    description: Holt Integrated Circuits, Inc.
+  "^honeywell,.*":
+    description: Honeywell
+  "^hp,.*":
+    description: Hewlett Packard
+  "^holtek,.*":
+    description: Holtek Semiconductor, Inc.
+  "^hwacom,.*":
+    description: HwaCom Systems Inc.
+  "^i2se,.*":
+    description: I2SE GmbH
+  "^ibm,.*":
+    description: International Business Machines (IBM)
+  "^icplus,.*":
+    description: IC Plus Corp.
+  "^idt,.*":
+    description: Integrated Device Technologies, Inc.
+  "^ifi,.*":
+    description: Ingenieurburo Fur Ic-Technologie (I/F/I)
+  "^ilitek,.*":
+    description: ILI Technology Corporation (ILITEK)
+  "^img,.*":
+    description: Imagination Technologies Ltd.
+  "^infineon,.*":
+    description: Infineon Technologies
+  "^inforce,.*":
+    description: Inforce Computing
+  "^ingenic,.*":
+    description: Ingenic Semiconductor
+  "^innolux,.*":
+    description: Innolux Corporation
+  "^inside-secure,.*":
+    description: INSIDE Secure
+  "^intel,.*":
+    description: Intel Corporation
+  "^intercontrol,.*":
+    description: Inter Control Group
+  "^invensense,.*":
+    description: InvenSense Inc.
+  "^inversepath,.*":
+    description: Inverse Path
+  "^iom,.*":
+    description: Iomega Corporation
+  "^isee,.*":
+    description: ISEE 2007 S.L.
+  "^isil,.*":
+    description: Intersil
+  "^issi,.*":
+    description: Integrated Silicon Solutions Inc.
+  "^itead,.*":
+    description: ITEAD Intelligent Systems Co.Ltd
+  "^iwave,.*":
+    description: iWave Systems Technologies Pvt. Ltd.
+  "^jdi,.*":
+    description: Japan Display Inc.
+  "^jedec,.*":
+    description: JEDEC Solid State Technology Association
+  "^jianda,.*":
+    description: Jiandangjing Technology Co., Ltd.
+  "^karo,.*":
+    description: Ka-Ro electronics GmbH
+  "^keithkoep,.*":
+    description: Keith & Koep GmbH
+  "^keymile,.*":
+    description: Keymile GmbH
+  "^khadas,.*":
+    description: Khadas
+  "^kiebackpeter,.*":
+    description: Kieback & Peter GmbH
+  "^kinetic,.*":
+    description: Kinetic Technologies
+  "^kingdisplay,.*":
+    description: King & Display Technology Co., Ltd.
+  "^kingnovel,.*":
+    description: Kingnovel Technology Co., Ltd.
+  "^kionix,.*":
+    description: Kionix, Inc.
+  "^kobo,.*":
+    description: Rakuten Kobo Inc.
+  "^koe,.*":
+    description: Kaohsiung Opto-Electronics Inc.
+  "^kosagi,.*":
+    description: Sutajio Ko-Usagi PTE Ltd.
+  "^kyo,.*":
+    description: Kyocera Corporation
+  "^lacie,.*":
+    description: LaCie
+  "^laird,.*":
+    description: Laird PLC
+  "^lantiq,.*":
+    description: Lantiq Semiconductor
+  "^lattice,.*":
+    description: Lattice Semiconductor
+  "^lego,.*":
+    description: LEGO Systems A/S
+  "^lemaker,.*":
+    description: Shenzhen LeMaker Technology Co., Ltd.
+  "^lenovo,.*":
+    description: Lenovo Group Ltd.
+  "^lg,.*":
+    description: LG Corporation
+  "^libretech,.*":
+    description: Shenzhen Libre Technology Co., Ltd
+  "^licheepi,.*":
+    description: Lichee Pi
+  "^linaro,.*":
+    description: Linaro Limited
+  "^linksys,.*":
+    description: Belkin International, Inc. (Linksys)
+  "^linux,.*":
+    description: Linux-specific binding
+  "^linx,.*":
+    description: Linx Technologies
+  "^lltc,.*":
+    description: Linear Technology Corporation
+  "^logicpd,.*":
+    description: Logic PD, Inc.
+  "^lsi,.*":
+    description: LSI Corp. (LSI Logic)
+  "^lwn,.*":
+    description: Liebherr-Werk Nenzing GmbH
+  "^macnica,.*":
+    description: Macnica Americas
+  "^marvell,.*":
+    description: Marvell Technology Group Ltd.
+  "^maxbotix,.*":
+    description: MaxBotix Inc.
+  "^maxim,.*":
+    description: Maxim Integrated Products
+  "^mbvl,.*":
+    description: Mobiveil Inc.
+  "^mcube,.*":
+    description: mCube
+  "^meas,.*":
+    description: Measurement Specialties
+  "^mediatek,.*":
+    description: MediaTek Inc.
+  "^megachips,.*":
+    description: MegaChips
+  "^mele,.*":
+    description: Shenzhen MeLE Digital Technology Ltd.
+  "^melexis,.*":
+    description: Melexis N.V.
+  "^melfas,.*":
+    description: MELFAS Inc.
+  "^mellanox,.*":
+    description: Mellanox Technologies
+  "^memsic,.*":
+    description: MEMSIC Inc.
+  "^menlo,.*":
+    description: Menlo Systems GmbH
+  "^merrii,.*":
+    description: Merrii Technology Co., Ltd.
+  "^micrel,.*":
+    description: Micrel Inc.
+  "^microchip,.*":
+    description: Microchip Technology Inc.
+  "^microcrystal,.*":
+    description: Micro Crystal AG
+  "^micron,.*":
+    description: Micron Technology Inc.
+  "^mikroe,.*":
+    description: MikroElektronika d.o.o.
+  "^minix,.*":
+    description: MINIX Technology Ltd.
+  "^miramems,.*":
+    description: MiraMEMS Sensing Technology Co., Ltd.
+  "^mitsubishi,.*":
+    description: Mitsubishi Electric Corporation
+  "^mosaixtech,.*":
+    description: Mosaix Technologies, Inc.
+  "^motorola,.*":
+    description: Motorola, Inc.
+  "^moxa,.*":
+    description: Moxa Inc.
+  "^mpl,.*":
+    description: MPL AG
+  "^mqmaker,.*":
+    description: mqmaker Inc.
+  "^mscc,.*":
+    description: Microsemi Corporation
+  "^msi,.*":
+    description: Micro-Star International Co. Ltd.
+  "^mti,.*":
+    description: Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
+  "^multi-inno,.*":
+    description: Multi-Inno Technology Co.,Ltd
+  "^mundoreader,.*":
+    description: Mundo Reader S.L.
+  "^murata,.*":
+    description: Murata Manufacturing Co., Ltd.
+  "^mxicy,.*":
+    description: Macronix International Co., Ltd.
+  "^myir,.*":
+    description: MYIR Tech Limited
+  "^national,.*":
+    description: National Semiconductor
+  "^nec,.*":
+    description: NEC LCD Technologies, Ltd.
+  "^neonode,.*":
+    description: Neonode Inc.
+  "^netgear,.*":
+    description: NETGEAR
+  "^netlogic,.*":
+    description: Broadcom Corporation (formerly NetLogic Microsystems)
+  "^netron-dy,.*":
+    description: Netron DY
+  "^netxeon,.*":
+    description: Shenzhen Netxeon Technology CO., LTD
+  "^nexbox,.*":
+    description: Nexbox
+  "^nextthing,.*":
+    description: Next Thing Co.
+  "^newhaven,.*":
+    description: Newhaven Display International
+  "^ni,.*":
+    description: National Instruments
+  "^nintendo,.*":
+    description: Nintendo
+  "^nlt,.*":
+    description: NLT Technologies, Ltd.
+  "^nokia,.*":
+    description: Nokia
+  "^nordic,.*":
+    description: Nordic Semiconductor
+  "^novtech,.*":
+    description: NovTech, Inc.
+  "^nutsboard,.*":
+    description: NutsBoard
+  "^nuvoton,.*":
+    description: Nuvoton Technology Corporation
+  "^nvd,.*":
+    description: New Vision Display
+  "^nvidia,.*":
+    description: NVIDIA
+  "^nxp,.*":
+    description: NXP Semiconductors
+  "^oceanic,.*":
+    description: Oceanic Systems (UK) Ltd.
+  "^okaya,.*":
+    description: Okaya Electric America, Inc.
+  "^oki,.*":
+    description: Oki Electric Industry Co., Ltd.
+  "^olimex,.*":
+    description: OLIMEX Ltd.
+  "^olpc,.*":
+    description: One Laptop Per Child
+  "^onion,.*":
+    description: Onion Corporation
+  "^onnn,.*":
+    description: ON Semiconductor Corp.
+  "^ontat,.*":
+    description: On Tat Industrial Company
+  "^opalkelly,.*":
+    description: Opal Kelly Incorporated
+  "^opencores,.*":
+    description: OpenCores.org
+  "^openrisc,.*":
+    description: OpenRISC.io
+  "^option,.*":
+    description: Option NV
+  "^oranth,.*":
+    description: Shenzhen Oranth Technology Co., Ltd.
+  "^ORCL,.*":
+    description: Oracle Corporation
+  "^orisetech,.*":
+    description: Orise Technology
+  "^ortustech,.*":
+    description: Ortus Technology Co., Ltd.
+  "^osddisplays,.*":
+    description: OSD Displays
+  "^ovti,.*":
+    description: OmniVision Technologies
+  "^oxsemi,.*":
+    description: Oxford Semiconductor, Ltd.
+  "^panasonic,.*":
+    description: Panasonic Corporation
+  "^parade,.*":
+    description: Parade Technologies Inc.
+  "^pda,.*":
+    description: Precision Design Associates, Inc.
+  "^pericom,.*":
+    description: Pericom Technology Inc.
+  "^pervasive,.*":
+    description: Pervasive Displays, Inc.
+  "^phicomm,.*":
+    description: PHICOMM Co., Ltd.
+  "^phytec,.*":
+    description: PHYTEC Messtechnik GmbH
+  "^picochip,.*":
+    description: Picochip Ltd
+  "^pine64,.*":
+    description: Pine64
+  "^pixcir,.*":
+    description: PIXCIR MICROELECTRONICS Co., Ltd
+  "^plantower,.*":
+    description: Plantower Co., Ltd
+  "^plathome,.*":
+    description: Plat'Home Co., Ltd.
+  "^plda,.*":
+    description: PLDA
+  "^plx,.*":
+    description: Broadcom Corporation (formerly PLX Technology)
+  "^pni,.*":
+    description: PNI Sensor Corporation
+  "^portwell,.*":
+    description: Portwell Inc.
+  "^poslab,.*":
+    description: Poslab Technology Co., Ltd.
+  "^powervr,.*":
+    description: PowerVR (deprecated, use img)
+  "^probox2,.*":
+    description: PROBOX2 (by W2COMP Co., Ltd.)
+  "^pulsedlight,.*":
+    description: PulsedLight, Inc
+  "^qca,.*":
+    description: Qualcomm Atheros, Inc.
+  "^qcom,.*":
+    description: Qualcomm Technologies, Inc
+  "^qemu,.*":
+    description: QEMU, a generic and open source machine emulator and virtualizer
+  "^qi,.*":
+    description: Qi Hardware
+  "^qiaodian,.*":
+    description: QiaoDian XianShi Corporation
+  "^qnap,.*":
+    description: QNAP Systems, Inc.
+  "^radxa,.*":
+    description: Radxa
+  "^raidsonic,.*":
+    description: RaidSonic Technology GmbH
+  "^ralink,.*":
+    description: Mediatek/Ralink Technology Corp.
+  "^ramtron,.*":
+    description: Ramtron International
+  "^raspberrypi,.*":
+    description: Raspberry Pi Foundation
+  "^raydium,.*":
+    description: Raydium Semiconductor Corp.
+  "^rda,.*":
+    description: Unisoc Communications, Inc.
+  "^realtek,.*":
+    description: Realtek Semiconductor Corp.
+  "^renesas,.*":
+    description: Renesas Electronics Corporation
+  "^richtek,.*":
+    description: Richtek Technology Corporation
+  "^ricoh,.*":
+    description: Ricoh Co. Ltd.
+  "^rikomagic,.*":
+    description: Rikomagic Tech Corp. Ltd
+  "^riscv,.*":
+    description: RISC-V Foundation
+  "^rockchip,.*":
+    description: Fuzhou Rockchip Electronics Co., Ltd
+  "^rocktech,.*":
+    description: ROCKTECH DISPLAYS LIMITED
+  "^rohm,.*":
+    description: ROHM Semiconductor Co., Ltd
+  "^ronbo,.*":
+    description: Ronbo Electronics
+  "^roofull,.*":
+    description: Shenzhen Roofull Technology Co, Ltd
+  "^samsung,.*":
+    description: Samsung Semiconductor
+  "^samtec,.*":
+    description: Samtec/Softing company
+  "^sancloud,.*":
+    description: Sancloud Ltd
+  "^sandisk,.*":
+    description: Sandisk Corporation
+  "^sbs,.*":
+    description: Smart Battery System
+  "^schindler,.*":
+    description: Schindler
+  "^seagate,.*":
+    description: Seagate Technology PLC
+  "^seirobotics,.*":
+    description: Shenzhen SEI Robotics Co., Ltd
+  "^semtech,.*":
+    description: Semtech Corporation
+  "^sensirion,.*":
+    description: Sensirion AG
+  "^sff,.*":
+    description: Small Form Factor Committee
+  "^sgd,.*":
+    description: Solomon Goldentek Display Corporation
+  "^sgx,.*":
+    description: SGX Sensortech
+  "^sharp,.*":
+    description: Sharp Corporation
+  "^shimafuji,.*":
+    description: Shimafuji Electric, Inc.
+  "^si-en,.*":
+    description: Si-En Technology Ltd.
+  "^si-linux,.*":
+    description: Silicon Linux Corporation
+  "^sifive,.*":
+    description: SiFive, Inc.
+  "^sigma,.*":
+    description: Sigma Designs, Inc.
+  "^sii,.*":
+    description: Seiko Instruments, Inc.
+  "^sil,.*":
+    description: Silicon Image
+  "^silabs,.*":
+    description: Silicon Laboratories
+  "^silead,.*":
+    description: Silead Inc.
+  "^silergy,.*":
+    description: Silergy Corp.
+  "^siliconmitus,.*":
+    description: Silicon Mitus, Inc.
+  "^simte,.*":
+    description: k
+  "^sirf,.*":
+    description: SiRF Technology, Inc.
+  "^sis,.*":
+    description: Silicon Integrated Systems Corp.
+  "^sitronix,.*":
+    description: Sitronix Technology Corporation
+  "^skyworks,.*":
+    description: Skyworks Solutions, Inc.
+  "^smsc,.*":
+    description: Standard Microsystems Corporation
+  "^snps,.*":
+    description: Synopsys, Inc.
+  "^socionext,.*":
+    description: Socionext Inc.
+  "^solidrun,.*":
+    description: SolidRun
+  "^solomon,.*":
+    description: Solomon Systech Limited
+  "^sony,.*":
+    description: Sony Corporation
+  "^spansion,.*":
+    description: Spansion Inc.
+  "^sprd,.*":
+    description: Spreadtrum Communications Inc.
+  "^sst,.*":
+    description: Silicon Storage Technology, Inc.
+  "^st,.*":
+    description: STMicroelectronics
+  "^starry,.*":
+    description: Starry Electronic Technology (ShenZhen) Co., LTD
+  "^startek,.*":
+    description: Startek
+  "^ste,.*":
+    description: ST-Ericsson
+  "^stericsson,.*":
+    description: ST-Ericsson
+  "^summit,.*":
+    description: Summit microelectronics
+  "^sunchip,.*":
+    description: Shenzhen Sunchip Technology Co., Ltd
+  "^SUNW,.*":
+    description: Sun Microsystems, Inc
+  "^swir,.*":
+    description: Sierra Wireless
+  "^syna,.*":
+    description: Synaptics Inc.
+  "^synology,.*":
+    description: Synology, Inc.
+  "^tbs,.*":
+    description: TBS Technologies
+  "^tbs-biometrics,.*":
+    description: Touchless Biometric Systems AG
+  "^tcg,.*":
+    description: Trusted Computing Group
+  "^tcl,.*":
+    description: Toby Churchill Ltd.
+  "^technexion,.*":
+    description: TechNexion
+  "^technologic,.*":
+    description: Technologic Systems
+  "^tempo,.*":
+    description: Tempo Semiconductor
+  "^techstar,.*":
+    description: Shenzhen Techstar Electronics Co., Ltd.
+  "^terasic,.*":
+    description: Terasic Inc.
+  "^thine,.*":
+    description: THine Electronics, Inc.
+  "^ti,.*":
+    description: Texas Instruments
+  "^tianma,.*":
+    description: Tianma Micro-electronics Co., Ltd.
+  "^tlm,.*":
+    description: Trusted Logic Mobility
+  "^tmt,.*":
+    description: Tecon Microprocessor Technologies, LLC.
+  "^topeet,.*":
+    description: Topeet
+  "^toradex,.*":
+    description: Toradex AG
+  "^toshiba,.*":
+    description: Toshiba Corporation
+  "^toumaz,.*":
+    description: Toumaz
+  "^tpk,.*":
+    description: TPK U.S.A. LLC
+  "^tplink,.*":
+    description: TP-LINK Technologies Co., Ltd.
+  "^tpo,.*":
+    description: TPO
+  "^tq,.*":
+    description: TQ Systems GmbH
+  "^tronfy,.*":
+    description: Tronfy
+  "^tronsmart,.*":
+    description: Tronsmart
+  "^truly,.*":
+    description: Truly Semiconductors Limited
+  "^tsd,.*":
+    description: Theobroma Systems Design und Consulting GmbH
+  "^tyan,.*":
+    description: Tyan Computer Corporation
+  "^u-blox,.*":
+    description: u-blox
+  "^ucrobotics,.*":
+    description: uCRobotics
+  "^ubnt,.*":
+    description: Ubiquiti Networks
+  "^udoo,.*":
+    description: Udoo
+  "^uniwest,.*":
+    description: United Western Technologies Corp (UniWest)
+  "^upisemi,.*":
+    description: uPI Semiconductor Corp.
+  "^urt,.*":
+    description: United Radiant Technology Corporation
+  "^usi,.*":
+    description: Universal Scientific Industrial Co., Ltd.
+  "^v3,.*":
+    description: V3 Semiconductor
+  "^vamrs,.*":
+    description: Vamrs Ltd.
+  "^variscite,.*":
+    description: Variscite Ltd.
+  "^via,.*":
+    description: VIA Technologies, Inc.
+  "^virtio,.*":
+    description: Virtual I/O Device Specification, developed by the OASIS consortium
+  "^vishay,.*":
+    description: Vishay Intertechnology, Inc
+  "^vitesse,.*":
+    description: Vitesse Semiconductor Corporation
+  "^vivante,.*":
+    description: Vivante Corporation
+  "^vocore,.*":
+    description: VoCore Studio
+  "^voipac,.*":
+    description: Voipac Technologies s.r.o.
+  "^vot,.*":
+    description: Vision Optical Technology Co., Ltd.
+  "^wd,.*":
+    description: Western Digital Corp.
+  "^wetek,.*":
+    description: WeTek Electronics, limited.
+  "^wexler,.*":
+    description: Wexler
+  "^whwave,.*":
+    description: Shenzhen whwave Electronics, Inc.
+  "^wi2wi,.*":
+    description: Wi2Wi, Inc.
+  "^winbond,.*":
+    description: Winbond Electronics corp.
+  "^winstar,.*":
+    description: Winstar Display Corp.
+  "^wlf,.*":
+    description: Wolfson Microelectronics
+  "^wm,.*":
+    description: Wondermedia Technologies, Inc.
+  "^x-powers,.*":
+    description: X-Powers
+  "^xes,.*":
+    description: Extreme Engineering Solutions (X-ES)
+  "^xillybus,.*":
+    description: Xillybus Ltd.
+  "^xlnx,.*":
+    description: Xilinx
+  "^xunlong,.*":
+    description: Shenzhen Xunlong Software CO.,Limited
+  "^ysoft,.*":
+    description: Y Soft Corporation a.s.
+  "^zarlink,.*":
+    description: Zarlink Semiconductor
+  "^zeitec,.*":
+    description: ZEITEC Semiconductor Co., LTD.
+  "^zidoo,.*":
+    description: Shenzhen Zidoo Technology Co., Ltd.
+  "^zii,.*":
+    description: Zodiac Inflight Innovations
+  "^zte,.*":
+    description: ZTE Corp.
+  "^zyxel,.*":
+    description: ZyXEL Communications Corp.
+
+  # Normal property name match without a comma
+  # These should catch all node/property names without a prefix
+  "^[a-zA-Z0-9#][a-zA-Z0-9+\\-._@]{0,63}$": true
+  "^[a-zA-Z0-9+\\-._]*@[0-9a-zA-Z,]*$": true
+  "^#.*": true
+
+additionalProperties: false
+
+...
index 45edad6..acc02fc 100644 (file)
@@ -354,8 +354,10 @@ this ioctl is called until no further expire candidates are found.
 
 The call requires an initialized struct autofs_dev_ioctl with the
 ioctlfd field set to the descriptor obtained from the open call. In
-addition an immediate expire, independent of the mount timeout, can be
-requested by setting the how field of struct args_expire to 1. If no
+addition an immediate expire that's independent of the mount timeout,
+and a forced expire that's independent of whether the mount is busy,
+can be requested by setting the how field of struct args_expire to
+AUTOFS_EXP_IMMEDIATE or AUTOFS_EXP_FORCED, respectively . If no
 expire candidates can be found the ioctl returns -1 with errno set to
 EAGAIN.
 
index 373ad25..3af38c7 100644 (file)
@@ -116,7 +116,7 @@ that purpose there is another flag.
 **DCACHE_MANAGE_TRANSIT**
 
 If a dentry has DCACHE_MANAGE_TRANSIT set then two very different but
-related behaviors are invoked, both using the `d_op->d_manage()`
+related behaviours are invoked, both using the `d_op->d_manage()`
 dentry operation.
 
 Firstly, before checking to see if any filesystem is mounted on the
@@ -193,8 +193,8 @@ VFS remain in RCU-walk mode, but can only tell it to get out of
 RCU-walk mode by returning `-ECHILD`.
 
 So `d_manage()`, when called with `rcu_walk` set, should either return
--ECHILD if there is any reason to believe it is unsafe to end the
-mounted filesystem, and otherwise should return 0.
+-ECHILD if there is any reason to believe it is unsafe to enter the
+mounted filesystem, otherwise it should return 0.
 
 autofs will return `-ECHILD` if an expiry of the filesystem has been
 initiated or is being considered, otherwise it returns 0.
@@ -210,7 +210,7 @@ mounts that were created by `d_automount()` returning a filesystem to be
 mounted.  As autofs doesn't return such a filesystem but leaves the
 mounting to the automount daemon, it must involve the automount daemon
 in unmounting as well.  This also means that autofs has more control
-of expiry.
+over expiry.
 
 The VFS also supports "expiry" of mounts using the MNT_EXPIRE flag to
 the `umount` system call.  Unmounting with MNT_EXPIRE will fail unless
@@ -225,7 +225,7 @@ unmount any filesystems mounted on the autofs filesystem or remove any
 symbolic links or empty directories any time it likes.  If the unmount
 or removal is successful the filesystem will be returned to the state
 it was before the mount or creation, so that any access of the name
-will trigger normal auto-mount processing.  In particlar, `rmdir` and
+will trigger normal auto-mount processing.  In particular, `rmdir` and
 `unlink` do not leave negative entries in the dcache as a normal
 filesystem would, so an attempt to access a recently-removed object is
 passed to autofs for handling.
@@ -240,11 +240,18 @@ Normally the daemon only wants to remove entries which haven't been
 used for a while.  For this purpose autofs maintains a "`last_used`"
 time stamp on each directory or symlink.  For symlinks it genuinely
 does record the last time the symlink was "used" or followed to find
-out where it points to.  For directories the field is a slight
-misnomer.  It actually records the last time that autofs checked if
-the directory or one of its descendents was busy and found that it
-was.  This is just as useful and doesn't require updating the field so
-often.
+out where it points to.  For directories the field is used slightly
+differently.  The field is updated at mount time and during expire
+checks if it is found to be in use (ie. open file descriptor or
+process working directory) and during path walks. The update done
+during path walks prevents frequent expire and immediate mount of
+frequently accessed automounts. But in the case where a GUI continually
+access or an application frequently scans an autofs directory tree
+there can be an accumulation of mounts that aren't actually being
+used. To cater for this case the "`strictexpire`" autofs mount option
+can be used to avoid the "`last_used`" update on path walk thereby
+preventing this apparent inability to expire mounts that aren't
+really in use.
 
 The daemon is able to ask autofs if anything is due to be expired,
 using an `ioctl` as discussed later.  For a *direct* mount, autofs
@@ -255,8 +262,12 @@ up.
 
 There is an option with indirect mounts to consider each of the leaves
 that has been mounted on instead of considering the top-level names.
-This is intended for compatability with version 4 of autofs and should
-be considered as deprecated.
+This was originally intended for compatibility with version 4 of autofs
+and should be considered as deprecated for Sun Format automount maps.
+However, it may be used again for amd format mount maps (which are
+generally indirect maps) because the amd automounter allows for the
+setting of an expire timeout for individual mounts. But there are
+some difficulties in making the needed changes for this.
 
 When autofs considers a directory it checks the `last_used` time and
 compares it with the "timeout" value set when the filesystem was
@@ -273,7 +284,7 @@ mounts.  If it finds something in the root directory to expire it will
 return the name of that thing.  Once a name has been returned the
 automount daemon needs to unmount any filesystems mounted below the
 name normally.  As described above, this is unsafe for non-toplevel
-mounts in a version-5 autofs.  For this reason the current `automountd`
+mounts in a version-5 autofs.  For this reason the current `automount(8)`
 does not use this ioctl.
 
 The second mechanism uses either the **AUTOFS_DEV_IOCTL_EXPIRE_CMD** or
@@ -345,7 +356,7 @@ The `wait_queue_token` is a unique number which can identify a
 particular request to be acknowledged.  When a message is sent over
 the pipe the affected dentry is marked as either "active" or
 "expiring" and other accesses to it block until the message is
-acknowledged using one of the ioctls below and the relevant
+acknowledged using one of the ioctls below with the relevant
 `wait_queue_token`.
 
 Communicating with autofs: root directory ioctls
@@ -367,15 +378,14 @@ The available ioctl commands are:
     This mode is also entered if a write to the pipe fails.
 - **AUTOFS_IOC_PROTOVER**:  This returns the protocol version in use.
 - **AUTOFS_IOC_PROTOSUBVER**: Returns the protocol sub-version which
-    is really a version number for the implementation.  It is
-    currently 2.
+    is really a version number for the implementation.
 - **AUTOFS_IOC_SETTIMEOUT**:  This passes a pointer to an unsigned
     long.  The value is used to set the timeout for expiry, and
     the current timeout value is stored back through the pointer.
 - **AUTOFS_IOC_ASKUMOUNT**:  Returns, in the pointed-to `int`, 1 if
     the filesystem could be unmounted.  This is only a hint as
     the situation could change at any instant.  This call can be
-    use to avoid a more expensive full unmount attempt.
+    used to avoid a more expensive full unmount attempt.
 - **AUTOFS_IOC_EXPIRE**: as described above, this asks if there is
     anything suitable to expire.  A pointer to a packet:
 
@@ -400,6 +410,11 @@ The available ioctl commands are:
      **AUTOFS_EXP_IMMEDIATE** causes `last_used` time to be ignored
      and objects are expired if the are not in use.
 
+     **AUTOFS_EXP_FORCED** causes the in use status to be ignored
+     and objects are expired ieven if they are in use. This assumes
+     that the daemon has requested this because it is capable of
+     performing the umount.
+
      **AUTOFS_EXP_LEAVES** will select a leaf rather than a top-level
      name to expire.  This is only safe when *maxproto* is 4.
 
@@ -415,7 +430,7 @@ which can be used to communicate directly with the autofs filesystem.
 It requires CAP_SYS_ADMIN for access.
 
 The `ioctl`s that can be used on this device are described in a separate
-document `autofs-mount-control.txt`, and are summarized briefly here.
+document `autofs-mount-control.txt`, and are summarised briefly here.
 Each ioctl is passed a pointer to an `autofs_dev_ioctl` structure:
 
         struct autofs_dev_ioctl {
@@ -511,6 +526,21 @@ directories.
 Catatonic mode can only be left via the
 **AUTOFS_DEV_IOCTL_OPENMOUNT_CMD** ioctl on the `/dev/autofs`.
 
+The "ignore" mount option
+-------------------------
+
+The "ignore" mount option can be used to provide a generic indicator
+to applications that the mount entry should be ignored when displaying
+mount information.
+
+In other OSes that provide autofs and that provide a mount list to user
+space based on the kernel mount list a no-op mount option ("ignore" is
+the one use on the most common OSes) is allowed so that autofs file
+system users can optionally use it.
+
+This is intended to be used by user space programs to exclude autofs
+mounts from consideration when reading the mounts list.
+
 autofs, name spaces, and shared mounts
 --------------------------------------
 
index 1351984..febccbc 100644 (file)
@@ -45,8 +45,8 @@ the ANOD object which is also the final target node of the reference.
            Name (_DSD, Package () {
                ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
                Package () {
-                   Package () { "node@0", NOD0 },
-                   Package () { "node@1", NOD1 },
+                   Package () { "node@0", "NOD0" },
+                   Package () { "node@1", "NOD1" },
                }
            })
            Name (NOD0, Package() {
@@ -58,7 +58,7 @@ the ANOD object which is also the final target node of the reference.
            Name (NOD1, Package() {
                ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
                Package () {
-                   Package () { "anothernode", ANOD },
+                   Package () { "anothernode", "ANOD" },
                }
            })
            Name (ANOD, Package() {
index e0baed3..1a6ce7a 100644 (file)
@@ -45,7 +45,7 @@ with "port" and must be followed by the "@" character and the number of the
 port as its key. The target object it refers to should be called "PRTX", where
 "X" is the number of the port. An example of such a package would be::
 
-    Package() { "port@4", PRT4 }
+    Package() { "port@4", "PRT4" }
 
 Further on, endpoints are located under the port nodes. The hierarchical
 data extension key of the endpoint nodes must begin with
@@ -54,7 +54,7 @@ endpoint. The object it refers to should be called "EPXY", where "X" is the
 number of the port and "Y" is the number of the endpoint. An example of such a
 package would be::
 
-    Package() { "endpoint@0", EP40 }
+    Package() { "endpoint@0", "EP40" }
 
 Each port node contains a property extension key "port", the value of which is
 the number of the port. Each endpoint is similarly numbered with a property
@@ -82,68 +82,68 @@ A simple example of this is show below::
 
     Scope (\_SB.PCI0.I2C2)
     {
-        Device (CAM0)
-        {
-            Name (_DSD, Package () {
-                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
-                Package () {
-                    Package () { "compatible", Package () { "nokia,smia" } },
-                },
-                ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
-                Package () {
-                    Package () { "port@0", PRT0 },
-                }
-            })
-            Name (PRT0, Package() {
-                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
-                Package () {
-                    Package () { "reg", 0 },
-                },
-                ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
-                Package () {
-                    Package () { "endpoint@0", EP00 },
-                }
-            })
-            Name (EP00, Package() {
-                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
-                Package () {
-                    Package () { "reg", 0 },
-                    Package () { "remote-endpoint", Package() { \_SB.PCI0.ISP, "port@4", "endpoint@0" } },
-                }
-            })
-        }
+       Device (CAM0)
+       {
+           Name (_DSD, Package () {
+               ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+               Package () {
+                   Package () { "compatible", Package () { "nokia,smia" } },
+               },
+               ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
+               Package () {
+                   Package () { "port@0", "PRT0" },
+               }
+           })
+           Name (PRT0, Package() {
+               ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+               Package () {
+                   Package () { "reg", 0 },
+               },
+               ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
+               Package () {
+                   Package () { "endpoint@0", "EP00" },
+               }
+           })
+           Name (EP00, Package() {
+               ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+               Package () {
+                   Package () { "reg", 0 },
+                   Package () { "remote-endpoint", Package() { \_SB.PCI0.ISP, "port@4", "endpoint@0" } },
+               }
+           })
+       }
     }
 
     Scope (\_SB.PCI0)
     {
-        Device (ISP)
-        {
-            Name (_DSD, Package () {
-                ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
-                Package () {
-                    Package () { "port@4", PRT4 },
-                }
-            })
-
-            Name (PRT4, Package() {
-                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
-                Package () {
-                    Package () { "reg", 4 }, /* CSI-2 port number */
-                },
-                ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
-                Package () {
-                    Package () { "endpoint@0", EP40 },
-                }
-            })
-
-            Name (EP40, Package() {
-                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
-                Package () {
-                    Package () { "reg", 0 },
-                    Package () { "remote-endpoint", Package () { \_SB.PCI0.I2C2.CAM0, "port@0", "endpoint@0" } },
-                }
-            })
-        }
+       Device (ISP)
+       {
+           Name (_DSD, Package () {
+               ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
+               Package () {
+                   Package () { "port@4", "PRT4" },
+               }
+           })
+
+           Name (PRT4, Package() {
+               ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+               Package () {
+                   Package () { "reg", 4 }, /* CSI-2 port number */
+               },
+               ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
+               Package () {
+                   Package () { "endpoint@0", "EP40" },
+               }
+           })
+
+           Name (EP40, Package() {
+               ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+               Package () {
+                   Package () { "reg", 0 },
+                   Package () { "remote-endpoint", Package () { \_SB.PCI0.I2C2.CAM0, "port@0", "endpoint@0" } },
+               }
+           })
+       }
     }
 
 Here, the port 0 of the "CAM0" device is connected to the port 4 of
index 9e01aac..a7566ef 100644 (file)
@@ -114,6 +114,7 @@ implementation.
 
    x86/index
    sh/index
+   x86/index
 
 Filesystem Documentation
 ------------------------
index 3fb473e..d640e92 100644 (file)
@@ -75,12 +75,11 @@ enum v4l2_field
 
     * - ``V4L2_FIELD_ANY``
       - 0
-      - Applications request this field order when any one of the
-       ``V4L2_FIELD_NONE``, ``V4L2_FIELD_TOP``, ``V4L2_FIELD_BOTTOM``, or
-       ``V4L2_FIELD_INTERLACED`` formats is acceptable. Drivers choose
-       depending on hardware capabilities or e. g. the requested image
-       size, and return the actual field order. Drivers must never return
-       ``V4L2_FIELD_ANY``. If multiple field orders are possible the
+      - Applications request this field order when any field format
+       is acceptable. Drivers choose depending on hardware capabilities or
+       e.g. the requested image size, and return the actual field order.
+       Drivers must never return ``V4L2_FIELD_ANY``.
+       If multiple field orders are possible the
        driver must choose one of the possible field orders during
        :ref:`VIDIOC_S_FMT <VIDIOC_G_FMT>` or
        :ref:`VIDIOC_TRY_FMT <VIDIOC_G_FMT>`. struct
@@ -88,9 +87,8 @@ enum v4l2_field
        ``V4L2_FIELD_ANY``.
     * - ``V4L2_FIELD_NONE``
       - 1
-      - Images are in progressive format, not interlaced. The driver may
-       also indicate this order when it cannot distinguish between
-       ``V4L2_FIELD_TOP`` and ``V4L2_FIELD_BOTTOM``.
+      - Images are in progressive (frame-based) format, not interlaced
+        (field-based).
     * - ``V4L2_FIELD_TOP``
       - 2
       - Images consist of the top (aka odd) field only.
index cd7303d..180e07d 100644 (file)
@@ -796,7 +796,9 @@ The kernel interface functions are as follows:
                                s64 tx_total_len,
                                gfp_t gfp,
                                rxrpc_notify_rx_t notify_rx,
-                               bool upgrade);
+                               bool upgrade,
+                               bool intr,
+                               unsigned int debug_id);
 
      This allocates the infrastructure to make a new RxRPC call and assigns
      call and connection numbers.  The call will be made on the UDP port that
@@ -824,6 +826,13 @@ The kernel interface functions are as follows:
      the server upgrade the service to a better one.  The resultant service ID
      is returned by rxrpc_kernel_recv_data().
 
+     intr should be set to true if the call should be interruptible.  If this
+     is not set, this function may not return until a channel has been
+     allocated; if it is set, the function may return -ERESTARTSYS.
+
+     debug_id is the call debugging ID to be used for tracing.  This can be
+     obtained by atomically incrementing rxrpc_debug_id.
+
      If this function is successful, an opaque reference to the RxRPC call is
      returned.  The caller now holds a reference on this and it must be
      properly ended.
@@ -1056,6 +1065,16 @@ The kernel interface functions are as follows:
      This value can be used to determine if the remote client has been
      restarted as it shouldn't change otherwise.
 
+ (*) Set the maxmimum lifespan on a call.
+
+       void rxrpc_kernel_set_max_life(struct socket *sock,
+                                      struct rxrpc_call *call,
+                                      unsigned long hard_timeout)
+
+     This sets the maximum lifespan on a call to hard_timeout (which is in
+     jiffies).  In the event of the timeout occurring, the call will be
+     aborted and -ETIME or -ETIMEDOUT will be returned.
+
 
 =======================
 CONFIGURABLE PARAMETERS
index 3f13d85..7493220 100644 (file)
@@ -61,6 +61,7 @@ Currently, these files are in /proc/sys/vm:
 - stat_refresh
 - numa_stat
 - swappiness
+- unprivileged_userfaultfd
 - user_reserve_kbytes
 - vfs_cache_pressure
 - watermark_boost_factor
@@ -818,6 +819,17 @@ The default value is 60.
 
 ==============================================================
 
+unprivileged_userfaultfd
+
+This flag controls whether unprivileged users can use the userfaultfd
+system calls.  Set this to 1 to allow unprivileged users to use the
+userfaultfd system calls, or set this to 0 to restrict userfaultfd to only
+privileged users (with SYS_CAP_PTRACE capability).
+
+The default value is 1.
+
+==============================================================
+
 - user_reserve_kbytes
 
 When overcommit_memory is set to 2, "never overcommit" mode, reserve
index c3b9bd2..f600792 100644 (file)
@@ -765,6 +765,37 @@ Here is the list of current tracers that may be configured.
        tracers from tracing simply echo "nop" into
        current_tracer.
 
+Error conditions
+----------------
+
+  For most ftrace commands, failure modes are obvious and communicated
+  using standard return codes.
+
+  For other more involved commands, extended error information may be
+  available via the tracing/error_log file.  For the commands that
+  support it, reading the tracing/error_log file after an error will
+  display more detailed information about what went wrong, if
+  information is available.  The tracing/error_log file is a circular
+  error log displaying a small number (currently, 8) of ftrace errors
+  for the last (8) failed commands.
+
+  The extended error information and usage takes the form shown in
+  this example::
+
+    # echo xxx > /sys/kernel/debug/tracing/events/sched/sched_wakeup/trigger
+    echo: write error: Invalid argument
+
+    # cat /sys/kernel/debug/tracing/error_log
+    [ 5348.887237] location: error: Couldn't yyy: zzz
+      Command: xxx
+               ^
+    [ 7517.023364] location: error: Bad rrr: sss
+      Command: ppp qqq
+                   ^
+
+  To clear the error log, echo the empty string into it::
+
+    # echo > /sys/kernel/debug/tracing/error_log
 
 Examples of using the tracer
 ----------------------------
index ddbaffa..fb621a1 100644 (file)
@@ -199,20 +199,8 @@ Extended error information
 
   For some error conditions encountered when invoking a hist trigger
   command, extended error information is available via the
-  corresponding event's 'hist' file.  Reading the hist file after an
-  error will display more detailed information about what went wrong,
-  if information is available.  This extended error information will
-  be available until the next hist trigger command for that event.
-
-  If available for a given error condition, the extended error
-  information and usage takes the following form::
-
-    # echo xxx > /sys/kernel/debug/tracing/events/sched/sched_wakeup/trigger
-    echo: write error: Invalid argument
-
-    # cat /sys/kernel/debug/tracing/events/sched/sched_wakeup/hist
-    ERROR: Couldn't yyy: zzz
-      Last command: xxx
+  tracing/error_log file.  See Error Conditions in
+  :file:`Documentation/trace/ftrace.rst` for details.
 
 6.2 'hist' trigger examples
 ---------------------------
index 66bfd83..995da15 100644 (file)
@@ -113,7 +113,7 @@ my $regex_kswapd_wake_default = 'nid=([0-9]*) order=([0-9]*)';
 my $regex_kswapd_sleep_default = 'nid=([0-9]*)';
 my $regex_wakeup_kswapd_default = 'nid=([0-9]*) zid=([0-9]*) order=([0-9]*) gfp_flags=([A-Z_|]*)';
 my $regex_lru_isolate_default = 'isolate_mode=([0-9]*) classzone_idx=([0-9]*) order=([0-9]*) nr_requested=([0-9]*) nr_scanned=([0-9]*) nr_skipped=([0-9]*) nr_taken=([0-9]*) lru=([a-z_]*)';
-my $regex_lru_shrink_inactive_default = 'nid=([0-9]*) nr_scanned=([0-9]*) nr_reclaimed=([0-9]*) nr_dirty=([0-9]*) nr_writeback=([0-9]*) nr_congested=([0-9]*) nr_immediate=([0-9]*) nr_activate=([0-9]*) nr_ref_keep=([0-9]*) nr_unmap_fail=([0-9]*) priority=([0-9]*) flags=([A-Z_|]*)';
+my $regex_lru_shrink_inactive_default = 'nid=([0-9]*) nr_scanned=([0-9]*) nr_reclaimed=([0-9]*) nr_dirty=([0-9]*) nr_writeback=([0-9]*) nr_congested=([0-9]*) nr_immediate=([0-9]*) nr_activate_anon=([0-9]*) nr_activate_file=([0-9]*) nr_ref_keep=([0-9]*) nr_unmap_fail=([0-9]*) priority=([0-9]*) flags=([A-Z_|]*)';
 my $regex_lru_shrink_active_default = 'lru=([A-Z_]*) nr_scanned=([0-9]*) nr_rotated=([0-9]*) priority=([0-9]*)';
 my $regex_writepage_default = 'page=([0-9a-f]*) pfn=([0-9]*) flags=([A-Z_|]*)';
 
@@ -212,7 +212,8 @@ $regex_lru_shrink_inactive = generate_traceevent_regex(
                        "vmscan/mm_vmscan_lru_shrink_inactive",
                        $regex_lru_shrink_inactive_default,
                        "nid", "nr_scanned", "nr_reclaimed", "nr_dirty", "nr_writeback",
-                       "nr_congested", "nr_immediate", "nr_activate", "nr_ref_keep",
+                       "nr_congested", "nr_immediate", "nr_activate_anon",
+                       "nr_activate_file", "nr_ref_keep",
                        "nr_unmap_fail", "priority", "flags");
 $regex_lru_shrink_active = generate_traceevent_regex(
                        "vmscan/mm_vmscan_lru_shrink_active",
@@ -407,7 +408,7 @@ EVENT_PROCESS:
                        }
 
                        my $nr_reclaimed = $3;
-                       my $flags = $12;
+                       my $flags = $13;
                        my $file = 0;
                        if ($flags =~ /RECLAIM_WB_FILE/) {
                                $file = 1;
index 44205f0..ec1efa3 100644 (file)
@@ -189,20 +189,10 @@ the driver callback returns.
 When the device driver wants to populate a range of virtual addresses, it can
 use either::
 
-  int hmm_vma_get_pfns(struct vm_area_struct *vma,
-                      struct hmm_range *range,
-                      unsigned long start,
-                      unsigned long end,
-                      hmm_pfn_t *pfns);
-  int hmm_vma_fault(struct vm_area_struct *vma,
-                    struct hmm_range *range,
-                    unsigned long start,
-                    unsigned long end,
-                    hmm_pfn_t *pfns,
-                    bool write,
-                    bool block);
-
-The first one (hmm_vma_get_pfns()) will only fetch present CPU page table
+  long hmm_range_snapshot(struct hmm_range *range);
+  long hmm_range_fault(struct hmm_range *range, bool block);
+
+The first one (hmm_range_snapshot()) will only fetch present CPU page table
 entries and will not trigger a page fault on missing or non-present entries.
 The second one does trigger a page fault on missing or read-only entry if the
 write parameter is true. Page faults use the generic mm page fault code path
@@ -220,25 +210,56 @@ respect in order to keep things properly synchronized. The usage pattern is::
  {
       struct hmm_range range;
       ...
+
+      range.start = ...;
+      range.end = ...;
+      range.pfns = ...;
+      range.flags = ...;
+      range.values = ...;
+      range.pfn_shift = ...;
+      hmm_range_register(&range);
+
+      /*
+       * Just wait for range to be valid, safe to ignore return value as we
+       * will use the return value of hmm_range_snapshot() below under the
+       * mmap_sem to ascertain the validity of the range.
+       */
+      hmm_range_wait_until_valid(&range, TIMEOUT_IN_MSEC);
+
  again:
-      ret = hmm_vma_get_pfns(vma, &range, start, end, pfns);
-      if (ret)
+      down_read(&mm->mmap_sem);
+      ret = hmm_range_snapshot(&range);
+      if (ret) {
+          up_read(&mm->mmap_sem);
+          if (ret == -EAGAIN) {
+            /*
+             * No need to check hmm_range_wait_until_valid() return value
+             * on retry we will get proper error with hmm_range_snapshot()
+             */
+            hmm_range_wait_until_valid(&range, TIMEOUT_IN_MSEC);
+            goto again;
+          }
+          hmm_mirror_unregister(&range);
           return ret;
+      }
       take_lock(driver->update);
-      if (!hmm_vma_range_done(vma, &range)) {
+      if (!range.valid) {
           release_lock(driver->update);
+          up_read(&mm->mmap_sem);
           goto again;
       }
 
       // Use pfns array content to update device page table
 
+      hmm_mirror_unregister(&range);
       release_lock(driver->update);
+      up_read(&mm->mmap_sem);
       return 0;
  }
 
 The driver->update lock is the same lock that the driver takes inside its
-update() callback. That lock must be held before hmm_vma_range_done() to avoid
-any race with a concurrent CPU page table update.
+update() callback. That lock must be held before checking the range.valid
+field to avoid any race with a concurrent CPU page table update.
 
 HMM implements all this on top of the mmu_notifier API because we wanted a
 simpler API and also to be able to perform optimizations latter on like doing
@@ -255,6 +276,41 @@ report commands as executed is serialized (there is no point in doing this
 concurrently).
 
 
+Leverage default_flags and pfn_flags_mask
+=========================================
+
+The hmm_range struct has 2 fields default_flags and pfn_flags_mask that allows
+to set fault or snapshot policy for a whole range instead of having to set them
+for each entries in the range.
+
+For instance if the device flags for device entries are:
+    VALID (1 << 63)
+    WRITE (1 << 62)
+
+Now let say that device driver wants to fault with at least read a range then
+it does set:
+    range->default_flags = (1 << 63)
+    range->pfn_flags_mask = 0;
+
+and calls hmm_range_fault() as described above. This will fill fault all page
+in the range with at least read permission.
+
+Now let say driver wants to do the same except for one page in the range for
+which its want to have write. Now driver set:
+    range->default_flags = (1 << 63);
+    range->pfn_flags_mask = (1 << 62);
+    range->pfns[index_of_write] = (1 << 62);
+
+With this HMM will fault in all page with at least read (ie valid) and for the
+address == range->start + (index_of_write << PAGE_SHIFT) it will fault with
+write permission ie if the CPU pte does not have write permission set then HMM
+will call handle_mm_fault().
+
+Note that HMM will populate the pfns array with write permission for any entry
+that have write permission within the CPU pte no matter what are the values set
+in default_flags or pfn_flags_mask.
+
+
 Represent and manage device memory from core kernel point of view
 =================================================================
 
diff --git a/Documentation/x86/conf.py b/Documentation/x86/conf.py
new file mode 100644 (file)
index 0000000..33c5c31
--- /dev/null
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = "X86 architecture specific documentation"
+
+tags.add("subproject")
+
+latex_documents = [
+    ('index', 'x86.tex', project,
+     'The kernel development community', 'manual'),
+]
index 73a4879..ae36fc5 100644 (file)
@@ -23,6 +23,7 @@ x86-specific Documentation
    intel_mpx
    amd-memory-encryption
    pti
+   mds
    microcode
    resctrl_ui
    usb-legacy-support
diff --git a/Documentation/x86/mds.rst b/Documentation/x86/mds.rst
new file mode 100644 (file)
index 0000000..5d4330b
--- /dev/null
@@ -0,0 +1,193 @@
+Microarchitectural Data Sampling (MDS) mitigation
+=================================================
+
+.. _mds:
+
+Overview
+--------
+
+Microarchitectural Data Sampling (MDS) is a family of side channel attacks
+on internal buffers in Intel CPUs. The variants are:
+
+ - Microarchitectural Store Buffer Data Sampling (MSBDS) (CVE-2018-12126)
+ - Microarchitectural Fill Buffer Data Sampling (MFBDS) (CVE-2018-12130)
+ - Microarchitectural Load Port Data Sampling (MLPDS) (CVE-2018-12127)
+ - Microarchitectural Data Sampling Uncacheable Memory (MDSUM) (CVE-2019-11091)
+
+MSBDS leaks Store Buffer Entries which can be speculatively forwarded to a
+dependent load (store-to-load forwarding) as an optimization. The forward
+can also happen to a faulting or assisting load operation for a different
+memory address, which can be exploited under certain conditions. Store
+buffers are partitioned between Hyper-Threads so cross thread forwarding is
+not possible. But if a thread enters or exits a sleep state the store
+buffer is repartitioned which can expose data from one thread to the other.
+
+MFBDS leaks Fill Buffer Entries. Fill buffers are used internally to manage
+L1 miss situations and to hold data which is returned or sent in response
+to a memory or I/O operation. Fill buffers can forward data to a load
+operation and also write data to the cache. When the fill buffer is
+deallocated it can retain the stale data of the preceding operations which
+can then be forwarded to a faulting or assisting load operation, which can
+be exploited under certain conditions. Fill buffers are shared between
+Hyper-Threads so cross thread leakage is possible.
+
+MLPDS leaks Load Port Data. Load ports are used to perform load operations
+from memory or I/O. The received data is then forwarded to the register
+file or a subsequent operation. In some implementations the Load Port can
+contain stale data from a previous operation which can be forwarded to
+faulting or assisting loads under certain conditions, which again can be
+exploited eventually. Load ports are shared between Hyper-Threads so cross
+thread leakage is possible.
+
+MDSUM is a special case of MSBDS, MFBDS and MLPDS. An uncacheable load from
+memory that takes a fault or assist can leave data in a microarchitectural
+structure that may later be observed using one of the same methods used by
+MSBDS, MFBDS or MLPDS.
+
+Exposure assumptions
+--------------------
+
+It is assumed that attack code resides in user space or in a guest with one
+exception. The rationale behind this assumption is that the code construct
+needed for exploiting MDS requires:
+
+ - to control the load to trigger a fault or assist
+
+ - to have a disclosure gadget which exposes the speculatively accessed
+   data for consumption through a side channel.
+
+ - to control the pointer through which the disclosure gadget exposes the
+   data
+
+The existence of such a construct in the kernel cannot be excluded with
+100% certainty, but the complexity involved makes it extremly unlikely.
+
+There is one exception, which is untrusted BPF. The functionality of
+untrusted BPF is limited, but it needs to be thoroughly investigated
+whether it can be used to create such a construct.
+
+
+Mitigation strategy
+-------------------
+
+All variants have the same mitigation strategy at least for the single CPU
+thread case (SMT off): Force the CPU to clear the affected buffers.
+
+This is achieved by using the otherwise unused and obsolete VERW
+instruction in combination with a microcode update. The microcode clears
+the affected CPU buffers when the VERW instruction is executed.
+
+For virtualization there are two ways to achieve CPU buffer
+clearing. Either the modified VERW instruction or via the L1D Flush
+command. The latter is issued when L1TF mitigation is enabled so the extra
+VERW can be avoided. If the CPU is not affected by L1TF then VERW needs to
+be issued.
+
+If the VERW instruction with the supplied segment selector argument is
+executed on a CPU without the microcode update there is no side effect
+other than a small number of pointlessly wasted CPU cycles.
+
+This does not protect against cross Hyper-Thread attacks except for MSBDS
+which is only exploitable cross Hyper-thread when one of the Hyper-Threads
+enters a C-state.
+
+The kernel provides a function to invoke the buffer clearing:
+
+    mds_clear_cpu_buffers()
+
+The mitigation is invoked on kernel/userspace, hypervisor/guest and C-state
+(idle) transitions.
+
+As a special quirk to address virtualization scenarios where the host has
+the microcode updated, but the hypervisor does not (yet) expose the
+MD_CLEAR CPUID bit to guests, the kernel issues the VERW instruction in the
+hope that it might actually clear the buffers. The state is reflected
+accordingly.
+
+According to current knowledge additional mitigations inside the kernel
+itself are not required because the necessary gadgets to expose the leaked
+data cannot be controlled in a way which allows exploitation from malicious
+user space or VM guests.
+
+Kernel internal mitigation modes
+--------------------------------
+
+ ======= ============================================================
+ off      Mitigation is disabled. Either the CPU is not affected or
+          mds=off is supplied on the kernel command line
+
+ full     Mitigation is enabled. CPU is affected and MD_CLEAR is
+          advertised in CPUID.
+
+ vmwerv          Mitigation is enabled. CPU is affected and MD_CLEAR is not
+         advertised in CPUID. That is mainly for virtualization
+         scenarios where the host has the updated microcode but the
+         hypervisor does not expose MD_CLEAR in CPUID. It's a best
+         effort approach without guarantee.
+ ======= ============================================================
+
+If the CPU is affected and mds=off is not supplied on the kernel command
+line then the kernel selects the appropriate mitigation mode depending on
+the availability of the MD_CLEAR CPUID bit.
+
+Mitigation points
+-----------------
+
+1. Return to user space
+^^^^^^^^^^^^^^^^^^^^^^^
+
+   When transitioning from kernel to user space the CPU buffers are flushed
+   on affected CPUs when the mitigation is not disabled on the kernel
+   command line. The migitation is enabled through the static key
+   mds_user_clear.
+
+   The mitigation is invoked in prepare_exit_to_usermode() which covers
+   all but one of the kernel to user space transitions.  The exception
+   is when we return from a Non Maskable Interrupt (NMI), which is
+   handled directly in do_nmi().
+
+   (The reason that NMI is special is that prepare_exit_to_usermode() can
+    enable IRQs.  In NMI context, NMIs are blocked, and we don't want to
+    enable IRQs with NMIs blocked.)
+
+
+2. C-State transition
+^^^^^^^^^^^^^^^^^^^^^
+
+   When a CPU goes idle and enters a C-State the CPU buffers need to be
+   cleared on affected CPUs when SMT is active. This addresses the
+   repartitioning of the store buffer when one of the Hyper-Threads enters
+   a C-State.
+
+   When SMT is inactive, i.e. either the CPU does not support it or all
+   sibling threads are offline CPU buffer clearing is not required.
+
+   The idle clearing is enabled on CPUs which are only affected by MSBDS
+   and not by any other MDS variant. The other MDS variants cannot be
+   protected against cross Hyper-Thread attacks because the Fill Buffer and
+   the Load Ports are shared. So on CPUs affected by other variants, the
+   idle clearing would be a window dressing exercise and is therefore not
+   activated.
+
+   The invocation is controlled by the static key mds_idle_clear which is
+   switched depending on the chosen mitigation mode and the SMT state of
+   the system.
+
+   The buffer clear is only invoked before entering the C-State to prevent
+   that stale data from the idling CPU from spilling to the Hyper-Thread
+   sibling after the store buffer got repartitioned and all entries are
+   available to the non idle sibling.
+
+   When coming out of idle the store buffer is partitioned again so each
+   sibling has half of it available. The back from idle CPU could be then
+   speculatively exposed to contents of the sibling. The buffers are
+   flushed either on exit to user space or on VMENTER so malicious code
+   in user space or the guest cannot speculatively access them.
+
+   The mitigation is hooked into all variants of halt()/mwait(), but does
+   not cover the legacy ACPI IO-Port mechanism because the ACPI idle driver
+   has been superseded by the intel_idle driver around 2010 and is
+   preferred on all affected CPUs which are expected to gain the MD_CLEAR
+   functionality in microcode. Aside of that the IO-Port mechanism is a
+   legacy interface which is only used on older systems which are either
+   not affected or do not receive microcode updates anymore.
index 0ab686c..5f39b4f 100644 (file)
@@ -41,8 +41,8 @@ Example of EEMI ops usage:
        int ret;
 
        eemi_ops = zynqmp_pm_get_eemi_ops();
-       if (!eemi_ops)
-               return -ENXIO;
+       if (IS_ERR(eemi_ops))
+               return PTR_ERR(eemi_ops);
 
        ret = eemi_ops->query_data(qdata, ret_payload);
 
index fb9f9d7..005902e 100644 (file)
@@ -710,6 +710,12 @@ L: linux-gpio@vger.kernel.org
 S:     Maintained
 F:     drivers/gpio/gpio-altera.c
 
+ALTERA SYSTEM MANAGER DRIVER
+M:     Thor Thayer <thor.thayer@linux.intel.com>
+S:     Maintained
+F:     drivers/mfd/altera-sysmgr.c
+F:     include/linux/mfd/altera-sysgmr.h
+
 ALTERA SYSTEM RESOURCE DRIVER FOR ARRIA10 DEVKIT
 M:     Thor Thayer <thor.thayer@linux.intel.com>
 S:     Maintained
@@ -736,6 +742,12 @@ F: drivers/tty/serial/altera_jtaguart.c
 F:     include/linux/altera_uart.h
 F:     include/linux/altera_jtaguart.h
 
+AMAZON ANNAPURNA LABS THERMAL MMIO DRIVER
+M:     Talel Shenhar <talel@amazon.com>
+S:     Maintained
+F:     Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt
+F:     drivers/thermal/thermal_mmio.c
+
 AMAZON ETHERNET DRIVERS
 M:     Netanel Belgazal <netanel@amazon.com>
 R:     Saeed Bishara <saeedb@amazon.com>
@@ -1721,11 +1733,21 @@ L:      linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 
 ARM/INTEL IXP4XX ARM ARCHITECTURE
+M:     Linus Walleij <linusw@kernel.org>
 M:     Imre Kaloz <kaloz@openwrt.org>
 M:     Krzysztof Halasa <khalasa@piap.pl>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
+F:     Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
+F:     Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
+F:     Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
+F:     Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
 F:     arch/arm/mach-ixp4xx/
+F:     drivers/clocksource/timer-ixp4xx.c
+F:     drivers/gpio/gpio-ixp4xx.c
+F:     drivers/irqchip/irq-ixp4xx.c
+F:     include/linux/irqchip/irq-ixp4xx.h
+F:     include/linux/platform_data/timer-ixp4xx.h
 
 ARM/INTEL RESEARCH IMOTE/STARGATE 2 MACHINE SUPPORT
 M:     Jonathan Cameron <jic23@cam.ac.uk>
@@ -2021,7 +2043,7 @@ W:        http://www.armlinux.org.uk/
 S:     Maintained
 
 ARM/QUALCOMM SUPPORT
-M:     Andy Gross <andy.gross@linaro.org>
+M:     Andy Gross <agross@kernel.org>
 M:     David Brown <david.brown@linaro.org>
 L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
@@ -2226,6 +2248,7 @@ F:        arch/arm/mach-socfpga/
 F:     arch/arm/boot/dts/socfpga*
 F:     arch/arm/configs/socfpga_defconfig
 F:     arch/arm64/boot/dts/altera/
+F:     arch/arm64/boot/dts/intel/
 W:     http://www.rocketboards.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git
 
@@ -4127,7 +4150,9 @@ F:        Documentation/admin-guide/pm/intel_pstate.rst
 F:     Documentation/cpu-freq/
 F:     Documentation/devicetree/bindings/cpufreq/
 F:     drivers/cpufreq/
+F:     kernel/sched/cpufreq*.c
 F:     include/linux/cpufreq.h
+F:     include/linux/sched/cpufreq.h
 F:     tools/testing/selftests/cpufreq/
 
 CPU FREQUENCY DRIVERS - ARM BIG LITTLE
@@ -4310,7 +4335,7 @@ F:        drivers/infiniband/hw/cxgb3/
 F:     include/uapi/rdma/cxgb3-abi.h
 
 CXGB4 CRYPTO DRIVER (chcr)
-M:     Harsh Jain <harsh@chelsio.com>
+M:     Atul Gupta <atul.gupta@chelsio.com>
 L:     linux-crypto@vger.kernel.org
 W:     http://www.chelsio.com
 S:     Supported
@@ -7976,10 +8001,10 @@ F:      Documentation/media/v4l-drivers/ipu3.rst
 INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT
 M:     Krzysztof Halasa <khalasa@piap.pl>
 S:     Maintained
-F:     arch/arm/mach-ixp4xx/include/mach/qmgr.h
-F:     arch/arm/mach-ixp4xx/include/mach/npe.h
-F:     arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
-F:     arch/arm/mach-ixp4xx/ixp4xx_npe.c
+F:     include/linux/soc/ixp4xx/qmgr.h
+F:     include/linux/soc/ixp4xx/npe.h
+F:     drivers/soc/ixp4xx/ixp4xx-qmgr.c
+F:     drivers/soc/ixp4xx/ixp4xx-npe.c
 F:     drivers/net/ethernet/xscale/ixp4xx_eth.c
 F:     drivers/net/wan/ixp4xx_hss.c
 
@@ -9517,6 +9542,20 @@ S:       Maintained
 F:     Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.txt
 F:     drivers/iio/proximity/mb1232.c
 
+MAXIM MAX77650 PMIC MFD DRIVER
+M:     Bartosz Golaszewski <bgolaszewski@baylibre.com>
+L:     linux-kernel@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/*/*max77650.txt
+F:     Documentation/devicetree/bindings/*/max77650*.txt
+F:     include/linux/mfd/max77650.h
+F:     drivers/mfd/max77650.c
+F:     drivers/regulator/max77650-regulator.c
+F:     drivers/power/supply/max77650-charger.c
+F:     drivers/input/misc/max77650-onkey.c
+F:     drivers/leds/leds-max77650.c
+F:     drivers/gpio/gpio-max77650.c
+
 MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER
 M:     Javier Martinez Canillas <javier@dowhile0.org>
 L:     linux-kernel@vger.kernel.org
@@ -11746,6 +11785,7 @@ F:      include/linux/oprofile.h
 ORACLE CLUSTER FILESYSTEM 2 (OCFS2)
 M:     Mark Fasheh <mark@fasheh.com>
 M:     Joel Becker <jlbec@evilplan.org>
+M:     Joseph Qi <joseph.qi@linux.alibaba.com>
 L:     ocfs2-devel@oss.oracle.com (moderated for non-subscribers)
 W:     http://ocfs2.wiki.kernel.org
 S:     Supported
@@ -12025,7 +12065,8 @@ F:      include/linux/switchtec.h
 F:     drivers/ntb/hw/mscc/
 
 PCI DRIVER FOR MOBIVEIL PCIE IP
-M:     Subrahmanya Lingappa <l.subrahmanya@mobiveil.co.in>
+M:     Karthikeyan Mitran <m.karthikeyan@mobiveil.co.in>
+M:     Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
 L:     linux-pci@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/pci/mobiveil-pcie.txt
@@ -12159,6 +12200,12 @@ T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/
 S:     Supported
 F:     drivers/pci/controller/
 
+PCIE DRIVER FOR ANNAPURNA LABS
+M:     Jonathan Chocron <jonnyc@amazon.com>
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     drivers/pci/controller/dwc/pcie-al.c
+
 PCIE DRIVER FOR AMLOGIC MESON
 M:     Yue Wang <yue.wang@Amlogic.com>
 L:     linux-pci@vger.kernel.org
@@ -15618,7 +15665,7 @@ F:      include/linux/clk/ti.h
 
 TI DAVINCI MACHINE SUPPORT
 M:     Sekhar Nori <nsekhar@ti.com>
-M:     Kevin Hilman <khilman@kernel.org>
+R:     Bartosz Golaszewski <bgolaszewski@baylibre.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git
 S:     Supported
index 5e43fcb..c47b328 100644 (file)
@@ -245,6 +245,13 @@ config ARCH_HAS_FORTIFY_SOURCE
          An architecture should select this when it can successfully
          build and run with CONFIG_FORTIFY_SOURCE.
 
+#
+# Select if the arch provides a historic keepinit alias for the retain_initrd
+# command line option
+#
+config ARCH_HAS_KEEPINITRD
+       bool
+
 # Select if arch has all set_memory_ro/rw/x/nx() functions in asm/cacheflush.h
 config ARCH_HAS_SET_MEMORY
        bool
@@ -774,7 +781,7 @@ config COMPAT_OLD_SIGACTION
        bool
 
 config 64BIT_TIME
-       def_bool ARCH_HAS_64BIT_TIME
+       def_bool y
        help
          This should be selected by all architectures that need to support
          new system calls with a 64-bit time_t. This is relevant on all 32-bit
diff --git a/arch/alpha/include/asm/segment.h b/arch/alpha/include/asm/segment.h
deleted file mode 100644 (file)
index 0453d97..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ALPHA_SEGMENT_H
-#define __ALPHA_SEGMENT_H
-
-/* Only here because we have some old header files that expect it.. */
-
-#endif
index 4dbd4e4..bbbd345 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <asm/hwrpb.h>
 #include <asm/io.h>
-#include <asm/segment.h>
 
 #if 0
 # define DBG_DEVS(args)         printk args
index 733f089..71cd7ac 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <asm/hwrpb.h>
 #include <asm/io.h>
-#include <asm/segment.h>
 
 #define SMC_DEBUG 0
 
index a42fc5c..e2cbec3 100644 (file)
@@ -285,17 +285,3 @@ mem_init(void)
        memblock_free_all();
        mem_init_print_info(NULL);
 }
-
-void
-free_initmem(void)
-{
-       free_initmem_default(-1);
-}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void
-free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
index eabc3ef..5264185 100644 (file)
@@ -742,6 +742,7 @@ extern long arc_strnlen_user_noinline(const char __user *src, long n);
 
 #endif
 
+#include <asm/segment.h>
 #include <asm-generic/uaccess.h>
 
 #endif
index e1ab2d7..02b7a3b 100644 (file)
@@ -206,18 +206,3 @@ void __init mem_init(void)
        memblock_free_all();
        mem_init_print_info(NULL);
 }
-
-/*
- * free_initmem: Free all the __init memory.
- */
-void __ref free_initmem(void)
-{
-       free_initmem_default(-1);
-}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void __init free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
index dc9855c..8869742 100644 (file)
@@ -4,11 +4,11 @@ config ARM
        default y
        select ARCH_32BIT_OFF_T
        select ARCH_CLOCKSOURCE_DATA
-       select ARCH_DISCARD_MEMBLOCK if !HAVE_ARCH_PFN_VALID && !KEXEC
        select ARCH_HAS_DEBUG_VIRTUAL if MMU
        select ARCH_HAS_DEVMEM_IS_ALLOWED
        select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_FORTIFY_SOURCE
+       select ARCH_HAS_KEEPINITRD
        select ARCH_HAS_KCOV
        select ARCH_HAS_MEMBARRIER_SYNC_CORE
        select ARCH_HAS_PTE_SPECIAL if ARM_LPAE
@@ -21,6 +21,7 @@ config ARM
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_HAVE_CUSTOM_GPIO_H
        select ARCH_HAS_GCOV_PROFILE_ALL
+       select ARCH_KEEP_MEMBLOCK if HAVE_ARCH_PFN_VALID || KEXEC
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_NO_SG_CHAIN if !ARM_HAS_SG_CHAIN
        select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
@@ -425,12 +426,15 @@ config ARCH_IXP4XX
        depends on MMU
        select ARCH_HAS_DMA_SET_COHERENT_MASK
        select ARCH_SUPPORTS_BIG_ENDIAN
-       select CLKSRC_MMIO
        select CPU_XSCALE
        select DMABOUNCE if PCI
        select GENERIC_CLOCKEVENTS
+       select GENERIC_IRQ_MULTI_HANDLER
+       select GPIO_IXP4XX
        select GPIOLIB
        select HAVE_PCI
+       select IXP4XX_IRQ
+       select IXP4XX_TIMER
        select NEED_MACH_IO_H
        select USB_EHCI_BIG_ENDIAN_DESC
        select USB_EHCI_BIG_ENDIAN_MMIO
@@ -896,8 +900,6 @@ config PLAT_PXA
 config PLAT_VERSATILE
        bool
 
-source "arch/arm/firmware/Kconfig"
-
 source "arch/arm/mm/Kconfig"
 
 config IWMMXT
index e388af4..9a8862f 100644 (file)
@@ -1676,6 +1676,7 @@ config DEBUG_UART_PHYS
        default 0xe6e68000 if DEBUG_RCAR_GEN2_SCIF1
        default 0xe6ee0000 if DEBUG_RCAR_GEN2_SCIF4
        default 0xe8008000 if DEBUG_R7S72100_SCIF2
+       default 0xf0000000 if DEBUG_DIGICOLOR_UA0
        default 0xf0000be0 if ARCH_EBSA110
        default 0xf1012000 if DEBUG_MVEBU_UART0_ALTERNATE
        default 0xf1012100 if DEBUG_MVEBU_UART1_ALTERNATE
@@ -1727,6 +1728,7 @@ config DEBUG_UART_VIRT
        default 0xe0010fe0 if ARCH_RPC
        default 0xf0000be0 if ARCH_EBSA110
        default 0xf0010000 if DEBUG_ASM9260_UART
+       default 0xf0100000 if DEBUG_DIGICOLOR_UA0
        default 0xf01fb000 if DEBUG_NOMADIK_UART
        default 0xf0201000 if DEBUG_BCM2835 || DEBUG_BCM2836
        default 0xf1000300 if DEBUG_BCM_5301X
index 807a7d0..f863c69 100644 (file)
@@ -116,8 +116,7 @@ endif
 AFLAGS_NOWARN  :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
 
 ifeq ($(CONFIG_THUMB2_KERNEL),y)
-AFLAGS_AUTOIT  :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mauto-it)
-CFLAGS_ISA     :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
+CFLAGS_ISA     :=-mthumb -Wa,-mimplicit-it=always $(AFLAGS_NOWARN)
 AFLAGS_ISA     :=$(CFLAGS_ISA) -Wa$(comma)-mthumb
 # Work around buggy relocation from gas if requested:
 ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y)
@@ -290,7 +289,6 @@ core-y                              += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
 core-y                         += arch/arm/probes/
 core-y                         += arch/arm/net/
 core-y                         += arch/arm/crypto/
-core-y                         += arch/arm/firmware/
 core-y                         += $(machdirs) $(platdirs)
 
 drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
index f4f5aea..dab2914 100644 (file)
@@ -229,6 +229,9 @@ dtb-$(CONFIG_ARCH_HIX5HD2) += \
 dtb-$(CONFIG_ARCH_INTEGRATOR) += \
        integratorap.dtb \
        integratorcp.dtb
+dtb-$(CONFIG_ARCH_IXP4XX) += \
+       intel-ixp42x-linksys-nslu2.dtb \
+       intel-ixp43x-gateworks-gw2358.dtb
 dtb-$(CONFIG_ARCH_KEYSTONE) += \
        keystone-k2hk-evm.dtb \
        keystone-k2l-evm.dtb \
@@ -363,7 +366,8 @@ dtb-$(CONFIG_SOC_IMX35) += \
        imx35-eukrea-mbimxsd35-baseboard.dtb \
        imx35-pdk.dtb
 dtb-$(CONFIG_SOC_IMX50) += \
-       imx50-evk.dtb
+       imx50-evk.dtb \
+       imx50-kobo-aura.dtb
 dtb-$(CONFIG_SOC_IMX51) += \
        imx51-apf51.dtb \
        imx51-apf51dev.dtb \
@@ -380,6 +384,7 @@ dtb-$(CONFIG_SOC_IMX53) += \
        imx53-kp-ddc.dtb \
        imx53-kp-hsc.dtb \
        imx53-m53evk.dtb \
+       imx53-m53menlo.dtb \
        imx53-mba53.dtb \
        imx53-ppd.dtb \
        imx53-qsb.dtb \
@@ -400,6 +405,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
        imx6dl-cubox-i-emmc-som-v15.dtb \
        imx6dl-cubox-i-som-v15.dtb \
        imx6dl-dfi-fs700-m60.dtb \
+       imx6dl-eckelmann-ci4x10.dtb \
        imx6dl-emcon-avari.dtb \
        imx6dl-gw51xx.dtb \
        imx6dl-gw52xx.dtb \
@@ -579,6 +585,7 @@ dtb-$(CONFIG_SOC_IMX7D) += \
        imx7d-cl-som-imx7.dtb \
        imx7d-colibri-emmc-eval-v3.dtb \
        imx7d-colibri-eval-v3.dtb \
+       imx7d-mba7.dtb \
        imx7d-nitrogen7.dtb \
        imx7d-pico-hobbit.dtb \
        imx7d-pico-pi.dtb \
@@ -586,7 +593,9 @@ dtb-$(CONFIG_SOC_IMX7D) += \
        imx7d-sdb.dtb \
        imx7d-sdb-reva.dtb \
        imx7d-sdb-sht11.dtb \
+       imx7d-zii-rpu2.dtb \
        imx7s-colibri-eval-v3.dtb \
+       imx7s-mba7.dtb \
        imx7s-warp.dtb
 dtb-$(CONFIG_SOC_IMX7ULP) += \
        imx7ulp-evk.dtb
@@ -606,6 +615,7 @@ dtb-$(CONFIG_SOC_VF610) += \
        vf610-zii-dev-rev-b.dtb \
        vf610-zii-dev-rev-c.dtb \
        vf610-zii-scu4-aib.dtb \
+       vf610-zii-spb4.dtb \
        vf610-zii-ssmb-dtu.dtb \
        vf610-zii-ssmb-spu3.dtb
 dtb-$(CONFIG_ARCH_MXS) += \
@@ -909,6 +919,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
        rk3288-veyron-jaq.dtb \
        rk3288-veyron-jerry.dtb \
        rk3288-veyron-mickey.dtb \
+       rk3288-veyron-mighty.dtb \
        rk3288-veyron-minnie.dtb \
        rk3288-veyron-pinky.dtb \
        rk3288-veyron-speedy.dtb \
@@ -964,6 +975,8 @@ dtb-$(CONFIG_ARCH_STM32) += \
        stm32746g-eval.dtb \
        stm32h743i-eval.dtb \
        stm32h743i-disco.dtb \
+       stm32mp157a-dk1.dtb \
+       stm32mp157c-dk2.dtb \
        stm32mp157c-ed1.dtb \
        stm32mp157c-ev1.dtb
 dtb-$(CONFIG_MACH_SUN4I) += \
@@ -1091,6 +1104,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
        sun8i-h3-orangepi-plus.dtb \
        sun8i-h3-orangepi-plus2e.dtb \
        sun8i-h3-orangepi-zero-plus2.dtb \
+       sun8i-h3-rervision-dvk.dtb \
        sun8i-r16-bananapi-m2m.dtb \
        sun8i-r16-nintendo-nes-classic.dtb \
        sun8i-r16-nintendo-super-nes-classic.dtb \
index 50dcf12..2f650a7 100644 (file)
 &am33xx_pinmux {
        uart1_pins: pinmux_uart1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0)      /* uart1_rxd */
-                       AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE0)      /* uart1_txd */
-                       AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* uart1_ctsn */
-                       AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)      /* uart1_rtsn */
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE7)      /* lcd_vsync.gpio2[22] DTR */
-                       AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_hsync.gpio2[23] DSR */
-                       AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_pclk.gpio2[24] DCD */
-                       AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_ac_bias_en.gpio2[25] RI */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* lcd_vsync.gpio2[22] DTR */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* lcd_hsync.gpio2[23] DSR */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* lcd_pclk.gpio2[24] DCD */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* lcd_ac_bias_en.gpio2[25] RI */
                >;
        };
 };
index f3f1abd..1ba66d5 100644 (file)
 &am33xx_pinmux {
        tca6416_pins: pinmux_tca6416_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9b4, PIN_INPUT_PULLUP | MUX_MODE7)      /* xdma_event_intr1.gpio0[20] tca6416 stuff */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_INPUT_PULLUP, MUX_MODE7)      /* xdma_event_intr1.gpio0[20] tca6416 stuff */
                >;
        };
 
        uart1_pins: pinmux_uart1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0)      /* uart1_rxd */
-                       AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE0)      /* uart1_txd */
-                       AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* uart1_ctsn */
-                       AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)      /* uart1_rtsn */
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE7)      /* lcd_vsync.gpio2[22] DTR */
-                       AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_hsync.gpio2[23] DSR */
-                       AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_pclk.gpio2[24] DCD */
-                       AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_ac_bias_en.gpio2[25] RI */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* lcd_vsync.gpio2[22] DTR */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* lcd_hsync.gpio2[23] DSR */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* lcd_pclk.gpio2[24] DCD */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* lcd_ac_bias_en.gpio2[25] RI */
                >;
        };
 
        uart2_pins: pinmux_uart2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1)      /* spi0_sclk.uart2_rxd_mux3 */
-                       AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1)      /* spi0_d0.uart2_txd_mux3 */
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE2)      /* i2c0_sda.uart2_ctsn_mux0 */
-                       AM33XX_IOPAD(0x98c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)      /* i2c0_scl.uart2_rtsn_mux0 */
-                       AM33XX_IOPAD(0x830, PIN_OUTPUT_PULLDOWN | MUX_MODE7)      /* gpmc_ad12.gpio1[12] DTR */
-                       AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* gpmc_ad13.gpio1[13] DSR */
-                       AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* gpmc_ad14.gpio1[14] DCD */
-                       AM33XX_IOPAD(0x83c, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_ad15.gpio1[15] RI */
-
-                       AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLUP | MUX_MODE7)      /* mcasp0_aclkr.gpio3[18], INPUT_PULLDOWN | MODE7 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE1)      /* spi0_sclk.uart2_rxd_mux3 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE1)      /* spi0_d0.uart2_txd_mux3 */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLDOWN, MUX_MODE2)      /* i2c0_sda.uart2_ctsn_mux0 */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* i2c0_scl.uart2_rtsn_mux0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* gpmc_ad12.gpio1[12] DTR */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* gpmc_ad13.gpio1[13] DSR */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* gpmc_ad14.gpio1[14] DCD */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* gpmc_ad15.gpio1[15] RI */
+
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_INPUT_PULLUP, MUX_MODE7)      /* mcasp0_aclkr.gpio3[18], INPUT_PULLDOWN | MODE7 */
                >;
        };
 };
index 42f473f..eed65fc 100644 (file)
 &am33xx_pinmux {
        tca6416_pins: pinmux_tca6416_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9b4, PIN_INPUT_PULLUP | MUX_MODE7)      /* xdma_event_intr1.gpio0[20] tca6416 stuff */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_INPUT_PULLUP, MUX_MODE7)      /* xdma_event_intr1.gpio0[20] tca6416 stuff */
                >;
        };
 
 
        dcan1_pins: pinmux_dcan1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x968, PIN_OUTPUT | MUX_MODE2)      /* uart0_ctsn.dcan1_tx_mux0 */
-                       AM33XX_IOPAD(0x96c, PIN_INPUT | MUX_MODE2)      /* uart0_rtsn.dcan1_rx_mux0 */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT, MUX_MODE2)      /* uart0_ctsn.dcan1_tx_mux0 */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT, MUX_MODE2)      /* uart0_rtsn.dcan1_rx_mux0 */
                >;
        };
 
        uart1_pins: pinmux_uart1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0)      /* uart1_rxd */
-                       AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE0)      /* uart1_txd */
-                       AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* uart1_ctsn */
-                       AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)      /* uart1_rtsn */
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE7)      /* lcd_vsync.gpio2[22] DTR */
-                       AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_hsync.gpio2[23] DSR */
-                       AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_pclk.gpio2[24] DCD */
-                       AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_ac_bias_en.gpio2[25] RI */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* lcd_vsync.gpio2[22] DTR */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* lcd_hsync.gpio2[23] DSR */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* lcd_pclk.gpio2[24] DCD */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* lcd_ac_bias_en.gpio2[25] RI */
                >;
        };
 
        uart2_pins: pinmux_uart2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1)      /* spi0_sclk.uart2_rxd_mux3 */
-                       AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1)      /* spi0_d0.uart2_txd_mux3 */
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE2)      /* i2c0_sda.uart2_ctsn_mux0 */
-                       AM33XX_IOPAD(0x98c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)      /* i2c0_scl.uart2_rtsn_mux0 */
-                       AM33XX_IOPAD(0x830, PIN_OUTPUT_PULLDOWN | MUX_MODE7)      /* gpmc_ad12.gpio1[12] DTR */
-                       AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* gpmc_ad13.gpio1[13] DSR */
-                       AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* gpmc_ad14.gpio1[14] DCD */
-                       AM33XX_IOPAD(0x83c, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_ad15.gpio1[15] RI */
-
-                       AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLUP | MUX_MODE7)      /* mcasp0_aclkr.gpio3[18], INPUT_PULLDOWN | MODE7 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE1)      /* spi0_sclk.uart2_rxd_mux3 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE1)      /* spi0_d0.uart2_txd_mux3 */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLDOWN, MUX_MODE2)      /* i2c0_sda.uart2_ctsn_mux0 */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* i2c0_scl.uart2_rtsn_mux0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* gpmc_ad12.gpio1[12] DTR */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* gpmc_ad13.gpio1[13] DSR */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* gpmc_ad14.gpio1[14] DCD */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* gpmc_ad15.gpio1[15] RI */
+
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_INPUT_PULLUP, MUX_MODE7)      /* mcasp0_aclkr.gpio3[18], INPUT_PULLDOWN | MODE7 */
                >;
        };
 
index 3ab1767..fe75050 100644 (file)
@@ -42,9 +42,9 @@
 &am33xx_pinmux {
        user_leds: pinmux_user_leds {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* mii1_col.gpio3_0 PWR LED */
-                       AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* mii1_txd3.gpio0_16 WLAN LED */
-                       AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* mii1_txd2.gpio0_17 APP LED */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_OUTPUT_PULLDOWN, MUX_MODE7)     /* mii1_col.gpio3_0 PWR LED */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE7)    /* mii1_txd3.gpio0_16 WLAN LED */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE7)    /* mii1_txd2.gpio0_17 APP LED */
                >;
        };
 };
index 8c6fc41..b572ad1 100644 (file)
 &am33xx_pinmux {
        mmc2_pins: pinmux_mmc2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x820, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_ad8.mmc1_dat0_mux0 */
-                       AM33XX_IOPAD(0x824, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_ad9.mmc1_dat1_mux0 */
-                       AM33XX_IOPAD(0x828, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_ad10.mmc1_dat2_mux0 */
-                       AM33XX_IOPAD(0x82c, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_ad11.mmc1_dat3_mux0 */
-                       AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_csn1.mmc1_clk_mux0 */
-                       AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_csn2.mmc1_cmd_mux0 */
-                       AM33XX_IOPAD(0x9e4, PIN_INPUT_PULLUP | MUX_MODE7)      /* emu0.gpio3[7] */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_INPUT_PULLUP, MUX_MODE2)      /* gpmc_ad8.mmc1_dat0_mux0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_INPUT_PULLUP, MUX_MODE2)      /* gpmc_ad9.mmc1_dat1_mux0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_INPUT_PULLUP, MUX_MODE2)      /* gpmc_ad10.mmc1_dat2_mux0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_INPUT_PULLUP, MUX_MODE2)      /* gpmc_ad11.mmc1_dat3_mux0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2)      /* gpmc_csn1.mmc1_clk_mux0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2)      /* gpmc_csn2.mmc1_cmd_mux0 */
+                       AM33XX_PADCONF(AM335X_PIN_EMU0, PIN_INPUT_PULLUP, MUX_MODE7)      /* emu0.gpio3[7] */
                >;
        };
 
        wl12xx_gpio: pinmux_wl12xx_gpio {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9e8, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* emu1.gpio3[8] */
+                       AM33XX_PADCONF(AM335X_PIN_EMU1, PIN_OUTPUT_PULLUP, MUX_MODE7)      /* emu1.gpio3[8] */
                >;
        };
 
        tps65910_pins: pinmux_tps65910_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x878, PIN_INPUT_PULLUP | MUX_MODE7)      /* gpmc_ben1.gpio1[28] */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT_PULLUP, MUX_MODE7)      /* gpmc_ben1.gpio1[28] */
                >;
        };
 
        i2c1_pins: pinmux_i2c1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x958, PIN_INPUT | MUX_MODE2)      /* spi0_d1.i2c1_sda_mux3 */
-                       AM33XX_IOPAD(0x95c, PIN_INPUT | MUX_MODE2)      /* spi0_cs0.i2c1_scl_mux3 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT, MUX_MODE2)      /* spi0_d1.i2c1_sda_mux3 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT, MUX_MODE2)      /* spi0_cs0.i2c1_scl_mux3 */
                >;
        };
 
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)            /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        cpsw_default: cpsw_default {
                pinctrl-single,pins = <
                        /* Slave 1 */
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1)       /* mii1_crs.rmii1_crs_dv */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_tx_en.rmii1_txen */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_txd1.rmii1_txd1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_txd0.rmii1_txd0 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE1)      /* mii1_rxd1.rmii1_rxd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE1)      /* mii1_rxd0.rmii1_rxd0 */
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* rmii1_ref_clk.rmii1_refclk */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE1)       /* mii1_crs.rmii1_crs_dv */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE1)      /* mii1_tx_en.rmii1_txen */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE1)      /* mii1_txd1.rmii1_txd1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE1)      /* mii1_txd0.rmii1_txd0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE1)      /* mii1_rxd1.rmii1_rxd1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE1)      /* mii1_rxd0.rmii1_rxd0 */
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE0)      /* rmii1_ref_clk.rmii1_refclk */
 
 
                        /* Slave 2 */
-                       AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a0.rgmii2_tctl */
-                       AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a1.rgmii2_rctl */
-                       AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a2.rgmii2_td3 */
-                       AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a3.rgmii2_td2 */
-                       AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a4.rgmii2_td1 */
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a5.rgmii2_td0 */
-                       AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a6.rgmii2_tclk */
-                       AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a7.rgmii2_rclk */
-                       AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a8.rgmii2_rd3 */
-                       AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a9.rgmii2_rd2 */
-                       AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a10.rgmii2_rd1 */
-                       AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a11.rgmii2_rd0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a0.rgmii2_tctl */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE2)       /* gpmc_a1.rgmii2_rctl */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a2.rgmii2_td3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a3.rgmii2_td2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a4.rgmii2_td1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a5.rgmii2_td0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a6.rgmii2_tclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_INPUT_PULLDOWN, MUX_MODE2)       /* gpmc_a7.rgmii2_rclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_INPUT_PULLDOWN, MUX_MODE2)       /* gpmc_a8.rgmii2_rd3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLDOWN, MUX_MODE2)       /* gpmc_a9.rgmii2_rd2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a10.rgmii2_rd1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a11.rgmii2_rd0 */
                >;
        };
 
        cpsw_sleep: cpsw_sleep {
                pinctrl-single,pins = <
                        /* Slave 1 reset value */
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
 
                        /* Slave 2 reset value*/
-                       AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x848, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x84c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
                        /* MDIO */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)                      /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)    /* mdio_data.mdio_data */
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)                    /* mdio_clk.mdio_clk */
                >;
        };
 
        davinci_mdio_sleep: davinci_mdio_sleep {
                pinctrl-single,pins = <
                        /* MDIO reset value */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        nandflash_pins_s0: nandflash_pins_s0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad0.gpmc_ad0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad1.gpmc_ad1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad2.gpmc_ad2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad3.gpmc_ad3 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad4.gpmc_ad4 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad5.gpmc_ad5 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad6.gpmc_ad6 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad7.gpmc_ad7 */
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_wait0.gpmc_wait0 */
-                       AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7)       /* gpmc_wpn.gpio0_30 */
-                       AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0)             /* gpmc_csn0.gpmc_csn0  */
-                       AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0)             /* gpmc_advn_ale.gpmc_advn_ale */
-                       AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0)             /* gpmc_oen_ren.gpmc_oen_ren */
-                       AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0)             /* gpmc_wen.gpmc_wen */
-                       AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0)             /* gpmc_be0n_cle.gpmc_be0n_cle */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE0)        /* gpmc_ad0.gpmc_ad0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE0)        /* gpmc_ad1.gpmc_ad1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE0)        /* gpmc_ad2.gpmc_ad2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE0)        /* gpmc_ad3.gpmc_ad3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE0)        /* gpmc_ad4.gpmc_ad4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE0)        /* gpmc_ad5.gpmc_ad5 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE0)        /* gpmc_ad6.gpmc_ad6 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE0)        /* gpmc_ad7.gpmc_ad7 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE0)      /* gpmc_wait0.gpmc_wait0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_INPUT_PULLUP, MUX_MODE7)        /* gpmc_wpn.gpio0_30 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT, MUX_MODE0)             /* gpmc_csn0.gpmc_csn0  */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_ADVN_ALE, PIN_OUTPUT, MUX_MODE0)         /* gpmc_advn_ale.gpmc_advn_ale */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_OEN_REN, PIN_OUTPUT, MUX_MODE0)          /* gpmc_oen_ren.gpmc_oen_ren */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WEN, PIN_OUTPUT, MUX_MODE0)              /* gpmc_wen.gpmc_wen */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN0_CLE, PIN_OUTPUT, MUX_MODE0)         /* gpmc_be0n_cle.gpmc_be0n_cle */
                >;
        };
 };
index 29782be..cbd5bd8 100644 (file)
 &am33xx_pinmux {
        nxp_hdmi_pins: pinmux_nxp_hdmi_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE3)     /* xdma_event_intr0.clkout1 */
-                       AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data0 */
-                       AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data1 */
-                       AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data2 */
-                       AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)     /* lcd_data3 */
-                       AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data4 */
-                       AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data5 */
-                       AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data6 */
-                       AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)     /* lcd_data7 */
-                       AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data8 */
-                       AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data9 */
-                       AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data10 */
-                       AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)     /* lcd_data11 */
-                       AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data12 */
-                       AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data13 */
-                       AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data14 */
-                       AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)     /* lcd_data15 */
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0)     /* lcd_vsync */
-                       AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0)     /* lcd_hsync */
-                       AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0)     /* lcd_pclk */
-                       AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0)     /* lcd_ac_bias_en */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT, MUX_MODE3)      /* xdma_event_intr0.clkout1 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0)
                >;
        };
        nxp_hdmi_off_pins: pinmux_nxp_hdmi_off_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE3)     /* xdma_event_intr0.clkout1 */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT, MUX_MODE3)      /* xdma_event_intr0.clkout1 */
                >;
        };
 
        leds_base_pins: pinmux_leds_base_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_a5.gpio1_21 */
-                       AM33XX_IOPAD(0x888, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_csn3.gpio2_0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* gpmc_a5.gpio1_21 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_OUTPUT_PULLDOWN, MUX_MODE7)    /* gpmc_csn3.gpio2_0 */
                >;
        };
 };
index 456eef5..42cfc3b 100644 (file)
 
        user_leds_s0: user_leds_s0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_a5.gpio1_21 */
-                       AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* gpmc_a6.gpio1_22 */
-                       AM33XX_IOPAD(0x85c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_a7.gpio1_23 */
-                       AM33XX_IOPAD(0x860, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* gpmc_a8.gpio1_24 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* gpmc_a5.gpio1_21 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7)        /* gpmc_a6.gpio1_22 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* gpmc_a7.gpio1_23 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT_PULLUP, MUX_MODE7)        /* gpmc_a8.gpio1_24 */
                >;
        };
 
        i2c0_pins: pinmux_i2c0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_scl.i2c0_scl */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)        /* i2c0_sda.i2c0_sda */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)        /* i2c0_scl.i2c0_scl */
                >;
        };
 
        i2c2_pins: pinmux_i2c2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE3)       /* uart1_ctsn.i2c2_sda */
-                       AM33XX_IOPAD(0x97c, PIN_INPUT_PULLUP | MUX_MODE3)       /* uart1_rtsn.i2c2_scl */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3)      /* uart1_ctsn.i2c2_sda */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLUP, MUX_MODE3)      /* uart1_rtsn.i2c2_scl */
                >;
        };
 
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        clkout2_pin: pinmux_clkout2_pin {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* xdma_event_intr1.clkout2 */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3)     /* xdma_event_intr1.clkout2 */
                >;
        };
 
        cpsw_default: cpsw_default {
                pinctrl-single,pins = <
                        /* Slave 1 */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxerr.mii1_rxerr */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* mii1_txen.mii1_txen */
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxdv.mii1_rxdv */
-                       AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* mii1_txd3.mii1_txd3 */
-                       AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* mii1_txd2.mii1_txd2 */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* mii1_txd1.mii1_txd1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* mii1_txd0.mii1_txd0 */
-                       AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_txclk.mii1_txclk */
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxclk.mii1_rxclk */
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxd3.mii1_rxd3 */
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxd2.mii1_rxd2 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxd1.mii1_rxd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxd0.mii1_rxd0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        cpsw_sleep: cpsw_sleep {
                pinctrl-single,pins = <
                        /* Slave 1 reset value */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
                        /* MDIO */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)                      /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        davinci_mdio_sleep: davinci_mdio_sleep {
                pinctrl-single,pins = <
                        /* MDIO reset value */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        mmc1_pins: pinmux_mmc1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7)              /* spio0_cs1.gpio0_6 */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat0.mmc0_dat0 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat1.mmc0_dat1 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat2.mmc0_dat2 */
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat3.mmc0_dat3 */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_cmd.mmc0_cmd */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_clk.mmc0_clk */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7)               /* spio0_cs1.gpio0_6 */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        emmc_pins: pinmux_emmc_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
-                       AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
                >;
        };
 };
index e543c2b..283e288 100644 (file)
 &am33xx_pinmux {
        nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* xdma_event_intr0 */
-                       AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data0.lcd_data0 */
-                       AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data1.lcd_data1 */
-                       AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data2.lcd_data2 */
-                       AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)             /* lcd_data3.lcd_data3 */
-                       AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data4.lcd_data4 */
-                       AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data5.lcd_data5 */
-                       AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data6.lcd_data6 */
-                       AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)             /* lcd_data7.lcd_data7 */
-                       AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data8.lcd_data8 */
-                       AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data9.lcd_data9 */
-                       AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data10.lcd_data10 */
-                       AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)             /* lcd_data11.lcd_data11 */
-                       AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data12.lcd_data12 */
-                       AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data13.lcd_data13 */
-                       AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data14.lcd_data14 */
-                       AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)             /* lcd_data15.lcd_data15 */
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* lcd_vsync.lcd_vsync */
-                       AM33XX_IOPAD(0x8e4, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* lcd_hsync.lcd_hsync */
-                       AM33XX_IOPAD(0x8e8, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* lcd_pclk.lcd_pclk */
-                       AM33XX_IOPAD(0x8ec, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* lcd_ac_bias_en.lcd_ac_bias_en */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* xdma_event_intr0 */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)
                >;
        };
 
        mcasp0_pins: mcasp0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLUP | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
-                       AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
-                       AM33XX_IOPAD(0x994, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
-                       AM33XX_IOPAD(0x990, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
-                       AM33XX_IOPAD(0x86c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.GPIO1_27 */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLUP, MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_OUTPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a11.GPIO1_27 */
                >;
        };
 };
index 83f49f6..5b275c9 100644 (file)
 &am33xx_pinmux {
        bt_pins: pinmux_bt_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* gmii1_txd0.gpio0_28 - BT_EN */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLUP, MUX_MODE7)      /* gmii1_txd0.gpio0_28 - BT_EN */
                >;
        };
 
        mmc3_pins: pinmux_mmc3_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */
-                       AM33XX_IOPAD(0x914, PIN_INPUT_PULLUP | MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLUP | MUX_MODE5 ) /* (J17) gmii1_rxdv.mmc2_dat0 */
-                       AM33XX_IOPAD(0x91c, PIN_INPUT_PULLUP | MUX_MODE5 ) /* (J18) gmii1_txd3.mmc2_dat1 */
-                       AM33XX_IOPAD(0x920, PIN_INPUT_PULLUP | MUX_MODE5 ) /* (K15) gmii1_txd2.mmc2_dat2 */
-                       AM33XX_IOPAD(0x908, PIN_INPUT_PULLUP | MUX_MODE5 ) /* (H16) gmii1_col.mmc2_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J17) gmii1_rxdv.mmc2_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J18) gmii1_txd3.mmc2_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (K15) gmii1_txd2.mmc2_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (H16) gmii1_col.mmc2_dat3 */
                >;
        };
 
        uart3_pins: pinmux_uart3_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE1)       /* gmii1_rxd3.uart3_rxd */
-                       AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* gmii1_rxd2.uart3_txd */
-                       AM33XX_IOPAD(0x948, PIN_INPUT | MUX_MODE3)              /* mdio_data.uart3_ctsn */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* mdio_clk.uart3_rtsn */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1)       /* gmii1_rxd3.uart3_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1)    /* gmii1_rxd2.uart3_txd */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT, MUX_MODE3)           /* mdio_data.uart3_ctsn */
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLDOWN, MUX_MODE3)  /* mdio_clk.uart3_rtsn */
                >;
        };
 
        wl18xx_pins: pinmux_wl18xx_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gmii1_txclk.gpio3_9 WL_EN */
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii1_refclk.gpio0_29 WL_IRQ */
-                       AM33XX_IOPAD(0x930, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* gmii1_rxclk.gpio3_10 LS_BUF_EN */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7)  /* gmii1_txclk.gpio3_9 WL_EN */
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7) /* rmii1_refclk.gpio0_29 WL_IRQ */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7)    /* gmii1_rxclk.gpio3_10 LS_BUF_EN */
                >;
        };
 };
index ccb147e..8d241c8 100644 (file)
 &am33xx_pinmux {
        user_leds_s0: user_leds_s0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE7) /* (V15) gpmc_a5.gpio1[21] - USR_LED_0 */
-                       AM33XX_IOPAD(0x858, PIN_OUTPUT | MUX_MODE7) /* (U15) gpmc_a6.gpio1[22] - USR_LED_1 */
-                       AM33XX_IOPAD(0x85c, PIN_OUTPUT | MUX_MODE7) /* (T15) gpmc_a7.gpio1[23] - USR_LED_2 */
-                       AM33XX_IOPAD(0x860, PIN_OUTPUT | MUX_MODE7) /* (V16) gpmc_a8.gpio1[24] - USR_LED_3 */
-                       AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE7) /* (A15) xdma_event_intr0.gpio0[19] - WIFI_LED */
-                       AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE7) /* (R7) gpmc_advn_ale.gpio2[2] - P8.7, LED_RED, GP1_PIN_5 */
-                       AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE7) /* (T7) gpmc_oen_ren.gpio2[3] - P8.8, LED_GREEN, GP1_PIN_6 */
-                       AM33XX_IOPAD(0x82c, PIN_OUTPUT | MUX_MODE7) /* (U12) gpmc_ad11.gpio0[27] - P8.17, BATT_LED_1 */
-                       AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE7) /* (T5) lcd_data15.gpio0[11] - P8.32, BATT_LED_2 */
-                       AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE7) /* (V6) gpmc_csn0.gpio1[29] - P8.26, BATT_LED_3 */
-                       AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE7) /* (T11) gpmc_ad10.gpio0[26] - P8.14, BATT_LED_4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT, MUX_MODE7) /* (V15) gpmc_a5.gpio1[21] - USR_LED_0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT, MUX_MODE7) /* (U15) gpmc_a6.gpio1[22] - USR_LED_1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT, MUX_MODE7) /* (T15) gpmc_a7.gpio1[23] - USR_LED_2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT, MUX_MODE7) /* (V16) gpmc_a8.gpio1[24] - USR_LED_3 */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT, MUX_MODE7) /* (A15) xdma_event_intr0.gpio0[19] - WIFI_LED */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_ADVN_ALE, PIN_OUTPUT, MUX_MODE7) /* (R7) gpmc_advn_ale.gpio2[2] - P8.7, LED_RED, GP1_PIN_5 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_OEN_REN, PIN_OUTPUT, MUX_MODE7) /* (T7) gpmc_oen_ren.gpio2[3] - P8.8, LED_GREEN, GP1_PIN_6 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_OUTPUT, MUX_MODE7) /* (U12) gpmc_ad11.gpio0[27] - P8.17, BATT_LED_1 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE7) /* (T5) lcd_data15.gpio0[11] - P8.32, BATT_LED_2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT, MUX_MODE7) /* (V6) gpmc_csn0.gpio1[29] - P8.26, BATT_LED_3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT, MUX_MODE7) /* (T11) gpmc_ad10.gpio0[26] - P8.14, BATT_LED_4 */
 
                >;
        };
 
        i2c0_pins: pinmux_i2c0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)       /* (C17) I2C0_SDA.I2C0_SDA */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)       /* (C16) I2C0_SCL.I2C0_SCL */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)        /* (C17) I2C0_SDA.I2C0_SDA */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)        /* (C16) I2C0_SCL.I2C0_SCL */
                >;
        };
 
        i2c2_pins: pinmux_i2c2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE3)       /* (D18) uart1_ctsn.I2C2_SDA */
-                       AM33XX_IOPAD(0x97c, PIN_INPUT_PULLUP | MUX_MODE3)       /* (D17) uart1_rtsn.I2C2_SCL */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3)      /* (D18) uart1_ctsn.I2C2_SDA */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLUP, MUX_MODE3)      /* (D17) uart1_rtsn.I2C2_SCL */
                >;
        };
 
        /* UT0 */
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* (E15) uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* (E16) uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        /* UT1 */
        uart1_pins: pinmux_uart1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)       /* (D16) uart1_rxd.uart1_rxd */
-                       AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* (D15) uart1_txd.uart1_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        /* GPS */
        uart2_pins: pinmux_uart2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE1)       /* (A17) spi0_sclk.uart2_rxd */
-                       AM33XX_IOPAD(0x954, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* (B17) spi0_d0.uart2_txd */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE1)       /* (A17) spi0_sclk.uart2_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT_PULLDOWN, MUX_MODE1)      /* (B17) spi0_d0.uart2_txd */
                >;
        };
 
        /* DSM2 */
        uart4_pins: pinmux_uart4_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE6)       /* (T17) gpmc_wait0.uart4_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE6)      /* (T17) gpmc_wait0.uart4_rxd */
                >;
        };
 
        /* UT5 */
        uart5_pins: pinmux_uart5_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8C4, PIN_INPUT_PULLUP | MUX_MODE4)       /* (U2) lcd_data9.uart5_rxd */
-                       AM33XX_IOPAD(0x8C0, PIN_OUTPUT_PULLDOWN | MUX_MODE4)    /* (U1) lcd_data8.uart5_txd */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_INPUT_PULLUP, MUX_MODE4)       /* (U2) lcd_data9.uart5_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT_PULLDOWN, MUX_MODE4)    /* (U1) lcd_data8.uart5_txd */
                >;
        };
 
        mmc1_pins: pinmux_mmc1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7)              /* (C15) spi0_cs1.gpio0[6] */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7)               /* (C15) spi0_cs1.gpio0[6] */
                >;
        };
 
        mmc2_pins: pinmux_mmc2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2)       /* (U9) gpmc_csn1.mmc1_clk */
-                       AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2)       /* (V9) gpmc_csn2.mmc1_cmd */
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1)       /* (U7) gpmc_ad0.mmc1_dat0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1)       /* (V7) gpmc_ad1.mmc1_dat1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1)       /* (R8) gpmc_ad2.mmc1_dat2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1)       /* (T8) gpmc_ad3.mmc1_dat3 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1)       /* (U8) gpmc_ad4.mmc1_dat4 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1)       /* (V8) gpmc_ad5.mmc1_dat5 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1)       /* (R9) gpmc_ad6.mmc1_dat6 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1)       /* (T9) gpmc_ad7.mmc1_dat7 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2)       /* (U9) gpmc_csn1.mmc1_clk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2)       /* (V9) gpmc_csn2.mmc1_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE1)        /* (U7) gpmc_ad0.mmc1_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE1)        /* (V7) gpmc_ad1.mmc1_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE1)        /* (R8) gpmc_ad2.mmc1_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE1)        /* (T8) gpmc_ad3.mmc1_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE1)        /* (U8) gpmc_ad4.mmc1_dat4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE1)        /* (V8) gpmc_ad5.mmc1_dat5 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE1)        /* (R9) gpmc_ad6.mmc1_dat6 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE1)        /* (T9) gpmc_ad7.mmc1_dat7 */
                >;
        };
 
        mmc3_pins: pinmux_mmc3_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE6)       /* (L15) gmii1_rxd1.mmc2_clk */
-                       AM33XX_IOPAD(0x914, PIN_INPUT_PULLUP | MUX_MODE6)       /* (J16) gmii1_txen.mmc2_cmd */
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLUP | MUX_MODE5)       /* (J17) gmii1_rxdv.mmc2_dat0 */
-                       AM33XX_IOPAD(0x91c, PIN_INPUT_PULLUP | MUX_MODE5)       /* (J18) gmii1_txd3.mmc2_dat1 */
-                       AM33XX_IOPAD(0x920, PIN_INPUT_PULLUP | MUX_MODE5)       /* (K15) gmii1_txd2.mmc2_dat2 */
-                       AM33XX_IOPAD(0x908, PIN_INPUT_PULLUP | MUX_MODE5)       /* (H16) gmii1_col.mmc2_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE6)       /* (L15) gmii1_rxd1.mmc2_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLUP, MUX_MODE6)      /* (J16) gmii1_txen.mmc2_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLUP, MUX_MODE5)      /* (J17) gmii1_rxdv.mmc2_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLUP, MUX_MODE5)       /* (J18) gmii1_txd3.mmc2_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLUP, MUX_MODE5)       /* (K15) gmii1_txd2.mmc2_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLUP, MUX_MODE5)        /* (H16) gmii1_col.mmc2_dat3 */
                >;
        };
 
        bt_pins: pinmux_bt_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* (K17) gmii1_txd0.gpio0[28] - BT_EN */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLUP, MUX_MODE7)      /* (K17) gmii1_txd0.gpio0[28] - BT_EN */
                >;
        };
 
        uart3_pins: pinmux_uart3_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE1)       /* (L17) gmii1_rxd3.uart3_rxd */
-                       AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* (L16) gmii1_rxd2.uart3_txd */
-                       AM33XX_IOPAD(0x948, PIN_INPUT | MUX_MODE3)              /* (M17) mdio_data.uart3_ctsn */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* (M18) mdio_clk.uart3_rtsn */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1)       /* (L17) gmii1_rxd3.uart3_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1)    /* (L16) gmii1_rxd2.uart3_txd */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT, MUX_MODE3)           /* (M17) mdio_data.uart3_ctsn */
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLDOWN, MUX_MODE3)  /* (M18) mdio_clk.uart3_rtsn */
                >;
        };
 
        wl18xx_pins: pinmux_wl18xx_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* (K18) gmii1_txclk.gpio3[9] - WL_EN */
-                       AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* (K16) gmii1_txd1.gpio0[21] - WL_IRQ */
-                       AM33XX_IOPAD(0x930, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* (L18) gmii1_rxclk.gpio3[10] - LS_BUF_EN */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7)  /* (K18) gmii1_txclk.gpio3[9] - WL_EN */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* (K16) gmii1_txd1.gpio0[21] - WL_IRQ */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7)    /* (L18) gmii1_rxclk.gpio3[10] - LS_BUF_EN */
                >;
        };
 
        /* DCAN */
        dcan1_pins: pinmux_dcan1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x96c, PIN_INPUT | MUX_MODE2)              /* (E17) uart0_rtsn.dcan1_rx */
-                       AM33XX_IOPAD(0x968, PIN_OUTPUT | MUX_MODE2)             /* (E18) uart0_ctsn.dcan1_tx */
-                       AM33XX_IOPAD(0x940, PIN_OUTPUT | MUX_MODE7)             /* (M16) gmii1_rxd0.gpio2[21] */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT, MUX_MODE2)             /* (E17) uart0_rtsn.dcan1_rx */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT, MUX_MODE2)            /* (E18) uart0_ctsn.dcan1_tx */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_OUTPUT, MUX_MODE7)             /* (M16) gmii1_rxd0.gpio2[21] */
                >;
        };
 };
index 853e6d3..71317e3 100644 (file)
@@ -27,8 +27,8 @@
 &am33xx_pinmux {
        uart2_pins: uart2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1)      /* spi0_sclk.uart2_rxd */
-                       AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1)     /* spi0_d0.uart2_txd */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE1)      /* spi0_sclk.uart2_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE1)       /* spi0_d0.uart2_txd */
                >;
        };
 };
index 57731f0..7db86a9 100644 (file)
 &am33xx_pinmux {
        bt_pins: pinmux_bt_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x878, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* gpmc_ad12.gpio1_28 BT_EN */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_OUTPUT_PULLUP, MUX_MODE7)      /* gpmc_ad12.gpio1_28 BT_EN */
                >;
        };
 
        mmc3_pins: pinmux_mmc3_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x830, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ad12.mmc2_dat0 */
-                       AM33XX_IOPAD(0x834, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ad13.mmc2_dat1 */
-                       AM33XX_IOPAD(0x838, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ad14.mmc2_dat2 */
-                       AM33XX_IOPAD(0x83c, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ad15.mmc2_dat3 */
-                       AM33XX_IOPAD(0x888, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_csn3.mmc2_cmd */
-                       AM33XX_IOPAD(0x88c, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_clk.mmc2_clk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_ad12.mmc2_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_ad13.mmc2_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_ad14.mmc2_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_ad15.mmc2_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_csn3.mmc2_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CLK, PIN_INPUT_PULLUP, MUX_MODE3)        /* gpmc_clk.mmc2_clk */
                >;
        };
 
        uart3_pins: pinmux_uart3_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE1)       /* gmii1_rxd3.uart3_rxd */
-                       AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* gmii1_rxd2.uart3_txd */
-                       AM33XX_IOPAD(0x948, PIN_INPUT | MUX_MODE3)              /* mdio_data.uart3_ctsn */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* mdio_clk.uart3_rtsn */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1)       /* gmii1_rxd3.uart3_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1)    /* gmii1_rxd2.uart3_txd */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT, MUX_MODE3)           /* mdio_data.uart3_ctsn */
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLDOWN, MUX_MODE3)  /* mdio_clk.uart3_rtsn */
                >;
        };
 
        wl18xx_pins: pinmux_wl18xx_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x828, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_ad10.gpio0_26 WL_EN */
-                       AM33XX_IOPAD(0x82C, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_ad11.gpio0_27 WL_IRQ */
-                       AM33XX_IOPAD(0x87C, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* gpmc_csn0.gpio1_29 LS_BUF_EN */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT_PULLDOWN, MUX_MODE7)    /* gpmc_ad10.gpio0_26 WL_EN */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* gpmc_ad11.gpio0_27 WL_IRQ */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT_PULLUP, MUX_MODE7)      /* gpmc_csn0.gpio1_29 LS_BUF_EN */
                >;
        };
 };
index bffa5dc..31da683 100644 (file)
 &am33xx_pinmux {
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        cpsw_default: cpsw_default {
                pinctrl-single,pins = <
                        /* Slave 1 */
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1)  /* mii1_crs.rmii1_crs */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE1)       /* mii1_rxerr.rmii1_rxerr */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* mii1_txen.rmii1_txen */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* mii1_txd1.rmii1_txd1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* mii1_txd0.rmii1_txd0 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE1)       /* mii1_rxd1.rmii1_rxd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE1)       /* mii1_rxd0.rmii1_rxd0 */
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* rmii1_ref_clk.rmii_ref_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        cpsw_sleep: cpsw_sleep {
                pinctrl-single,pins = <
                        /* Slave 1 reset value */
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
                        /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
                        /* mdio_clk.mdio_clk */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        davinci_mdio_sleep: davinci_mdio_sleep {
                pinctrl-single,pins = <
                        /* MDIO reset value */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        usb1_drvvbus: usb1_drvvbus {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0xa34, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usb1_drvvbus.usb1_drvvbus */
+                       AM33XX_PADCONF(AM335X_PIN_USB1_DRVVBUS, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        sd_pins: pinmux_sd_card {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
-                       AM33XX_IOPAD(0x900, PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */
-                       AM33XX_IOPAD(0x904, PIN_INPUT | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
-                       AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7) /* spi0_cs1.gpio0_6 */
                >;
        };
 
        led_gpio_pins: led_gpio_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9e4, PIN_OUTPUT | MUX_MODE7) /* emu0.gpio3_7 */
-                       AM33XX_IOPAD(0x9e8, PIN_OUTPUT | MUX_MODE7) /* emu1.gpio3_8 */
+                       AM33XX_PADCONF(AM335X_PIN_EMU0, PIN_OUTPUT, MUX_MODE7) /* emu0.gpio3_7 */
+                       AM33XX_PADCONF(AM335X_PIN_EMU1, PIN_OUTPUT, MUX_MODE7) /* emu1.gpio3_8 */
                >;
        };
 };
index 1b43ebd..8b88bf6 100644 (file)
 
        i2c0_pins: pinmux_i2c0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_scl.i2c0_scl */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        nandflash_pins: nandflash_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* gpmc_ad0.gpmc_ad0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* gpmc_ad1.gpmc_ad1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* gpmc_ad2.gpmc_ad2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* gpmc_ad3.gpmc_ad3 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* gpmc_ad4.gpmc_ad4 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* gpmc_ad5.gpmc_ad5 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* gpmc_ad6.gpmc_ad6 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* gpmc_ad7.gpmc_ad7 */
-
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_wait0.gpmc_wait0 */
-                       AM33XX_IOPAD(0x87c, PIN_OUTPUT_PULLUP | MUX_MODE0)      /* gpmc_csn0.gpmc_csn0 */
-                       AM33XX_IOPAD(0x890, PIN_OUTPUT_PULLUP | MUX_MODE0)      /* gpmc_advn_ale.gpmc_advn_ale */
-                       AM33XX_IOPAD(0x894, PIN_OUTPUT_PULLUP | MUX_MODE0)      /* gpmc_oen_ren.gpmc_oen_ren */
-                       AM33XX_IOPAD(0x898, PIN_OUTPUT_PULLUP | MUX_MODE0)      /* gpmc_wen.gpmc_wen */
-                       AM33XX_IOPAD(0x89c, PIN_OUTPUT_PULLUP | MUX_MODE0)      /* gpmc_be0n_cle.gpmc_be0n_cle */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLDOWN, MUX_MODE0)
+
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_ADVN_ALE, PIN_OUTPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_OEN_REN, PIN_OUTPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WEN, PIN_OUTPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN0_CLE, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 };
index 2c724bb..3b0bb88 100644 (file)
 
        i2c0_pins: pinmux_i2c0_pins {
                pinctrl-single,pins = <
-                       /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* i2c0_scl.i2c0_scl */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        i2c1_pins: pinmux_i2c1_pins {
                pinctrl-single,pins = <
                        /* uart0_ctsn.i2c1_sda */
-                       AM33XX_IOPAD(0x968, PIN_INPUT_PULLUP | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT_PULLUP, MUX_MODE2)
                        /* uart0_rtsn.i2c1_scl */
-                       AM33XX_IOPAD(0x96c, PIN_INPUT_PULLUP | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLUP, MUX_MODE2)
                >;
        };
 
        gpio_led_pins: pinmux_gpio_led_pins {
                pinctrl-single,pins = <
                        /* gpmc_csn3.gpio2_0 */
-                       AM33XX_IOPAD(0x888, PIN_OUTPUT | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_OUTPUT, MUX_MODE7)
                >;
        };
 
        nandflash_pins: pinmux_nandflash_pins {
                pinctrl-single,pins = <
-                       /* gpmc_ad0.gpmc_ad0 */
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* gpmc_ad1.gpmc_ad1 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* gpmc_ad2.gpmc_ad2 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* gpmc_ad3.gpmc_ad3 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* gpmc_ad4.gpmc_ad4 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* gpmc_ad5.gpmc_ad5 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* gpmc_ad6.gpmc_ad6 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* gpmc_ad7.gpmc_ad7 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* gpmc_wait0.gpmc_wait0 */
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE0)
                        /* gpmc_wpn.gpio0_30 */
-                       AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7)
-                       /* gpmc_csn0.gpmc_csn0  */
-                       AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0)
-                       /* gpmc_advn_ale.gpmc_advn_ale */
-                       AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0)
-                       /* gpmc_oen_ren.gpmc_oen_ren */
-                       AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0)
-                       /* gpmc_wen.gpmc_wen */
-                       AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0)
-                       /* gpmc_ben0_cle.gpmc_ben0_cle */
-                       AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_INPUT_PULLUP, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_ADVN_ALE, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_OEN_REN, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WEN, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN0_CLE, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* uart0_txd.uart0_txd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        uart1_pins: pinmux_uart1_pins {
                pinctrl-single,pins = <
-                       /* uart1_ctsn.uart1_ctsn */
-                       AM33XX_IOPAD(0x978, PIN_INPUT | MUX_MODE0)
-                       /* uart1_rtsn.uart1_rtsn */
-                       AM33XX_IOPAD(0x97C, PIN_OUTPUT_PULLDOWN | MUX_MODE0)
-                       /* uart1_rxd.uart1_rxd */
-                       AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* uart1_txd.uart1_txd */
-                       AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        dcan0_pins: pinmux_dcan0_pins {
                pinctrl-single,pins = <
                        /* uart1_ctsn.dcan0_tx */
-                       AM33XX_IOPAD(0x978, PIN_OUTPUT | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_OUTPUT, MUX_MODE2)
                        /* uart1_rtsn.dcan0_rx */
-                       AM33XX_IOPAD(0x97C, PIN_INPUT | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT, MUX_MODE2)
                >;
        };
 
        dcan1_pins: pinmux_dcan1_pins {
                pinctrl-single,pins = <
                        /* uart1_rxd.dcan1_tx */
-                       AM33XX_IOPAD(0x980, PIN_OUTPUT | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_OUTPUT, MUX_MODE2)
                        /* uart1_txd.dcan1_rx */
-                       AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT, MUX_MODE2)
                >;
        };
 
        ecap0_pins: pinmux_ecap0_pins {
                pinctrl-single,pins = <
-                       /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */
-                       AM33XX_IOPAD(0x964, 0x0)
+                       AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, 0x0, MUX_MODE0)
                >;
        };
 
                pinctrl-single,pins = <
                        /* Slave 1 */
                        /* mii1_tx_en.rgmii1_tctl */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
                        /* mii1_rxdv.rgmii1_rctl */
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE2)
                        /* mii1_txd3.rgmii1_td3 */
-                       AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
                        /* mii1_txd2.rgmii1_td2 */
-                       AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
                        /* mii1_txd1.rgmii1_td1 */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
                        /* mii1_txd0.rgmii1_td0 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
                        /* mii1_txclk.rgmii1_tclk */
-                       AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
                        /* mii1_rxclk.rgmii1_rclk */
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE2)
                        /* mii1_rxd3.rgmii1_rd3 */
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE2)
                        /* mii1_rxd2.rgmii1_rd2 */
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE2)
                        /* mii1_rxd1.rgmii1_rd1 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE2)
                        /* mii1_rxd0.rgmii1_rd0 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE2)
                >;
        };
 
        cpsw_sleep: cpsw_sleep {
                pinctrl-single,pins = <
                        /* Slave 1 reset value */
-                       AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
-                       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)
-                       /* mdio_clk.mdio_clk */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        davinci_mdio_sleep: davinci_mdio_sleep {
                pinctrl-single,pins = <
                        /* MDIO reset value */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        mmc1_pins: pinmux_mmc1_pins {
                pinctrl-single,pins = <
-                       /* mmc0_dat3.mmc0_dat3 */
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* mmc0_dat2.mmc0_dat2 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* mmc0_dat1.mmc0_dat1 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* mmc0_dat0.mmc0_dat0 */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* mmc0_clk.mmc0_clk */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)
-                       /* mmc0_cmd.mmc0_cmd */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        spi0_pins: pinmux_spi0_pins {
                pinctrl-single,pins = <
-                       /* spi0_sclk.spi0_sclk */
-                       AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE0)
-                       /* spi0_d0.spi0_d0 */
-                       AM33XX_IOPAD(0x954, PIN_OUTPUT_PULLUP | MUX_MODE0)
-                       /* spi0_d1.spi0_d1 */
-                       AM33XX_IOPAD(0x958, PIN_INPUT | MUX_MODE0)
-                       /* spi0_cs0.spi0_cs0 */
-                       AM33XX_IOPAD(0x95C, PIN_OUTPUT | MUX_MODE0)
-                       /* spi0_cs1.spi0_cs1 */
-                       AM33XX_IOPAD(0x960, PIN_OUTPUT | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 
        bluetooth_pins: pinmux_bluetooth_pins {
                pinctrl-single,pins = <
                        /* XDMA_EVENT_INTR0.gpio0_19 - bluetooth enable */
-                       AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLUP | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLUP, MUX_MODE7)
                >;
        };
 
        mcasp1_pins: pinmux_mcasp1_pins {
                pinctrl-single,pins = <
                        /* MII1_CRS.mcasp1_aclkx */
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE4)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE4)
                        /* MII1_RX_ER.mcasp1_fsx */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE4)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE4)
                        /* MII1_COL.mcasp1_axr2 */
-                       AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE4)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLDOWN, MUX_MODE4)
                        /* RMII1_REF_CLK.mcasp1_axr3 */
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE4)
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE4)
                >;
        };
 
        wifi_pins: pinmux_wifi_pins {
                pinctrl-single,pins = <
                        /* EMU1.gpio3_8 - WiFi IRQ */
-                       AM33XX_IOPAD(0x9e8, PIN_INPUT_PULLUP | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_EMU1, PIN_INPUT_PULLUP, MUX_MODE7)
                        /* XDMA_EVENT_INTR1.gpio0_20 - WiFi enable */
-                       AM33XX_IOPAD(0x9b4, PIN_OUTPUT | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT, MUX_MODE7)
                >;
        };
 };
index edcff79..55d4392 100644 (file)
 
        matrix_keypad_s0: matrix_keypad_s0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_a5.gpio1_21 */
-                       AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_a6.gpio1_22 */
-                       AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_a9.gpio1_25 */
-                       AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_a10.gpio1_26 */
-                       AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_a11.gpio1_27 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* gpmc_a5.gpio1_21 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* gpmc_a6.gpio1_22 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLDOWN, MUX_MODE7)       /* gpmc_a9.gpio1_25 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* gpmc_a10.gpio1_26 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* gpmc_a11.gpio1_27 */
                >;
        };
 
        volume_keys_s0: volume_keys_s0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x950, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* spi0_sclk.gpio0_2 */
-                       AM33XX_IOPAD(0x954, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* spi0_d0.gpio0_3 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* spi0_sclk.gpio0_2 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLDOWN, MUX_MODE7)       /* spi0_d0.gpio0_3 */
                >;
        };
 
        i2c0_pins: pinmux_i2c0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_scl.i2c0_scl */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)        /* i2c0_sda.i2c0_sda */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)        /* i2c0_scl.i2c0_scl */
                >;
        };
 
        i2c1_pins: pinmux_i2c1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE2)       /* spi0_d1.i2c1_sda */
-                       AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE2)       /* spi0_cs0.i2c1_scl */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_d1.i2c1_sda */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE2)        /* spi0_cs0.i2c1_scl */
                >;
        };
 
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        uart1_pins: pinmux_uart1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x978, PIN_INPUT | MUX_MODE0)              /* uart1_ctsn.uart1_ctsn */
-                       AM33XX_IOPAD(0x97C, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart1_rtsn.uart1_rtsn */
-                       AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart1_rxd.uart1_rxd */
-                       AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart1_txd.uart1_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        clkout2_pin: pinmux_clkout2_pin {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* xdma_event_intr1.clkout2 */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3)     /* xdma_event_intr1.clkout2 */
                >;
        };
 
        nandflash_pins_s0: nandflash_pins_s0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad0.gpmc_ad0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad1.gpmc_ad1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad2.gpmc_ad2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad3.gpmc_ad3 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad4.gpmc_ad4 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad5.gpmc_ad5 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad6.gpmc_ad6 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad7.gpmc_ad7 */
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_wait0.gpmc_wait0 */
-                       AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7)       /* gpmc_wpn.gpio0_30 */
-                       AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0)             /* gpmc_csn0.gpmc_csn0  */
-                       AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0)             /* gpmc_advn_ale.gpmc_advn_ale */
-                       AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0)             /* gpmc_oen_ren.gpmc_oen_ren */
-                       AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0)             /* gpmc_wen.gpmc_wen */
-                       AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0)             /* gpmc_be0n_cle.gpmc_be0n_cle */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_INPUT_PULLUP, MUX_MODE7)        /* gpmc_wpn.gpio0_30 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_ADVN_ALE, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_OEN_REN, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WEN, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN0_CLE, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 
        ecap0_pins: backlight_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x964, MUX_MODE0)  /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out */
+                       AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, 0x0, MUX_MODE0)
                >;
        };
 
        cpsw_default: cpsw_default {
                pinctrl-single,pins = <
                        /* Slave 1 */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txen.rgmii1_tctl */
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxdv.rgmii1_rctl */
-                       AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd3.rgmii1_td3 */
-                       AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd2.rgmii1_td2 */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd1.rgmii1_td1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd0.rgmii1_td0 */
-                       AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txclk.rgmii1_tclk */
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxclk.rgmii1_rclk */
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxd3.rgmii1_rd3 */
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxd2.rgmii1_rd2 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxd1.rgmii1_rd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxd0.rgmii1_rd0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2)   /* mii1_txen.rgmii1_tctl */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE2)    /* mii1_rxdv.rgmii1_rctl */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd3.rgmii1_td3 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd2.rgmii1_td2 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd1.rgmii1_td1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd0.rgmii1_td0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE2)  /* mii1_txclk.rgmii1_tclk */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE2)   /* mii1_rxclk.rgmii1_rclk */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE2)     /* mii1_rxd3.rgmii1_rd3 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE2)     /* mii1_rxd2.rgmii1_rd2 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE2)     /* mii1_rxd1.rgmii1_rd1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE2)     /* mii1_rxd0.rgmii1_rd0 */
                >;
        };
 
        cpsw_sleep: cpsw_sleep {
                pinctrl-single,pins = <
                        /* Slave 1 reset value */
-                       AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
                        /* MDIO */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)                      /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        davinci_mdio_sleep: davinci_mdio_sleep {
                pinctrl-single,pins = <
                        /* MDIO reset value */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        mmc1_pins: pinmux_mmc1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7)              /* spi0_cs1.gpio0_6 */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat0.mmc0_dat0 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat1.mmc0_dat1 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat2.mmc0_dat2 */
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat3.mmc0_dat3 */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_cmd.mmc0_cmd */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_clk.mmc0_clk */
-                       AM33XX_IOPAD(0x9a0, PIN_INPUT | MUX_MODE4)              /* mcasp0_aclkr.mmc0_sdwp */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7)               /* spi0_cs1.gpio0_6 */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_INPUT, MUX_MODE4)           /* mcasp0_aclkr.mmc0_sdwp */
                >;
        };
 
        mmc3_pins: pinmux_mmc3_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_a1.mmc2_dat0, INPUT_PULLUP | MODE3 */
-                       AM33XX_IOPAD(0x848, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_a2.mmc2_dat1, INPUT_PULLUP | MODE3 */
-                       AM33XX_IOPAD(0x84c, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_a3.mmc2_dat2, INPUT_PULLUP | MODE3 */
-                       AM33XX_IOPAD(0x878, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ben1.mmc2_dat3, INPUT_PULLUP | MODE3 */
-                       AM33XX_IOPAD(0x888, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_csn3.mmc2_cmd, INPUT_PULLUP | MODE3 */
-                       AM33XX_IOPAD(0x88c, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_clk.mmc2_clk, INPUT_PULLUP | MODE3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_a1.mmc2_dat0, INPUT_PULLUP | MODE3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_a2.mmc2_dat1, INPUT_PULLUP | MODE3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_a3.mmc2_dat2, INPUT_PULLUP | MODE3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_ben1.mmc2_dat3, INPUT_PULLUP | MODE3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_csn3.mmc2_cmd, INPUT_PULLUP | MODE3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CLK, PIN_INPUT_PULLUP, MUX_MODE3)        /* gpmc_clk.mmc2_clk, INPUT_PULLUP | MODE3 */
                >;
        };
 
        wlan_pins: pinmux_wlan_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_a0.gpio1_16 */
-                       AM33XX_IOPAD(0x99c, PIN_INPUT | MUX_MODE7)              /* mcasp0_ahclkr.gpio3_17 */
-                       AM33XX_IOPAD(0x9ac, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* mcasp0_ahclkx.gpio3_21 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* gpmc_a0.gpio1_16 */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_INPUT, MUX_MODE7)          /* mcasp0_ahclkr.gpio3_17 */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE7)        /* mcasp0_ahclkx.gpio3_21 */
                >;
        };
 
        lcd_pins_s0: lcd_pins_s0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x820, PIN_OUTPUT | MUX_MODE1)             /* gpmc_ad8.lcd_data23 */
-                       AM33XX_IOPAD(0x824, PIN_OUTPUT | MUX_MODE1)             /* gpmc_ad9.lcd_data22 */
-                       AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE1)             /* gpmc_ad10.lcd_data21 */
-                       AM33XX_IOPAD(0x82c, PIN_OUTPUT | MUX_MODE1)             /* gpmc_ad11.lcd_data20 */
-                       AM33XX_IOPAD(0x830, PIN_OUTPUT | MUX_MODE1)             /* gpmc_ad12.lcd_data19 */
-                       AM33XX_IOPAD(0x834, PIN_OUTPUT | MUX_MODE1)             /* gpmc_ad13.lcd_data18 */
-                       AM33XX_IOPAD(0x838, PIN_OUTPUT | MUX_MODE1)             /* gpmc_ad14.lcd_data17 */
-                       AM33XX_IOPAD(0x83c, PIN_OUTPUT | MUX_MODE1)             /* gpmc_ad15.lcd_data16 */
-                       AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data0.lcd_data0 */
-                       AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data1.lcd_data1 */
-                       AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data2.lcd_data2 */
-                       AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)             /* lcd_data3.lcd_data3 */
-                       AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data4.lcd_data4 */
-                       AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data5.lcd_data5 */
-                       AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data6.lcd_data6 */
-                       AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)             /* lcd_data7.lcd_data7 */
-                       AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data8.lcd_data8 */
-                       AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data9.lcd_data9 */
-                       AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data10.lcd_data10 */
-                       AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)             /* lcd_data11.lcd_data11 */
-                       AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data12.lcd_data12 */
-                       AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data13.lcd_data13 */
-                       AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data14.lcd_data14 */
-                       AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)             /* lcd_data15.lcd_data15 */
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0)             /* lcd_vsync.lcd_vsync */
-                       AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0)             /* lcd_hsync.lcd_hsync */
-                       AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0)             /* lcd_pclk.lcd_pclk */
-                       AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0)             /* lcd_ac_bias_en.lcd_ac_bias_en */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_OUTPUT, MUX_MODE1)              /* gpmc_ad8.lcd_data23 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_OUTPUT, MUX_MODE1)              /* gpmc_ad9.lcd_data22 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT, MUX_MODE1)             /* gpmc_ad10.lcd_data21 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_OUTPUT, MUX_MODE1)             /* gpmc_ad11.lcd_data20 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_OUTPUT, MUX_MODE1)             /* gpmc_ad12.lcd_data19 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_OUTPUT, MUX_MODE1)             /* gpmc_ad13.lcd_data18 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_OUTPUT, MUX_MODE1)             /* gpmc_ad14.lcd_data17 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_OUTPUT, MUX_MODE1)             /* gpmc_ad15.lcd_data16 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 
        mcasp1_pins: mcasp1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */
-                       AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_OUTPUT_PULLDOWN, MUX_MODE4) /* mii1_col.mcasp1_axr2 */
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
                >;
        };
 
        mcasp1_pins_sleep: mcasp1_pins_sleep {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        dcan1_pins_default: dcan1_pins_default {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x968, PIN_OUTPUT | MUX_MODE2) /* uart0_ctsn.d_can1_tx */
-                       AM33XX_IOPAD(0x96c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* uart0_rtsn.d_can1_rx */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT, MUX_MODE2) /* uart0_ctsn.d_can1_tx */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLDOWN, MUX_MODE2) /* uart0_rtsn.d_can1_rx */
                >;
        };
 };
index 2c2d8b5..8fc8056 100644 (file)
 
        lcd_pins_default: lcd_pins_default {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x820, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad8.lcd_data23 */
-                       AM33XX_IOPAD(0x824, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad9.lcd_data22 */
-                       AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad10.lcd_data21 */
-                       AM33XX_IOPAD(0x82c, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad11.lcd_data20 */
-                       AM33XX_IOPAD(0x830, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad12.lcd_data19 */
-                       AM33XX_IOPAD(0x834, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad13.lcd_data18 */
-                       AM33XX_IOPAD(0x838, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad14.lcd_data17 */
-                       AM33XX_IOPAD(0x83c, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad15.lcd_data16 */
-                       AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data0.lcd_data0 */
-                       AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data1.lcd_data1 */
-                       AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data2.lcd_data2 */
-                       AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)     /* lcd_data3.lcd_data3 */
-                       AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data4.lcd_data4 */
-                       AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data5.lcd_data5 */
-                       AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data6.lcd_data6 */
-                       AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)     /* lcd_data7.lcd_data7 */
-                       AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data8.lcd_data8 */
-                       AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data9.lcd_data9 */
-                       AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data10.lcd_data10 */
-                       AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)     /* lcd_data11.lcd_data11 */
-                       AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data12.lcd_data12 */
-                       AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data13.lcd_data13 */
-                       AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data14.lcd_data14 */
-                       AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)     /* lcd_data15.lcd_data15 */
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0)     /* lcd_vsync.lcd_vsync */
-                       AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0)     /* lcd_hsync.lcd_hsync */
-                       AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0)     /* lcd_pclk.lcd_pclk */
-                       AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0)     /* lcd_ac_bias_en.lcd_ac_bias_en */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_OUTPUT, MUX_MODE1)      /* gpmc_ad8.lcd_data23 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_OUTPUT, MUX_MODE1)      /* gpmc_ad9.lcd_data22 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT, MUX_MODE1)     /* gpmc_ad10.lcd_data21 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_OUTPUT, MUX_MODE1)     /* gpmc_ad11.lcd_data20 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_OUTPUT, MUX_MODE1)     /* gpmc_ad12.lcd_data19 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_OUTPUT, MUX_MODE1)     /* gpmc_ad13.lcd_data18 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_OUTPUT, MUX_MODE1)     /* gpmc_ad14.lcd_data17 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_OUTPUT, MUX_MODE1)     /* gpmc_ad15.lcd_data16 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 
        lcd_pins_sleep: lcd_pins_sleep {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x820, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_ad8.lcd_data23 */
-                       AM33XX_IOPAD(0x824, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_ad9.lcd_data22 */
-                       AM33XX_IOPAD(0x828, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_ad10.lcd_data21 */
-                       AM33XX_IOPAD(0x82c, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_ad11.lcd_data20 */
-                       AM33XX_IOPAD(0x830, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_ad12.lcd_data19 */
-                       AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_ad13.lcd_data18 */
-                       AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_ad14.lcd_data17 */
-                       AM33XX_IOPAD(0x83c, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_ad15.lcd_data16 */
-                       AM33XX_IOPAD(0x8a0, PULL_DISABLE | MUX_MODE7)   /* lcd_data0.lcd_data0 */
-                       AM33XX_IOPAD(0x8a4, PULL_DISABLE | MUX_MODE7)   /* lcd_data1.lcd_data1 */
-                       AM33XX_IOPAD(0x8a8, PULL_DISABLE | MUX_MODE7)   /* lcd_data2.lcd_data2 */
-                       AM33XX_IOPAD(0x8ac, PULL_DISABLE | MUX_MODE7)   /* lcd_data3.lcd_data3 */
-                       AM33XX_IOPAD(0x8b0, PULL_DISABLE | MUX_MODE7)   /* lcd_data4.lcd_data4 */
-                       AM33XX_IOPAD(0x8b4, PULL_DISABLE | MUX_MODE7)   /* lcd_data5.lcd_data5 */
-                       AM33XX_IOPAD(0x8b8, PULL_DISABLE | MUX_MODE7)   /* lcd_data6.lcd_data6 */
-                       AM33XX_IOPAD(0x8bc, PULL_DISABLE | MUX_MODE7)   /* lcd_data7.lcd_data7 */
-                       AM33XX_IOPAD(0x8c0, PULL_DISABLE | MUX_MODE7)   /* lcd_data8.lcd_data8 */
-                       AM33XX_IOPAD(0x8c4, PULL_DISABLE | MUX_MODE7)   /* lcd_data9.lcd_data9 */
-                       AM33XX_IOPAD(0x8c8, PULL_DISABLE | MUX_MODE7)   /* lcd_data10.lcd_data10 */
-                       AM33XX_IOPAD(0x8cc, PULL_DISABLE | MUX_MODE7)   /* lcd_data11.lcd_data11 */
-                       AM33XX_IOPAD(0x8d0, PULL_DISABLE | MUX_MODE7)   /* lcd_data12.lcd_data12 */
-                       AM33XX_IOPAD(0x8d4, PULL_DISABLE | MUX_MODE7)   /* lcd_data13.lcd_data13 */
-                       AM33XX_IOPAD(0x8d8, PULL_DISABLE | MUX_MODE7)   /* lcd_data14.lcd_data14 */
-                       AM33XX_IOPAD(0x8dc, PULL_DISABLE | MUX_MODE7)   /* lcd_data15.lcd_data15 */
-                       AM33XX_IOPAD(0x8e0, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* lcd_vsync.lcd_vsync */
-                       AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* lcd_hsync.lcd_hsync */
-                       AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* lcd_pclk.lcd_pclk */
-                       AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* lcd_ac_bias_en.lcd_ac_bias_en */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* gpmc_ad8.lcd_data23 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* gpmc_ad9.lcd_data22 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* gpmc_ad10.lcd_data21 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* gpmc_ad11.lcd_data20 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* gpmc_ad12.lcd_data19 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* gpmc_ad13.lcd_data18 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* gpmc_ad14.lcd_data17 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* gpmc_ad15.lcd_data16 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
 
        user_leds_s0: user_leds_s0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x810, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_ad4.gpio1_4 */
-                       AM33XX_IOPAD(0x814, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_ad5.gpio1_5 */
-                       AM33XX_IOPAD(0x818, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_ad6.gpio1_6 */
-                       AM33XX_IOPAD(0x81c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_ad7.gpio1_7 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_OUTPUT_PULLDOWN, MUX_MODE7)     /* gpmc_ad4.gpio1_4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_OUTPUT_PULLDOWN, MUX_MODE7)     /* gpmc_ad5.gpio1_5 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_OUTPUT_PULLDOWN, MUX_MODE7)     /* gpmc_ad6.gpio1_6 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_OUTPUT_PULLDOWN, MUX_MODE7)     /* gpmc_ad7.gpio1_7 */
                >;
        };
 
        gpio_keys_s0: gpio_keys_s0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x894, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_oen_ren.gpio2_3 */
-                       AM33XX_IOPAD(0x890, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_advn_ale.gpio2_2 */
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_wait0.gpio0_30 */
-                       AM33XX_IOPAD(0x89c, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_ben0_cle.gpio2_5 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_OEN_REN, PIN_INPUT_PULLDOWN, MUX_MODE7)  /* gpmc_oen_ren.gpio2_3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_ADVN_ALE, PIN_INPUT_PULLDOWN, MUX_MODE7) /* gpmc_advn_ale.gpio2_2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLDOWN, MUX_MODE7)    /* gpmc_wait0.gpio0_30 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN0_CLE, PIN_INPUT_PULLDOWN, MUX_MODE7) /* gpmc_ben0_cle.gpio2_5 */
                >;
        };
 
        i2c0_pins: pinmux_i2c0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_scl.i2c0_scl */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        clkout2_pin: pinmux_clkout2_pin {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* xdma_event_intr1.clkout2 */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3)     /* xdma_event_intr1.clkout2 */
                >;
        };
 
        ecap2_pins: backlight_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x99c, MUX_MODE4)  /* mcasp0_ahclkr.ecap2_in_pwm2_out */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, 0x0, MUX_MODE4)        /* mcasp0_ahclkr.ecap2_in_pwm2_out */
                >;
        };
 
        cpsw_default: cpsw_default {
                pinctrl-single,pins = <
                        /* Slave 1 */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txen.rgmii1_tctl */
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxdv.rgmii1_rctl */
-                       AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd3.rgmii1_td3 */
-                       AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd2.rgmii1_td2 */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd1.rgmii1_td1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd0.rgmii1_td0 */
-                       AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txclk.rgmii1_tclk */
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxclk.rgmii1_rclk */
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxd3.rgmii1_rd3 */
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxd2.rgmii1_rd2 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxd1.rgmii1_rd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxd0.rgmii1_rd0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2)   /* mii1_txen.rgmii1_tctl */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE2)    /* mii1_rxdv.rgmii1_rctl */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd3.rgmii1_td3 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd2.rgmii1_td2 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd1.rgmii1_td1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd0.rgmii1_td0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE2)  /* mii1_txclk.rgmii1_tclk */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE2)   /* mii1_rxclk.rgmii1_rclk */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE2)     /* mii1_rxd3.rgmii1_rd3 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE2)     /* mii1_rxd2.rgmii1_rd2 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE2)     /* mii1_rxd1.rgmii1_rd1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE2)     /* mii1_rxd0.rgmii1_rd0 */
 
                        /* Slave 2 */
-                       AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a0.rgmii2_tctl */
-                       AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a1.rgmii2_rctl */
-                       AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a2.rgmii2_td3 */
-                       AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a3.rgmii2_td2 */
-                       AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a4.rgmii2_td1 */
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a5.rgmii2_td0 */
-                       AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a6.rgmii2_tclk */
-                       AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a7.rgmii2_rclk */
-                       AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a8.rgmii2_rd3 */
-                       AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a9.rgmii2_rd2 */
-                       AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a10.rgmii2_rd1 */
-                       AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a11.rgmii2_rd0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a0.rgmii2_tctl */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE2)       /* gpmc_a1.rgmii2_rctl */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a2.rgmii2_td3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a3.rgmii2_td2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a4.rgmii2_td1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a5.rgmii2_td0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a6.rgmii2_tclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_INPUT_PULLDOWN, MUX_MODE2)       /* gpmc_a7.rgmii2_rclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_INPUT_PULLDOWN, MUX_MODE2)       /* gpmc_a8.rgmii2_rd3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLDOWN, MUX_MODE2)       /* gpmc_a9.rgmii2_rd2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a10.rgmii2_rd1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a11.rgmii2_rd0 */
                >;
        };
 
        cpsw_sleep: cpsw_sleep {
                pinctrl-single,pins = <
                        /* Slave 1 reset value */
-                       AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
 
                        /* Slave 2 reset value*/
-                       AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x848, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x84c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
                        /* MDIO */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)                      /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        davinci_mdio_sleep: davinci_mdio_sleep {
                pinctrl-single,pins = <
                        /* MDIO reset value */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        mmc1_pins: pinmux_mmc1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7)              /* spi0_cs1.gpio0_6 */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat0.mmc0_dat0 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat1.mmc0_dat1 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat2.mmc0_dat2 */
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat3.mmc0_dat3 */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_cmd.mmc0_cmd */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_clk.mmc0_clk */
-                       AM33XX_IOPAD(0x9a0, PIN_INPUT | MUX_MODE4)              /* mcasp0_aclkr.mmc0_sdwp */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7)               /* spi0_cs1.gpio0_6 */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_INPUT, MUX_MODE4)           /* mcasp0_aclkr.mmc0_sdwp */
                >;
        };
 
        mcasp1_pins: mcasp1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */
-                       AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_OUTPUT_PULLDOWN, MUX_MODE4) /* mii1_col.mcasp1_axr2 */
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
                >;
        };
 
        mcasp1_pins_sleep: mcasp1_pins_sleep {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        mmc2_pins: pinmux_mmc2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_31 */
-                       AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
-                       AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_INPUT_PULLUP, MUX_MODE7) /* gpmc_wpn.gpio0_31 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
                >;
        };
 
        wl12xx_gpio: pinmux_wl12xx_gpio {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x87c, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_csn0.gpio1_29 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_csn0.gpio1_29 */
                >;
        };
 };
index 9ac775c..4365684 100644 (file)
 &am33xx_pinmux {
        user_leds: user_leds {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x91c, PIN_OUTPUT | MUX_MODE7) /* (J18) gmii1_txd3.gpio0[16] */
-                       AM33XX_IOPAD(0x920, PIN_OUTPUT | MUX_MODE7) /* (K15) gmii1_txd2.gpio0[17] */
-                       AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE7) /* (A15) xdma_event_intr0.gpio0[19] */
-                       AM33XX_IOPAD(0x9b4, PIN_OUTPUT | MUX_MODE7) /* (D14) xdma_event_intr1.gpio0[20] */
-                       AM33XX_IOPAD(0x880, PIN_OUTPUT | MUX_MODE7) /* (U9) gpmc_csn1.gpio1[30] */
-                       AM33XX_IOPAD(0x92c, PIN_OUTPUT | MUX_MODE7) /* (K18) gmii1_txclk.gpio3[9] */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT, MUX_MODE7) /* (J18) gmii1_txd3.gpio0[16] */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT, MUX_MODE7) /* (K15) gmii1_txd2.gpio0[17] */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT, MUX_MODE7) /* (A15) xdma_event_intr0.gpio0[19] */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT, MUX_MODE7) /* (D14) xdma_event_intr1.gpio0[20] */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_OUTPUT, MUX_MODE7) /* (U9) gpmc_csn1.gpio1[30] */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT, MUX_MODE7) /* (K18) gmii1_txclk.gpio3[9] */
                >;
        };
 
        mmc0_pins_default: mmc0_pins_default {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* (F17) mmc0_dat3.mmc0_dat3 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* (F18) mmc0_dat2.mmc0_dat2 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* (G15) mmc0_dat1.mmc0_dat1 */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* (G16) mmc0_dat0.mmc0_dat0 */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* (G17) mmc0_clk.mmc0_clk */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* (G18) mmc0_cmd.mmc0_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        i2c0_pins_default: i2c0_pins_default {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT | MUX_MODE0) /* (C17) I2C0_SDA.I2C0_SDA */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT | MUX_MODE0) /* (C16) I2C0_SCL.I2C0_SCL */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT, MUX_MODE0)
                >;
        };
 
        spi0_pins_default: spi0_pins_default {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) /* (A17) spi0_sclk.spi0_sclk */
-                       AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* (B17) spi0_d0.spi0_d0 */
-                       AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* (B16) spi0_d1.spi0_d1 */
-                       AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0) /* (A16) spi0_cs0.spi0_cs0 */
-                       AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE0) /* (C15) spi0_cs1.spi0_cs1 */
-                       AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLUP | MUX_MODE7) /* (B12) mcasp0_aclkr.gpio3[18] */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_INPUT_PULLUP, MUX_MODE7) /* (B12) mcasp0_aclkr.gpio3[18] */
                >;
        };
 
        uart3_pins_default: uart3_pins_default {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE1) /* (L17) gmii1_rxd3.uart3_rxd */
-                       AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLUP | MUX_MODE1) /* (L16) gmii1_rxd2.uart3_txd */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1) /* (L17) gmii1_rxd3.uart3_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLUP, MUX_MODE1) /* (L16) gmii1_rxd2.uart3_txd */
                >;
        };
 
        cpsw_default: cpsw_default {
                pinctrl-single,pins = <
                        /* Slave 1, RMII mode */
-                       AM33XX_IOPAD(0x90c, (PIN_INPUT_PULLUP | MUX_MODE1))     /* mii1_crs.rmii1_crs_dv */
-                       AM33XX_IOPAD(0x944, (PIN_INPUT_PULLUP | MUX_MODE0))     /* rmii1_refclk.rmii1_refclk */
-                       AM33XX_IOPAD(0x940, (PIN_INPUT_PULLUP | MUX_MODE1))     /* mii1_rxd0.rmii1_rxd0 */
-                       AM33XX_IOPAD(0x93c, (PIN_INPUT_PULLUP | MUX_MODE1))     /* mii1_rxd1.rmii1_rxd1 */
-                       AM33XX_IOPAD(0x910, (PIN_INPUT_PULLUP | MUX_MODE1))     /* mii1_rxerr.rmii1_rxerr */
-                       AM33XX_IOPAD(0x928, (PIN_OUTPUT_PULLDOWN | MUX_MODE1))  /* mii1_txd0.rmii1_txd0 */
-                       AM33XX_IOPAD(0x924, (PIN_OUTPUT_PULLDOWN | MUX_MODE1))  /* mii1_txd1.rmii1_txd1 */
-                       AM33XX_IOPAD(0x914, (PIN_OUTPUT_PULLDOWN | MUX_MODE1))  /* mii1_txen.rmii1_txen */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLUP, MUX_MODE1)        /* mii1_crs.rmii1_crs_dv */
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLUP, MUX_MODE1)      /* mii1_rxerr.rmii1_rxerr */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE1)    /* mii1_txd0.rmii1_txd0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE1)    /* mii1_txd1.rmii1_txd1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE1)   /* mii1_txen.rmii1_txen */
                        /* Slave 2, RMII mode */
-                       AM33XX_IOPAD(0x870, (PIN_INPUT_PULLUP | MUX_MODE3))     /* gpmc_wait0.rmii2_crs_dv */
-                       AM33XX_IOPAD(0x908, (PIN_INPUT_PULLUP | MUX_MODE1))     /* mii1_col.rmii2_refclk */
-                       AM33XX_IOPAD(0x86c, (PIN_INPUT_PULLUP | MUX_MODE3))     /* gpmc_a11.rmii2_rxd0 */
-                       AM33XX_IOPAD(0x868, (PIN_INPUT_PULLUP | MUX_MODE3))     /* gpmc_a10.rmii2_rxd1 */
-                       AM33XX_IOPAD(0x874, (PIN_INPUT_PULLUP | MUX_MODE3))     /* gpmc_wpn.rmii2_rxerr */
-                       AM33XX_IOPAD(0x854, (PIN_OUTPUT_PULLDOWN | MUX_MODE3))  /* gpmc_a5.rmii2_txd0 */
-                       AM33XX_IOPAD(0x850, (PIN_OUTPUT_PULLDOWN | MUX_MODE3))  /* gpmc_a4.rmii2_txd1 */
-                       AM33XX_IOPAD(0x840, (PIN_OUTPUT_PULLDOWN | MUX_MODE3))  /* gpmc_a0.rmii2_txen */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE3)      /* gpmc_wait0.rmii2_crs_dv */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLUP, MUX_MODE1)        /* mii1_col.rmii2_refclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLUP, MUX_MODE3)        /* gpmc_a11.rmii2_rxd0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLUP, MUX_MODE3)        /* gpmc_a10.rmii2_rxd1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_INPUT_PULLUP, MUX_MODE3)        /* gpmc_wpn.rmii2_rxerr */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE3)      /* gpmc_a5.rmii2_txd0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT_PULLDOWN, MUX_MODE3)      /* gpmc_a4.rmii2_txd1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)      /* gpmc_a0.rmii2_txen */
                >;
        };
 
        cpsw_sleep: cpsw_sleep {
                pinctrl-single,pins = <
                        /* Slave 1 reset value */
-                       AM33XX_IOPAD(0x90c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x944, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x940, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x93c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x910, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x928, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x924, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x914, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
 
                        /* Slave 2 reset value */
-                       AM33XX_IOPAD(0x870, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x908, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x86c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x868, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x874, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x854, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x850, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x840, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
                        /* MDIO */
-                       AM33XX_IOPAD(0x948, (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0))     /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, (PIN_OUTPUT_PULLUP | MUX_MODE0))                    /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        davinci_mdio_sleep: davinci_mdio_sleep {
                pinctrl-single,pins = <
                        /* MDIO reset value */
-                       AM33XX_IOPAD(0x948, (PIN_INPUT_PULLDOWN | MUX_MODE7))
-                       AM33XX_IOPAD(0x94c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 };
index cbd22f2..312deb6 100644 (file)
 &am33xx_pinmux {
        i2c0_pins: pinmux_i2c0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_scl.i2c0_scl */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        nandflash_pins: pinmux_nandflash_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad0.gpmc_ad0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad1.gpmc_ad1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad2.gpmc_ad2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad3.gpmc_ad3 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad4.gpmc_ad4 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad5.gpmc_ad5 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad6.gpmc_ad6 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad7.gpmc_ad7 */
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_wait0.gpmc_wait0 */
-                       AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7)       /* gpmc_wpn.gpio0_30 */
-                       AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0)             /* gpmc_csn0.gpmc_csn0 */
-                       AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0)             /* gpmc_advn_ale.gpmc_advn_ale */
-                       AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0)             /* gpmc_oen_ren.gpmc_oen_ren */
-                       AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0)             /* gpmc_wen.gpmc_wen */
-                       AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0)             /* gpmc_be0n_cle.gpmc_be0n_cle */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_INPUT_PULLUP, MUX_MODE7)        /* gpmc_wpn.gpio0_30 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_ADVN_ALE, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_OEN_REN, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WEN, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN0_CLE, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        leds_pins: pinmux_leds_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x85c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_a7.gpio1_23 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* gpmc_a7.gpio1_23 */
                >;
        };
 };
index d0e8e72..aa4cd2b 100644 (file)
 &am33xx_pinmux {
        mmc1_pins: pinmux_mmc1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat3 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat2 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat1 */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat0 */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_clk */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        i2c0_pins: pinmux_i2c0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT | MUX_MODE0)      /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT | MUX_MODE0)      /* i2c0_scl.i2c0_scl */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT, MUX_MODE0)
                >;
        };
 
        cpsw_default: cpsw_default {
                pinctrl-single,pins = <
                        /* Slave 1 */
-                       AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii1_int */
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* rmii1_crs_dv */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* rmii1_rxer */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* rmii1_txen */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* rmii1_td1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* rmii1_td0 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* rmii1_rd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* rmii1_rd0 */
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* rmii1_refclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLDOWN, MUX_MODE7)       /* rmii1_int */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE1)      /* rmii1_crs_dv */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE1)    /* rmii1_rxer */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE1)   /* rmii1_txen */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE1)    /* rmii1_td1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE1)    /* rmii1_td0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE1)     /* rmii1_rd1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE1)     /* rmii1_rd0 */
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE0)
 
                        /* Slave 2 */
-                       AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* rmii2_txen */
-                       AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* rmii2_td1 */
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* rmii2_td0 */
-                       AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE3)     /* rmii2_rd1 */
-                       AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE3)     /* rmii2_rd0 */
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLDOWN | MUX_MODE3)     /* rmii2_crs_dv */
-                       AM33XX_IOPAD(0x874, PIN_INPUT_PULLDOWN | MUX_MODE3)     /* rmii2_rxer */
-                       AM33XX_IOPAD(0x878, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii2_int */
-                       AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* rmii2_refclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)      /* rmii2_txen */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT_PULLDOWN, MUX_MODE3)      /* rmii2_td1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE3)      /* rmii2_td0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE3)      /* rmii2_rd1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE3)      /* rmii2_rd0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLDOWN, MUX_MODE3)    /* rmii2_crs_dv */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_INPUT_PULLDOWN, MUX_MODE3)      /* rmii2_rxer */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* rmii2_int */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLDOWN, MUX_MODE1)      /* rmii2_refclk */
                >;
        };
 
        cpsw_sleep: cpsw_sleep {
                pinctrl-single,pins = <
                        /* Slave 1 reset value */
-                       AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii1_int */
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii1_crs_dv */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii1_rxer */
-                       AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii1_txen */
-                       AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii1_td1 */
-                       AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii1_td0 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii1_rd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii1_rd0 */
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii1_refclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLDOWN, MUX_MODE7)       /* rmii1_int */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* rmii1_crs_dv */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7)    /* rmii1_rxer */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)    /* rmii1_txen */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* rmii1_td1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* rmii1_td0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* rmii1_rd1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* rmii1_rd0 */
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7) /* rmii1_refclk */
 
                        /* Slave 2 reset value*/
-                       AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii2_txen */
-                       AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii2_td1 */
-                       AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii2_td0 */
-                       AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii2_rd1 */
-                       AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii2_rd0 */
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii2_crs_dv */
-                       AM33XX_IOPAD(0x874, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii2_rxer */
-                       AM33XX_IOPAD(0x878, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii2_int */
-                       AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* rmii2_refclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_INPUT_PULLDOWN, MUX_MODE7)       /* rmii2_txen */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_INPUT_PULLDOWN, MUX_MODE7)       /* rmii2_td1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_INPUT_PULLDOWN, MUX_MODE7)       /* rmii2_td0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* rmii2_rd1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* rmii2_rd0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLDOWN, MUX_MODE7)    /* rmii2_crs_dv */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* rmii2_rxer */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* rmii2_int */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* rmii2_refclk */
                >;
        };
 
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
                        /* MDIO */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)                      /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        davinci_mdio_sleep: davinci_mdio_sleep {
                pinctrl-single,pins = <
                        /* MDIO reset value */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        emmc_pins: pinmux_emmc_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
-                       AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
                >;
        };
 
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 };
index cb5913a..671d4a5 100644 (file)
 
        i2c0_pins: pinmux_i2c0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_scl.i2c0_scl */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        push_button_pins: pinmux_push_button {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* lcd_hsync.gpio2_23 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* lcd_hsync.gpio2_23 */
                >;
        };
 
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
                        /* MDIO */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)                      /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        mmc1_pins_default: pinmux_mmc1_pins {
                pinctrl-single,pins = <
                        /* eMMC */
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad12.mmc1_dat0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad13.mmc1_dat1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad14.mmc1_dat2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad15.mmc1_dat3 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad8.mmc1_dat4 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad9.mmc1_dat5 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad10.mmc1_dat6 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad11.mmc1_dat7 */
-                       AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2)       /* gpmc_csn2.mmc1_cmd */
-                       AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2)       /* gpmc_csn1.mmc1_clk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad12.mmc1_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad13.mmc1_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad14.mmc1_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad15.mmc1_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad8.mmc1_dat4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad9.mmc1_dat5 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad10.mmc1_dat6 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad11.mmc1_dat7 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2)       /* gpmc_csn2.mmc1_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2)       /* gpmc_csn1.mmc1_clk */
                >;
        };
 
        spi0_pins: pinmux_spi0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0)        /* spi0_sclk.spi0_sclk */
-                       AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0)        /* spi0_cs0.spi0_cs0 */
-                       AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0)        /* spi0_d0.spi0_d0 */
-                       AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0)        /* spi0_d1.spi0_d1 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 };
index 48aee6d..5923b6e 100644 (file)
        cpsw_default: cpsw_default {
                pinctrl-single,pins = <
                        /* Slave 1 */
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* mii1_crs.rmii1_crs_dv */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE1)       /* mii1_rxerr.rmii1_rxerr */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* mii1_txen.rmii1_txen */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* mii1_txd1.rmii1_txd1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* mii1_txd0.rmii1_txd0 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE1)       /* mii1_rxd1.rmii1_rxd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE1)       /* mii1_rxd0.rmii1_rxd0 */
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* mii1_refclk.rmii1_refclk */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE1)      /* mii1_crs.rmii1_crs_dv */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLUP, MUX_MODE1)      /* mii1_rxerr.rmii1_rxerr */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE1)   /* mii1_txen.rmii1_txen */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE1)    /* mii1_txd1.rmii1_txd1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE1)    /* mii1_txd0.rmii1_txd0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE1)       /* mii1_rxd1.rmii1_rxd1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLUP, MUX_MODE1)       /* mii1_rxd0.rmii1_rxd0 */
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        spi1_pins: pinmux_spi1 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x964, PIN_INPUT_PULLUP | MUX_MODE4)        /* ecap0_in_pwm0_out.spi1_sclk */
-                       AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE4)        /* uart1_ctsn.spi1_cs0 */
-                       AM33XX_IOPAD(0x968, PIN_INPUT_PULLUP | MUX_MODE4)        /* uart0_ctsn.spi1_d0 */
-                       AM33XX_IOPAD(0x96c, PIN_INPUT_PULLUP | MUX_MODE4)        /* uart0_rtsn.spi1_d1 */
+                       AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, PIN_INPUT_PULLUP, MUX_MODE4)        /* ecap0_in_pwm0_out.spi1_sclk */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE4)       /* uart1_ctsn.spi1_cs0 */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT_PULLUP, MUX_MODE4)       /* uart0_ctsn.spi1_d0 */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLUP, MUX_MODE4)       /* uart0_rtsn.spi1_d1 */
                >;
        };
 };
index e562ce4..5a2fb4b 100644 (file)
 
        minipcie_pins: pinmux_minipcie {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* lcd_pclk.gpio2_24 */
-                       AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* lcd_ac_bias_en.gpio2_25 */
-                       AM33XX_IOPAD(0x8e0, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* lcd_vsync.gpio2_22  Power off PIN*/
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* lcd_pclk.gpio2_24 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)        /* lcd_ac_bias_en.gpio2_25 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_INPUT_PULLDOWN, MUX_MODE7)     /* lcd_vsync.gpio2_22  Power off PIN*/
                >;
        };
 
        push_button_pins: pinmux_push_button {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* mcasp0_ahcklx.gpio3_21 */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLDOWN, MUX_MODE7) /* mcasp0_ahcklx.gpio3_21 */
                >;
        };
 
        i2c0_pins: pinmux_i2c0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c0_scl.i2c0_scl */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
 
        i2c1_pins: pinmux_i2c1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x968, PIN_INPUT_PULLUP | MUX_MODE3)       /* uart0_ctsn.i2c1_sda */
-                       AM33XX_IOPAD(0x96c, PIN_INPUT_PULLUP | MUX_MODE3)       /* uart0_rtsn.i2c1_scl */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT_PULLUP, MUX_MODE3)      /* uart0_ctsn.i2c1_sda */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLUP, MUX_MODE3)      /* uart0_rtsn.i2c1_scl */
                >;
        };
 
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        uart1_pins: pinmux_uart1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x978, PIN_INPUT | MUX_MODE0)              /* uart1_ctsn.uart1_ctsn */
-                       AM33XX_IOPAD(0x97C, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_rtsn.uart1_rtsn */
-                       AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)    /* uart1_rxd.uart1_rxd */
-                       AM33XX_IOPAD(0x984, PIN_OUTPUT | MUX_MODE0)             /* uart1_txd.uart1_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 
        uart2_pins: pinmux_uart2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8d8, PIN_INPUT | MUX_MODE6)              /* lcd_data14.uart5_ctsn */
-                       AM33XX_IOPAD(0x8dc, PIN_OUTPUT_PULLDOWN | MUX_MODE6)  /* lcd_data15.uart5_rtsn */
-                       AM33XX_IOPAD(0x8c4, PIN_INPUT_PULLUP | MUX_MODE4)     /* lcd_data9.uart5_rxd */
-                       AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE4)             /* lcd_data8.uart5_txd */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_INPUT, MUX_MODE6)             /* lcd_data14.uart5_ctsn */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT_PULLDOWN, MUX_MODE6)  /* lcd_data15.uart5_rtsn */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_INPUT_PULLUP, MUX_MODE4)     /* lcd_data9.uart5_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE4)             /* lcd_data8.uart5_txd */
                >;
        };
 
        cpsw_default: cpsw_default {
                pinctrl-single,pins = <
                        /* Slave 1 */
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1)  /* mii1_crs.rmii1_crs_dv */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE1)    /* mii1_rxerr.rmii1_rxerr */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txen.rmii1_txen */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE1)    /* mii1_rxd1.rmii1_rxd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE1)    /* mii1_rxd0.rmii1_rxd0 */
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0)  /* mii1_refclk.rmii1_refclk */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE0)
 
                        /* Slave 2 */
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLDOWN | MUX_MODE3)   /* rmii2_crs_dv */
-                       AM33XX_IOPAD(0x874, PIN_INPUT_PULLDOWN | MUX_MODE3)   /* rmii2_rxer */
-                       AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE3)  /* rmii2_txen */
-                       AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE3)  /* rmii2_td1 */
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE3)  /* rmii2_td0 */
-                       AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE3)   /* rmii2_rd1 */
-                       AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE3)   /* rmii2_rd0 */
-                       AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE1)  /* rmii2_refclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLDOWN, MUX_MODE3)   /* rmii2_crs_dv */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_INPUT_PULLDOWN, MUX_MODE3)   /* rmii2_rxer */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)  /* rmii2_txen */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT_PULLDOWN, MUX_MODE3)  /* rmii2_td1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE3)  /* rmii2_td0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE3)   /* rmii2_rd1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE3)   /* rmii2_rd0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLDOWN, MUX_MODE1)  /* rmii2_refclk */
 
                >;
        };
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
                        /* MDIO */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)                      /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        mmc0_pins_default: pinmux_mmc0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat3 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat2 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat1 */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat0 */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_clk */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_cmd */
-                       AM33XX_IOPAD(0x990, PIN_INPUT_PULLUP | MUX_MODE7)       /* mcasp0_aclkx.gpio3_14 */
-                       AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLUP | MUX_MODE7)    /* mcasp0_aclkx.gpio3_18 */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT_PULLUP, MUX_MODE7)    /* mcasp0_aclkx.gpio3_14 */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_INPUT_PULLUP, MUX_MODE7)    /* mcasp0_aclkx.gpio3_18 */
                >;
        };
 
        mmc2_pins_default: pinmux_mmc2_pins {
                pinctrl-single,pins = <
                        /* eMMC */
-                       AM33XX_IOPAD(0x830, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ad12.mmc2_dat0 */
-                       AM33XX_IOPAD(0x834, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ad13.mmc2_dat1 */
-                       AM33XX_IOPAD(0x838, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ad14.mmc2_dat2 */
-                       AM33XX_IOPAD(0x83c, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ad15.mmc2_dat3 */
-                       AM33XX_IOPAD(0x820, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ad8.mmc2_dat4 */
-                       AM33XX_IOPAD(0x824, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ad9.mmc2_dat5 */
-                       AM33XX_IOPAD(0x828, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ad10.mmc2_dat6 */
-                       AM33XX_IOPAD(0x82c, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ad11.mmc2_dat7 */
-                       AM33XX_IOPAD(0x888, PIN_INPUT_PULLUP | MUX_MODE3)     /* gpmc_csn3.mmc2_cmd */
-                       AM33XX_IOPAD(0x88c, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_clk.mmc2_clk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_ad12.mmc2_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_ad13.mmc2_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_ad14.mmc2_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_ad15.mmc2_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_INPUT_PULLUP, MUX_MODE3)        /* gpmc_ad8.mmc2_dat4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_INPUT_PULLUP, MUX_MODE3)        /* gpmc_ad9.mmc2_dat5 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_ad10.mmc2_dat6 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_ad11.mmc2_dat7 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_INPUT_PULLUP, MUX_MODE3)     /* gpmc_csn3.mmc2_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CLK, PIN_INPUT_PULLUP, MUX_MODE3)        /* gpmc_clk.mmc2_clk */
                >;
        };
 
        spi0_pins: pinmux_spi0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_sclk.spi0_sclk */
-                       AM33XX_IOPAD(0x95C, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_cs0.spi0_cs0 */
-                       AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d0.spi0_d0 */
-                       AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d1.spi0_d1 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
index 9c9143e..0052657 100644 (file)
 
        misc_pins: misc_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x95c, PIN_OUTPUT | MUX_MODE7)     /* spi0_cs0.gpio0_5 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_OUTPUT, MUX_MODE7)      /* spi0_cs0.gpio0_5 */
                >;
        };
 
        gpmc_pins: gpmc_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad0.gpmc_ad0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad1.gpmc_ad1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad2.gpmc_ad2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad3.gpmc_ad3 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad4.gpmc_ad4 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad5.gpmc_ad5 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad6.gpmc_ad6 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad7.gpmc_ad7 */
-                       AM33XX_IOPAD(0x820, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad8.gpmc_ad8 */
-                       AM33XX_IOPAD(0x824, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad9.gpmc_ad9 */
-                       AM33XX_IOPAD(0x828, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad10.gpmc_ad10 */
-                       AM33XX_IOPAD(0x82c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad11.gpmc_ad11 */
-                       AM33XX_IOPAD(0x830, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad12.gpmc_ad12 */
-                       AM33XX_IOPAD(0x834, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad13.gpmc_ad13 */
-                       AM33XX_IOPAD(0x838, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad14.gpmc_ad14 */
-                       AM33XX_IOPAD(0x83c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad15.gpmc_ad15 */
-
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_wait0.gpmc_wait0 */
-                       AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0)             /* gpmc_csn0.gpmc_csn0 */
-                       AM33XX_IOPAD(0x880, PIN_OUTPUT | MUX_MODE0)             /* gpmc_csn1.gpmc_csn1 */
-                       AM33XX_IOPAD(0x884, PIN_OUTPUT | MUX_MODE0)             /* gpmc_csn2.gpmc_csn2 */
-                       AM33XX_IOPAD(0x888, PIN_OUTPUT | MUX_MODE0)             /* gpmc_csn3.gpmc_csn3 */
-
-                       AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0)             /* gpmc_advn_ale.gpmc_advn_ale */
-                       AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0)             /* gpmc_oen_ren.gpmc_oen_ren */
-                       AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0)             /* gpmc_wen.gpmc_wen */
-                       AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0)             /* gpmc_ben0_cle.gpmc_ben0_cle */
-
-                       AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE1)             /* lcd_data1.gpmc_a1 */
-                       AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE1)             /* lcd_data2.gpmc_a2 */
-                       AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE1)             /* lcd_data3.gpmc_a3 */
-                       AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE1)             /* lcd_data4.gpmc_a4 */
-                       AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE1)             /* lcd_data5.gpmc_a5 */
-                       AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE1)             /* lcd_data6.gpmc_a6 */
-                       AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE1)             /* lcd_data7.gpmc_a7 */
-
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE1)             /* lcd_vsync.gpmc_a8 */
-                       AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE1)             /* lcd_hsync.gpmc_a9 */
-                       AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE1)             /* lcd_pclk.gpmc_a10 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLUP, MUX_MODE0)
+
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_OUTPUT, MUX_MODE0)
+
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_ADVN_ALE, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_OEN_REN, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WEN, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN0_CLE, PIN_OUTPUT, MUX_MODE0)
+
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE1)             /* lcd_data1.gpmc_a1 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE1)             /* lcd_data2.gpmc_a2 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE1)             /* lcd_data3.gpmc_a3 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE1)             /* lcd_data4.gpmc_a4 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE1)             /* lcd_data5.gpmc_a5 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE1)             /* lcd_data6.gpmc_a6 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE1)             /* lcd_data7.gpmc_a7 */
+
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE1)             /* lcd_vsync.gpmc_a8 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE1)             /* lcd_hsync.gpmc_a9 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE1)              /* lcd_pclk.gpmc_a10 */
                >;
        };
 
        i2c0_pins: i2c0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* i2c0_scl.i2c0_scl */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        uart0_pins: uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT | MUX_MODE0)             /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 
        uart1_pins: uart1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x978, PIN_OUTPUT | MUX_MODE7)             /* uart1_ctsn.uart1_ctsn */
-                       AM33XX_IOPAD(0x97c, PIN_OUTPUT | MUX_MODE7)             /* uart1_rtsn.uart1_rtsn */
-                       AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart1_rxd.uart1_rxd */
-                       AM33XX_IOPAD(0x984, PIN_OUTPUT | MUX_MODE0)             /* uart1_txd.uart1_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 
        uart2_pins: uart2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8c0, PIN_INPUT_PULLUP | MUX_MODE7)       /* lcd_data8.gpio2[14] */
-                       AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE7)             /* lcd_data9.gpio2[15] */
-                       AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1)              /* spi0_sclk.uart2_rxd */
-                       AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1)             /* spi0_d0.uart2_txd */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_INPUT_PULLUP, MUX_MODE7)       /* lcd_data8.gpio2[14] */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE7)             /* lcd_data9.gpio2[15] */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE1)              /* spi0_sclk.uart2_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE1)               /* spi0_d0.uart2_txd */
                >;
        };
 
        uart3_pins: uart3_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8c8, PIN_INPUT_PULLUP | MUX_MODE6)       /* lcd_data10.uart3_ctsn */
-                       AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE6)             /* lcd_data11.uart3_rtsn */
-                       AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE1)              /* spi0_cs1.uart3_rxd */
-                       AM33XX_IOPAD(0x964, PIN_OUTPUT | MUX_MODE1)             /* ecap0_in_pwm0_out.uart3_txd */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_INPUT_PULLUP, MUX_MODE6)      /* lcd_data10.uart3_ctsn */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE6)            /* lcd_data11.uart3_rtsn */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE1)               /* spi0_cs1.uart3_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, PIN_OUTPUT, MUX_MODE1)             /* ecap0_in_pwm0_out.uart3_txd */
                >;
        };
 
        uart4_pins: uart4_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8d0, PIN_INPUT_PULLUP | MUX_MODE6)       /* lcd_data12.uart4_ctsn */
-                       AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE6)             /* lcd_data13.uart4_rtsn */
-                       AM33XX_IOPAD(0x968, PIN_INPUT | MUX_MODE1)              /* uart0_ctsn.uart4_rxd */
-                       AM33XX_IOPAD(0x96c, PIN_OUTPUT | MUX_MODE1)             /* uart0_rtsn.uart4_txd */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_INPUT_PULLUP, MUX_MODE6)      /* lcd_data12.uart4_ctsn */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE6)            /* lcd_data13.uart4_rtsn */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT, MUX_MODE1)             /* uart0_ctsn.uart4_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_OUTPUT, MUX_MODE1)            /* uart0_rtsn.uart4_txd */
                >;
        };
 
        uart5_pins: uart5_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8d8, PIN_INPUT | MUX_MODE4)              /* lcd_data14.uart5_rxd */
-                       AM33XX_IOPAD(0x944, PIN_OUTPUT | MUX_MODE3)             /* rmiii1_refclk.uart5_txd */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_INPUT, MUX_MODE4)             /* lcd_data14.uart5_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_OUTPUT, MUX_MODE3)         /* rmiii1_refclk.uart5_txd */
                >;
        };
 
        mmc1_pins: mmc1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat0.mmc0_dat0 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat1.mmc0_dat1 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat2.mmc0_dat2 */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat3.mmc0_dat3 */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_clk.mmc0_clk */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_cmd.mmc0_cmd */
-                       AM33XX_IOPAD(0x9e8, PIN_INPUT_PULLUP | MUX_MODE7)       /* emu1.gpio3[8] */
-                       AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLUP | MUX_MODE7)       /* mcasp0_aclkr.gpio3[18] */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)        /* mmc0_clk.mmc0_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)        /* mmc0_cmd.mmc0_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_EMU1, PIN_INPUT_PULLUP, MUX_MODE7)    /* emu1.gpio3[8] */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_INPUT_PULLUP, MUX_MODE7)    /* mcasp0_aclkr.gpio3[18] */
                >;
        };
 };
index 95d54cf..f47cc9f 100644 (file)
 &am33xx_pinmux {
        nxp_hdmi_bonelt_pins: nxp-hdmi-bonelt-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* xdma_event_intr0 */
-                       AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data0.lcd_data0 */
-                       AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data1.lcd_data1 */
-                       AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data2.lcd_data2 */
-                       AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)             /* lcd_data3.lcd_data3 */
-                       AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data4.lcd_data4 */
-                       AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data5.lcd_data5 */
-                       AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data6.lcd_data6 */
-                       AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)             /* lcd_data7.lcd_data7 */
-                       AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data8.lcd_data8 */
-                       AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data9.lcd_data9 */
-                       AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data10.lcd_data10 */
-                       AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)             /* lcd_data11.lcd_data11 */
-                       AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data12.lcd_data12 */
-                       AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data13.lcd_data13 */
-                       AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data14.lcd_data14 */
-                       AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)             /* lcd_data15.lcd_data15 */
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* lcd_vsync.lcd_vsync */
-                       AM33XX_IOPAD(0x8e4, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* lcd_hsync.lcd_hsync */
-                       AM33XX_IOPAD(0x8e8, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* lcd_pclk.lcd_pclk */
-                       AM33XX_IOPAD(0x8ec, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* lcd_ac_bias_en.lcd_ac_bias_en */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        nxp_hdmi_bonelt_off_pins: nxp-hdmi-bonelt-off-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* xdma_event_intr0 */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)
                >;
        };
 
        mcasp0_pins: mcasp0-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLUP | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
-                       AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
-                       AM33XX_IOPAD(0x994, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
-                       AM33XX_IOPAD(0x990, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
-                       AM33XX_IOPAD(0x86c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.GPIO1_27 */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_OUTPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a11.GPIO1_27 */
                >;
        };
 
        flash_enable: flash-enable {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x944, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* rmii1_ref_clk.gpio0_29 */
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7)        /* rmii1_ref_clk.gpio0_29 */
                >;
        };
 
        imu_interrupt: imu-interrupt {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)             /* mii1_rx_er.gpio3_2 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7)            /* mii1_rx_er.gpio3_2 */
                >;
        };
 
        ethernet_interrupt: ethernet-interrupt{
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7)             /* mii1_col.gpio3_0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLDOWN, MUX_MODE7)              /* mii1_col.gpio3_0 */
                >;
        };
 };
 
        user_leds_s0: user-leds-s0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_a5.gpio1_21 */
-                       AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* gpmc_a6.gpio1_22 */
-                       AM33XX_IOPAD(0x85c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_a7.gpio1_23 */
-                       AM33XX_IOPAD(0x860, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* gpmc_a8.gpio1_24 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* gpmc_a5.gpio1_21 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7)        /* gpmc_a6.gpio1_22 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT_PULLDOWN, MUX_MODE7)      /* gpmc_a7.gpio1_23 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT_PULLUP, MUX_MODE7)        /* gpmc_a8.gpio1_24 */
                >;
        };
 
        i2c2_pins: pinmux-i2c2-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE3)       /* uart1_ctsn.i2c2_sda */
-                       AM33XX_IOPAD(0x97c, PIN_INPUT_PULLUP | MUX_MODE3)       /* uart1_rtsn.i2c2_scl */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3)      /* uart1_ctsn.i2c2_sda */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLUP, MUX_MODE3)      /* uart1_rtsn.i2c2_scl */
                >;
        };
 
        uart0_pins: pinmux-uart0-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        clkout2_pin: pinmux-clkout2-pin {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* xdma_event_intr1.clkout2 */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3)     /* xdma_event_intr1.clkout2 */
                >;
        };
 
        cpsw_default: cpsw-default {
                pinctrl-single,pins = <
                        /* Slave 1 */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txen.rgmii1_tctl */
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2)             /* mii1_rxdv.rgmii1_rctl */
-                       AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd3.rgmii1_txd3 */
-                       AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd2.rgmii1_txd2 */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd1.rgmii1_txd1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd0.rgmii1_txd0 */
-                       AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txclk.rgmii1_txclk */
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2)             /* mii1_rxclk.rgmii1_rxclk */
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2)             /* mii1_rxd3.rgmii1_rxd3 */
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2)             /* mii1_rxd2.rgmii1_rxd2 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2)             /* mii1_rxd1.rgmii1_rxd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2)             /* mii1_rxd0.rgmii1_rxd0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2)   /* mii1_txen.rgmii1_tctl */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE2)            /* mii1_rxdv.rgmii1_rctl */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE2)
                >;
        };
 
        cpsw_sleep: cpsw-sleep {
                pinctrl-single,pins = <
                        /* Slave 1 reset value */
-                       AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        davinci_mdio_default: davinci-mdio-default {
                pinctrl-single,pins = <
                        /* MDIO */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)                      /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        davinci_mdio_sleep: davinci-mdio-sleep {
                pinctrl-single,pins = <
                        /* MDIO reset value */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        mmc1_pins: pinmux-mmc1-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* (C15) spi0_cs1.gpio0[6] */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* (G16) mmc0_dat0.mmc0_dat0 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* (G15) mmc0_dat1.mmc0_dat1 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* (F18) mmc0_dat2.mmc0_dat2 */
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* (F17) mmc0_dat3.mmc0_dat3 */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* (G18) mmc0_cmd.mmc0_cmd */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* (G17) mmc0_clk.mmc0_clk */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7) /* (C15) spi0_cs1.gpio0[6] */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        emmc_pins: pinmux-emmc-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
-                       AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
                >;
        };
 };
index f8ff473..a8b6842 100644 (file)
@@ -36,8 +36,8 @@
 &am33xx_pinmux {
        i2c0_pins: pinmux-i2c0-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)       /* (C17) I2C0_SDA.I2C0_SDA */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)       /* (C16) I2C0_SCL.I2C0_SCL */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 };
index 1ec8e0d..baceaa7 100644 (file)
 &am33xx_pinmux {
        user_buttons_pins: pinmux_user_buttons {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9e4, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* emu0.gpio3_7 */
-                       AM33XX_IOPAD(0x9e8, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* emu1.gpio3_8 */
+                       AM33XX_PADCONF(AM335X_PIN_EMU0, PIN_INPUT_PULLDOWN, MUX_MODE7)  /* emu0.gpio3_7 */
+                       AM33XX_PADCONF(AM335X_PIN_EMU1, PIN_INPUT_PULLDOWN, MUX_MODE7)  /* emu1.gpio3_8 */
                >;
        };
 
        user_leds_pins: pinmux_user_leds {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x880, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_csn1.gpio1_30 */
-                       AM33XX_IOPAD(0x884, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* gpmc_csn2.gpio1_31 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_OUTPUT_PULLDOWN, MUX_MODE7)    /* gpmc_csn1.gpio1_30 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_OUTPUT_PULLDOWN, MUX_MODE7)    /* gpmc_csn2.gpio1_31 */
                >;
        };
 };
@@ -96,8 +96,8 @@
 &am33xx_pinmux {
        dcan1_pins: pinmux_dcan1 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x980, PIN_OUTPUT_PULLUP | MUX_MODE2)      /* uart1_rxd.dcan1_tx_mux2 */
-                       AM33XX_IOPAD(0x984, PIN_INPUT_PULLUP | MUX_MODE2)       /* uart1_txd.dcan1_rx_mux2 */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_OUTPUT_PULLUP, MUX_MODE2)      /* uart1_rxd.dcan1_tx_mux2 */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT_PULLUP, MUX_MODE2)       /* uart1_txd.dcan1_rx_mux2 */
                >;
        };
 };
 &am33xx_pinmux {
        ethernet1_pins: pinmux_ethernet1 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a0.rgmii2_tctl */
-                       AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a1.rgmii2_rctl */
-                       AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a2.rgmii2_td3 */
-                       AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a3.rgmii2_td2 */
-                       AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a4.rgmii2_td1 */
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a5.rgmii2_td0 */
-                       AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a6.rgmii2_tclk */
-                       AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a7.rgmii2_rclk */
-                       AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a8.rgmii2_rd3 */
-                       AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a9.rgmii2_rd2 */
-                       AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a10.rgmii2_rd1 */
-                       AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a11.rgmii2_rd0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a0.rgmii2_tctl */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE2)       /* gpmc_a1.rgmii2_rctl */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a2.rgmii2_td3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a3.rgmii2_td2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a4.rgmii2_td1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a5.rgmii2_td0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a6.rgmii2_tclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_INPUT_PULLDOWN, MUX_MODE2)       /* gpmc_a7.rgmii2_rclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_INPUT_PULLDOWN, MUX_MODE2)       /* gpmc_a8.rgmii2_rd3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLDOWN, MUX_MODE2)       /* gpmc_a9.rgmii2_rd2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a10.rgmii2_rd1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE2)      /* gpmc_a11.rgmii2_rd0 */
                >;
        };
 };
 
        cb_gpio_pins: pinmux_cb_gpio {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x968, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* uart0_ctsn.gpio1_8 */
-                       AM33XX_IOPAD(0x96c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* uart0_rtsn.gpio1_9 */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE7)   /* uart0_ctsn.gpio1_8 */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE7)   /* uart0_rtsn.gpio1_9 */
                >;
        };
 };
 &am33xx_pinmux {
        mmc1_pins: pinmux_mmc1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat3.mmc0_dat3 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat2.mmc0_dat2 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat1.mmc0_dat1 */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat0.mmc0_dat0 */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_clk.mmc0_clk */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_cmd.mmc0_cmd */
-                       AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE7)       /* spi0_cs1.mmc0_sdcd */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT_PULLUP, MUX_MODE7)        /* spi0_cs1.mmc0_sdcd */
                >;
        };
 };
 &am33xx_pinmux {
        uart0_pins: pinmux_uart0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        uart1_pins: pinmux_uart1 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart1_rxd.uart1_rxd */
-                       AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart1_txd.uart1_txd */
-                       AM33XX_IOPAD(0x978, PIN_INPUT | MUX_MODE0)              /* uart1_ctsn.uart1_ctsn */
-                       AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart1_rtsn.uart1_rtsn */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        uart2_pins: pinmux_uart2 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE1)       /* mii1_tx_clk.uart2_rxd */
-                       AM33XX_IOPAD(0x930, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* mii1_rx_clk.uart2_txd */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLUP, MUX_MODE1)     /* mii1_tx_clk.uart2_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE1)  /* mii1_rx_clk.uart2_txd */
                >;
        };
 
        uart3_pins: pinmux_uart3 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE1)       /* mii1_rxd3.uart3_rxd */
-                       AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* mii1_rxd2.uart3_txd */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1)       /* mii1_rxd3.uart3_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1)    /* mii1_rxd2.uart3_txd */
                >;
        };
 };
index ae43d61..3141255 100644 (file)
 
        i2c0_pins: pinmux_i2c0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_scl.i2c0_scl */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        i2c1_pins: pinmux_i2c1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE2)       /* spi0_d1.i2c1_sda */
-                       AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE2)       /* spi0_cs0.i2c1_scl */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_d1.i2c1_sda */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE2)        /* spi0_cs0.i2c1_scl */
                >;
        };
 
        i2c2_pins: pinmux_i2c2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE2)       /* spi0_clk.i2c2_sda */
-                       AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE2)       /* spi0_d0.i2c2_scl */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE2)       /* spi0_clk.i2c2_sda */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_d0.i2c2_scl */
                >;
        };
 
        spi1_pins: pinmux_spi1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x990, PIN_OUTPUT | MUX_MODE3)             /* mcasp0_aclkx.spi1_sclk */
-                       AM33XX_IOPAD(0x994, PIN_OUTPUT | MUX_MODE3)             /* mcasp0_fsx.spi1_d0 */
-                       AM33XX_IOPAD(0x998, PIN_INPUT_PULLDOWN | MUX_MODE3)     /* mcasp0_axr0.spi1_d1 */
-                       AM33XX_IOPAD(0x99C, PIN_OUTPUT | MUX_MODE3)             /* mcasp0_ahclkr.spi1_cs0 */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_OUTPUT, MUX_MODE3)          /* mcasp0_aclkx.spi1_sclk */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_OUTPUT, MUX_MODE3)            /* mcasp0_fsx.spi1_d0 */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_INPUT_PULLDOWN, MUX_MODE3)   /* mcasp0_axr0.spi1_d1 */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT, MUX_MODE3)         /* mcasp0_ahclkr.spi1_cs0 */
                >;
        };
 
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x96C, PIN_OUTPUT | MUX_MODE7)             /* uart0_rtsn.gpio1_9 */
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        uart1_pins: pinmux_uart1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart1_rxd.uart1_rxd */
-                       AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart1_txd.uart1_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        uart3_pins: pinmux_uart3_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE1)       /* spi0_cs1.uart3_rxd */
-                       AM33XX_IOPAD(0x964, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* ecap0_in_pwm0_out.uart3_txd */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT_PULLUP, MUX_MODE1)        /* spi0_cs1.uart3_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, PIN_OUTPUT_PULLDOWN, MUX_MODE1)    /* ecap0_in_pwm0_out.uart3_txd */
                >;
        };
 
        clkout2_pin: pinmux_clkout2_pin {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* xdma_event_intr1.clkout2 */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3)     /* xdma_event_intr1.clkout2 */
                >;
        };
 
        cpsw_default: cpsw_default {
                pinctrl-single,pins = <
                        /* Port 1 (emac0) */
-                       AM33XX_IOPAD(0x908, PIN_INPUT | MUX_MODE0)              /* mii1_col.mii1_col */
-                       AM33XX_IOPAD(0x90C, PIN_INPUT | MUX_MODE0)              /* mii1_crs.mii1_crs */
-                       AM33XX_IOPAD(0x910, PIN_INPUT | MUX_MODE0)              /* mii1_rxer.mii1_rxer */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT | MUX_MODE0)             /* mii1_txen.mii1_txen */
-                       AM33XX_IOPAD(0x918, PIN_INPUT | MUX_MODE0)              /* mii1_rxdv.mii1_rxdv */
-                       AM33XX_IOPAD(0x91c, PIN_OUTPUT | MUX_MODE0)             /* mii1_txd3.mii1_txd3 */
-                       AM33XX_IOPAD(0x920, PIN_OUTPUT | MUX_MODE0)             /* mii1_txd2.mii1_txd2 */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT | MUX_MODE0)             /* mii1_txd1.mii1_txd1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT | MUX_MODE0)             /* mii1_txd0.mii1_txd0 */
-                       AM33XX_IOPAD(0x92c, PIN_INPUT | MUX_MODE0)              /* mii1_txclk.mii1_txclk */
-                       AM33XX_IOPAD(0x930, PIN_INPUT | MUX_MODE0)              /* mii1_rxclk.mii1_rxclk */
-                       AM33XX_IOPAD(0x934, PIN_INPUT | MUX_MODE0)              /* mii1_rxd3.mii1_rxd3 */
-                       AM33XX_IOPAD(0x938, PIN_INPUT | MUX_MODE0)              /* mii1_rxd2.mii1_rxd2 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT | MUX_MODE0)              /* mii1_rxd1.mii1_rxd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT | MUX_MODE0)              /* mii1_rxd0.mii1_rxd0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT, MUX_MODE0)
 
                        /* Port 2 (emac1) */
-                       AM33XX_IOPAD(0x840, PIN_OUTPUT | MUX_MODE1)             /* mii2_txen.gpmc_a0 */
-                       AM33XX_IOPAD(0x844, PIN_INPUT | MUX_MODE1)              /* mii2_rxdv.gpmc_a1 */
-                       AM33XX_IOPAD(0x848, PIN_OUTPUT | MUX_MODE1)             /* mii2_txd3.gpmc_a2 */
-                       AM33XX_IOPAD(0x84c, PIN_OUTPUT | MUX_MODE1)             /* mii2_txd2.gpmc_a3 */
-                       AM33XX_IOPAD(0x850, PIN_OUTPUT | MUX_MODE1)             /* mii2_txd1.gpmc_a4 */
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE1)             /* mii2_txd0.gpmc_a5 */
-                       AM33XX_IOPAD(0x858, PIN_INPUT | MUX_MODE1)              /* mii2_txclk.gpmc_a6 */
-                       AM33XX_IOPAD(0x85c, PIN_INPUT | MUX_MODE1)              /* mii2_rxclk.gpmc_a7 */
-                       AM33XX_IOPAD(0x860, PIN_INPUT | MUX_MODE1)              /* mii2_rxd3.gpmc_a8 */
-                       AM33XX_IOPAD(0x864, PIN_INPUT | MUX_MODE1)              /* mii2_rxd2.gpmc_a9 */
-                       AM33XX_IOPAD(0x868, PIN_INPUT | MUX_MODE1)              /* mii2_rxd1.gpmc_a10 */
-                       AM33XX_IOPAD(0x86C, PIN_INPUT | MUX_MODE1)              /* mii2_rxd0.gpmc_a11 */
-                       AM33XX_IOPAD(0x870, PIN_INPUT | MUX_MODE1)              /* mii2_crs.gpmc_wait0 */
-                       AM33XX_IOPAD(0x874, PIN_INPUT | MUX_MODE1)              /* mii2_rxer.gpmc_wpn */
-                       AM33XX_IOPAD(0x878, PIN_INPUT | MUX_MODE1)              /* mii2_col.gpmc_ben1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT, MUX_MODE1)               /* mii2_txen.gpmc_a0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT, MUX_MODE1)                /* mii2_rxdv.gpmc_a1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT, MUX_MODE1)               /* mii2_txd3.gpmc_a2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_OUTPUT, MUX_MODE1)               /* mii2_txd2.gpmc_a3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT, MUX_MODE1)               /* mii2_txd1.gpmc_a4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT, MUX_MODE1)               /* mii2_txd0.gpmc_a5 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_INPUT, MUX_MODE1)                /* mii2_txclk.gpmc_a6 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_INPUT, MUX_MODE1)                /* mii2_rxclk.gpmc_a7 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_INPUT, MUX_MODE1)                /* mii2_rxd3.gpmc_a8 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT, MUX_MODE1)                /* mii2_rxd2.gpmc_a9 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT, MUX_MODE1)               /* mii2_rxd1.gpmc_a10 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT, MUX_MODE1)               /* mii2_rxd0.gpmc_a11 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT, MUX_MODE1)             /* mii2_crs.gpmc_wait0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_INPUT, MUX_MODE1)               /* mii2_rxer.gpmc_wpn */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT, MUX_MODE1)              /* mii2_col.gpmc_ben1 */
                >;
        };
 
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)                      /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        mmc1_pins: pinmux_mmc1_pins {
                /* eMMC */
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat3 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat2 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat1 */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat0 */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_clk */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        mmc2_pins: pinmux_mmc2_pins {
                /* SD cardcage */
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad3.mmc1_dat3 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad2.mmc1_dat2 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad1.mmc1_dat1 */
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad0.mmc1_dat0 */
-                       AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2)       /* gpmc_csn1.mmc1_clk */
-                       AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2)       /* gpmc_csn2.mmc1_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad3.mmc1_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad2.mmc1_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad1.mmc1_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad0.mmc1_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2)       /* gpmc_csn1.mmc1_clk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2)       /* gpmc_csn2.mmc1_cmd */
                        /* card change signal for frontpanel SD cardcage */
-                       AM33XX_IOPAD(0x890, PIN_INPUT | MUX_MODE7)              /* gpmc_advn_ale.gpio2_2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_ADVN_ALE, PIN_INPUT, MUX_MODE7)          /* gpmc_advn_ale.gpio2_2 */
                >;
        };
 
        lcd_pins_s0: lcd_pins_s0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data0.lcd_data0 */
-                       AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data1.lcd_data1 */
-                       AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data2.lcd_data2 */
-                       AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)             /* lcd_data3.lcd_data3 */
-                       AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data4.lcd_data4 */
-                       AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data5.lcd_data5 */
-                       AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data6.lcd_data6 */
-                       AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)             /* lcd_data7.lcd_data7 */
-                       AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data8.lcd_data8 */
-                       AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data9.lcd_data9 */
-                       AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data10.lcd_data10 */
-                       AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)             /* lcd_data11.lcd_data11 */
-                       AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)             /* lcd_data12.lcd_data12 */
-                       AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)             /* lcd_data13.lcd_data13 */
-                       AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)             /* lcd_data14.lcd_data14 */
-                       AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)             /* lcd_data15.lcd_data15 */
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0)             /* lcd_vsync.lcd_vsync */
-                       AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0)             /* lcd_hsync.lcd_hsync */
-                       AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0)             /* lcd_pclk.lcd_pclk */
-                       AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0)             /* lcd_ac_bias_en.lcd_ac_bias_en */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 
        dcan0_pins: pinmux_dcan0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x978, PIN_OUTPUT | MUX_MODE2)             /* uart1_ctsn.d_can0_tx */
-                       AM33XX_IOPAD(0x97c, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* uart1_rtsn.d_can0_rx */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_OUTPUT, MUX_MODE2)            /* uart1_ctsn.d_can0_tx */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLDOWN, MUX_MODE2)    /* uart1_rtsn.d_can0_rx */
                >;
        };
 };
index 6be79b8..5c3e49f 100644 (file)
 &am33xx_pinmux {
        i2c0_pins: pinmux_i2c0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_scl.i2c0_scl */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
        i2c1_pins: pinmux_i2c1 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x90C, PIN_INPUT_PULLUP | MUX_MODE3)       /* mii1_crs,i2c1_sda */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE3)       /* mii1_rxerr,i2c1_scl */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLUP, MUX_MODE3)        /* mii1_crs,i2c1_sda */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLUP, MUX_MODE3)      /* mii1_rxerr,i2c1_scl */
                >;
        };
 };
 &am33xx_pinmux {
        accel_pins: pinmux_accel {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x898, PIN_INPUT | MUX_MODE7)   /* gpmc_wen.gpio2_4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WEN, PIN_INPUT, MUX_MODE7)   /* gpmc_wen.gpio2_4 */
                >;
        };
 };
 &am33xx_pinmux {
        audio_pins: pinmux_audio {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* mcasp0_ahcklx.mcasp0_ahclkx */
-                       AM33XX_IOPAD(0x994, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* mcasp0_fsx.mcasp0_fsx */
-                       AM33XX_IOPAD(0x990, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* mcasp0_aclkx.mcasp0_aclkx */
-                       AM33XX_IOPAD(0x998, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* mcasp0_axr0.mcasp0_axr0 */
-                       AM33XX_IOPAD(0x9a8, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* mcasp0_axr1.mcasp0_axr1 */
-                       AM33XX_IOPAD(0x840, PIN_OUTPUT | MUX_MODE7)     /* gpmc_a0.gpio1_16 */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR1, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT, MUX_MODE7)       /* gpmc_a0.gpio1_16 */
                >;
        };
 };
 &am33xx_pinmux {
        lcd_pins: pinmux_lcd {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data0.lcd_data0 */
-                       AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data1.lcd_data1 */
-                       AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data2.lcd_data2 */
-                       AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)     /* lcd_data3.lcd_data3 */
-                       AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data4.lcd_data4 */
-                       AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data5.lcd_data5 */
-                       AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data6.lcd_data6 */
-                       AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)     /* lcd_data7.lcd_data7 */
-                       AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data8.lcd_data8 */
-                       AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data9.lcd_data9 */
-                       AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data10.lcd_data10 */
-                       AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)     /* lcd_data11.lcd_data11 */
-                       AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data12.lcd_data12 */
-                       AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data13.lcd_data13 */
-                       AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data14.lcd_data14 */
-                       AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)     /* lcd_data15.lcd_data15 */
-                       AM33XX_IOPAD(0x820, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad8.lcd_data16 */
-                       AM33XX_IOPAD(0x824, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad9.lcd_data17 */
-                       AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad10.lcd_data18 */
-                       AM33XX_IOPAD(0x82c, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad11.lcd_data19 */
-                       AM33XX_IOPAD(0x830, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad12.lcd_data20 */
-                       AM33XX_IOPAD(0x834, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad13.lcd_data21 */
-                       AM33XX_IOPAD(0x838, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad14.lcd_data22 */
-                       AM33XX_IOPAD(0x83c, PIN_OUTPUT | MUX_MODE1)     /* gpmc_ad15.lcd_data23 */
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0)     /* lcd_vsync.lcd_vsync */
-                       AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0)     /* lcd_hsync.lcd_hsync */
-                       AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0)     /* lcd_pclk.lcd_pclk */
-                       AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0)     /* lcd_ac_bias_en.lcd_ac_bias_en */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_OUTPUT, MUX_MODE1)      /* gpmc_ad8.lcd_data16 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_OUTPUT, MUX_MODE1)      /* gpmc_ad9.lcd_data17 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT, MUX_MODE1)     /* gpmc_ad10.lcd_data18 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_OUTPUT, MUX_MODE1)     /* gpmc_ad11.lcd_data19 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_OUTPUT, MUX_MODE1)     /* gpmc_ad12.lcd_data20 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_OUTPUT, MUX_MODE1)     /* gpmc_ad13.lcd_data21 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_OUTPUT, MUX_MODE1)     /* gpmc_ad14.lcd_data22 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_OUTPUT, MUX_MODE1)     /* gpmc_ad15.lcd_data23 */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0)
                        /* Display Enable */
-                       AM33XX_IOPAD(0x86c, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* gpmc_a11.gpio1_27 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_OUTPUT_PULLUP, MUX_MODE7)       /* gpmc_a11.gpio1_27 */
                >;
        };
 };
 &am33xx_pinmux {
        ethernet_pins: pinmux_ethernet {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txen.rgmii1_tctl */
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLUP | MUX_MODE2)       /* mii1_rxdv.rgmii1_rctl */
-                       AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd3.rgmii1_td3 */
-                       AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd2.rgmii1_td2 */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd1.rgmii1_td1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd0.rgmii1_td0 */
-                       AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE2)       /* mii1_txclk.rgmii1_tclk */
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLUP | MUX_MODE2)       /* mii1_rxclk.rgmii1_rclk */
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE2)       /* mii1_rxd3.rgmii1_rxd3 */
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLUP | MUX_MODE2)       /* mii1_rxd2.rgmii1_rxd2 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE2)       /* mii1_rxd1.rgmii1_rxd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE2)       /* mii1_rxd0.rgmii1_rxd0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2)   /* mii1_txen.rgmii1_tctl */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLUP, MUX_MODE2)      /* mii1_rxdv.rgmii1_rctl */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd3.rgmii1_td3 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd2.rgmii1_td2 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd1.rgmii1_td1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd0.rgmii1_td0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLUP, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLUP, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLUP, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLUP, MUX_MODE2)
                        /* ethernet interrupt */
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLUP | MUX_MODE7)       /* rmii2_refclk.gpio0_29 */
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLUP, MUX_MODE7)   /* rmii2_refclk.gpio0_29 */
                        /* ethernet PHY nReset */
-                       AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* mii1_col.gpio3_0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_OUTPUT_PULLUP, MUX_MODE7)       /* mii1_col.gpio3_0 */
                >;
        };
 
        mdio_pins: pinmux_mdio {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)                      /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 };
 &am33xx_pinmux {
        sd_pins: pinmux_sd_card {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat0.mmc0_dat0 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat1.mmc0_dat1 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat2.mmc0_dat2 */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat3.mmc0_dat3 */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_clk.mmc0_clk */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_cmd.mmc0_cmd */
-                       AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7)              /* spi0_cs1.gpio0_6 */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7)               /* spi0_cs1.gpio0_6 */
                >;
        };
        emmc_pins: pinmux_emmc {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2)       /* gpmc_csn1.mmc1_clk */
-                       AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2)       /* gpmc_csn2.mmc1_cmd */
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad0.mmc1_dat0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad1.mmc1_dat1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad2.mmc1_dat2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad3.mmc1_dat3 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad4.mmc1_dat4 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad5.mmc1_dat5 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad6.mmc1_dat6 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad7.mmc1_dat7 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2)       /* gpmc_csn1.mmc1_clk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2)       /* gpmc_csn2.mmc1_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad0.mmc1_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad1.mmc1_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad2.mmc1_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad3.mmc1_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad4.mmc1_dat4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad5.mmc1_dat5 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad6.mmc1_dat6 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad7.mmc1_dat7 */
                        /* EMMC nReset */
-                       AM33XX_IOPAD(0x874, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* gpmc_wpn.gpio0_31 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_OUTPUT_PULLUP, MUX_MODE7)       /* gpmc_wpn.gpio0_31 */
                >;
        };
        wireless_pins: pinmux_wireless {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_a1.mmc2_dat0 */
-                       AM33XX_IOPAD(0x848, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_a2.mmc2_dat1 */
-                       AM33XX_IOPAD(0x84c, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_a3.mmc2_dat2 */
-                       AM33XX_IOPAD(0x878, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_ben1.mmc2_dat3 */
-                       AM33XX_IOPAD(0x888, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_csn3.mmc2_cmd */
-                       AM33XX_IOPAD(0x88c, PIN_INPUT_PULLUP | MUX_MODE3)       /* gpmc_clk.mmc1_clk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_a1.mmc2_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_a2.mmc2_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_a3.mmc2_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_ben1.mmc2_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_INPUT_PULLUP, MUX_MODE3)       /* gpmc_csn3.mmc2_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CLK, PIN_INPUT_PULLUP, MUX_MODE3)        /* gpmc_clk.mmc1_clk */
                        /* WLAN nReset */
-                       AM33XX_IOPAD(0x860, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* gpmc_a8.gpio1_24 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT_PULLUP, MUX_MODE7)        /* gpmc_a8.gpio1_24 */
                        /* WLAN nPower down */
-                       AM33XX_IOPAD(0x870, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* gpmc_wait0.gpio0_30 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_OUTPUT_PULLUP, MUX_MODE7)     /* gpmc_wait0.gpio0_30 */
                        /* 32kHz Clock */
-                       AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* xdma_event_intr1.clkout2 */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3)     /* xdma_event_intr1.clkout2 */
                >;
        };
 };
 &am33xx_pinmux {
        spi0_pins: pinmux_spi0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_sclk.spi0_sclk */
-                       AM33XX_IOPAD(0x95C, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_cs0.spi0_cs0 */
-                       AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d0.spi0_d0 */
-                       AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d1.spi0_d1 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 };
 &am33xx_pinmux {
        uart0_pins: pinmux_uart0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
        uart1_pins: pinmux_uart1 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart1_ctsn.uart1_ctsn */
-                       AM33XX_IOPAD(0x97C, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart1_rtsn.uart1_rtsn */
-                       AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart1_rxd.uart1_rxd */
-                       AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart1_txd.uart1_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 };
        usb_pins: pinmux_usb {
                pinctrl-single,pins = <
                        /* USB0 Over-Current (active low) */
-                       AM33XX_IOPAD(0x864, PIN_INPUT | MUX_MODE7)      /* gpmc_a9.gpio1_25 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT, MUX_MODE7)        /* gpmc_a9.gpio1_25 */
                        /* USB1 Over-Current (active low) */
-                       AM33XX_IOPAD(0x868, PIN_INPUT | MUX_MODE7)      /* gpmc_a10.gpio1_26 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT, MUX_MODE7)       /* gpmc_a10.gpio1_26 */
                >;
        };
 };
 &am33xx_pinmux {
        user_leds_pins: pinmux_user_leds {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x850, PIN_OUTPUT | MUX_MODE7)     /* gpmc_a4.gpio1_20 */
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE7)     /* gpmc_a5.gpio1_21 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT, MUX_MODE7)       /* gpmc_a4.gpio1_20 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT, MUX_MODE7)       /* gpmc_a5.gpio1_21 */
                >;
        };
 
        user_buttons_pins: pinmux_user_buttons {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x858, PIN_INPUT_PULLUP | MUX_MODE7)       /* gpmc_a6.gpio1_22 */
-                       AM33XX_IOPAD(0x85C, PIN_INPUT_PULLUP | MUX_MODE7)       /* gpmc_a7.gpio1_21 */
-                       AM33XX_IOPAD(0x964, PIN_INPUT_PULLUP | MUX_MODE7)       /* gpmc_a8.gpio0_7 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_INPUT_PULLUP, MUX_MODE7) /* gpmc_a6.gpio1_22 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_INPUT_PULLUP, MUX_MODE7) /* gpmc_a7.gpio1_21 */
+                       AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, PIN_INPUT_PULLUP, MUX_MODE7)       /* gpmc_a8.gpio0_7 */
                >;
        };
 };
index 015adb6..23c3039 100644 (file)
 &am33xx_pinmux {
        ethernet0_pins: pinmux_ethernet0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* mii1_crs.rmii1_crs_dv */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* mii1_rxerr.rmii1_rxerr */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT | MUX_MODE1)             /* mii1_txen.rmii1_txen */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT | MUX_MODE1)             /* mii1_txd1.rmii1_txd1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT | MUX_MODE1)             /* mii1_txd0.rmii1_txd0 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* mii1_rxd1.rmii1_rxd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* mii1_rxd0.rmii1_rxd0 */
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* rmii1_refclk.rmii1_refclk */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_CRS, PIN_INPUT_PULLDOWN, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        mdio_pins: pinmux_mdio {
                pinctrl-single,pins = <
                        /* MDIO */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)                      /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 };
 &am33xx_pinmux {
        i2c0_pins: pinmux_i2c0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT | MUX_MODE0)      /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT | MUX_MODE0)      /* i2c0_scl.i2c0_scl */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT, MUX_MODE0)
                >;
        };
 };
 &am33xx_pinmux {
                nandflash_pins: pinmux_nandflash {
                        pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad0.gpmc_ad0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad1.gpmc_ad1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad2.gpmc_ad2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad3.gpmc_ad3 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad4.gpmc_ad4 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad5.gpmc_ad5 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad6.gpmc_ad6 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad7.gpmc_ad7 */
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_wait0.gpmc_wait0 */
-                       AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0)             /* gpmc_csn0.gpmc_csn0 */
-                       AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0)             /* gpmc_advn_ale.gpmc_advn_ale */
-                       AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0)             /* gpmc_oen_ren.gpmc_oen_ren */
-                       AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0)             /* gpmc_wen.gpmc_wen */
-                       AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0)             /* gpmc_be0n_cle.gpmc_be0n_cle */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_ADVN_ALE, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_OEN_REN, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WEN, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN0_CLE, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 };
 &am33xx_pinmux {
        spi0_pins: pinmux_spi0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x950, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* spi0_clk.spi0_clk */
-                       AM33XX_IOPAD(0x954, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* spi0_d0.spi0_d0 */
-                       AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0)       /* spi0_d1.spi0_d1 */
-                       AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0)       /* spi0_cs0.spi0_cs0 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 };
index 62fe5ca..ff4f919 100644 (file)
 &am33xx_pinmux {
        i2c2_pins: pinmux-i2c2-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x97c, PIN_INPUT_PULLUP | MUX_MODE3)       /* (D17) uart1_rtsn.I2C2_SCL */
-                       AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE3)       /* (D18) uart1_ctsn.I2C2_SDA */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLUP, MUX_MODE3)      /* (D17) uart1_rtsn.I2C2_SCL */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3)      /* (D18) uart1_ctsn.I2C2_SDA */
                >;
        };
 
        ehrpwm0_pins: pinmux-ehrpwm0-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x990, PIN_OUTPUT_PULLDOWN | MUX_MODE1)    /* (A13) mcasp0_aclkx.ehrpwm0A */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* (A13) mcasp0_aclkx.ehrpwm0A */
                >;
        };
 
        ehrpwm1_pins: pinmux-ehrpwm1-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE6)    /* (U14) gpmc_a2.ehrpwm1A */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT_PULLDOWN, MUX_MODE6)      /* (U14) gpmc_a2.ehrpwm1A */
                >;
        };
 
        mmc0_pins: pinmux-mmc0-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7)              /* (C15) spi0_cs1.gpio0[6] */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)       /* (G16) mmc0_dat0.mmc0_dat0 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)       /* (G15) mmc0_dat1.mmc0_dat1 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)       /* (F18) mmc0_dat2.mmc0_dat2 */
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)       /* (F17) mmc0_dat3.mmc0_dat3 */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)       /* (G18) mmc0_cmd.mmc0_cmd */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)       /* (G17) mmc0_clk.mmc0_clk */
-                       AM33XX_IOPAD(0x9a0, PIN_INPUT | MUX_MODE4)              /* (B12) mcasp0_aclkr.mmc0_sdwp */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7)               /* (C15) spi0_cs1.gpio0[6] */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_INPUT, MUX_MODE4)           /* (B12) mcasp0_aclkr.mmc0_sdwp */
                >;
        };
 
        spi0_pins: pinmux-spi0-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0)       /* (A17) spi0_sclk.spi0_sclk */
-                       AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0)       /* (B17) spi0_d0.spi0_d0 */
-                       AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0)       /* (B16) spi0_d1.spi0_d1 */
-                       AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0)       /* (A16) spi0_cs0.spi0_cs0 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        spi1_pins: pinmux-spi1-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x964, PIN_INPUT_PULLUP | MUX_MODE4)       /* (C18) eCAP0_in_PWM0_out.spi1_sclk */
-                       AM33XX_IOPAD(0x968, PIN_INPUT_PULLUP | MUX_MODE4)       /* (E18) uart0_ctsn.spi1_d0 */
-                       AM33XX_IOPAD(0x96c, PIN_INPUT_PULLUP | MUX_MODE4)       /* (E17) uart0_rtsn.spi1_d1 */
-                       AM33XX_IOPAD(0x9b0, PIN_INPUT_PULLUP | MUX_MODE4)       /* (A15) xdma_event_intr0.spi1_cs1 */
+                       AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, PIN_INPUT_PULLUP, MUX_MODE4)       /* (C18) eCAP0_in_PWM0_out.spi1_sclk */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT_PULLUP, MUX_MODE4)      /* (E18) uart0_ctsn.spi1_d0 */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLUP, MUX_MODE4)      /* (E17) uart0_rtsn.spi1_d1 */
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_INPUT_PULLUP, MUX_MODE4)        /* (A15) xdma_event_intr0.spi1_cs1 */
                >;
        };
 
        usr_leds_pins: pinmux-usr-leds-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE7)             /* (V15) gpmc_a5.gpio1[21] - USR_LED_0 */
-                       AM33XX_IOPAD(0x858, PIN_OUTPUT | MUX_MODE7)             /* (U15) gpmc_a6.gpio1[22] - USR_LED_1 */
-                       AM33XX_IOPAD(0x85c, PIN_OUTPUT | MUX_MODE7)             /* (T15) gpmc_a7.gpio1[23] - USR_LED_2 */
-                       AM33XX_IOPAD(0x860, PIN_OUTPUT | MUX_MODE7)             /* (V16) gpmc_a8.gpio1[24] - USR_LED_3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT, MUX_MODE7)               /* (V15) gpmc_a5.gpio1[21] - USR_LED_0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT, MUX_MODE7)               /* (U15) gpmc_a6.gpio1[22] - USR_LED_1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT, MUX_MODE7)               /* (T15) gpmc_a7.gpio1[23] - USR_LED_2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT, MUX_MODE7)               /* (V16) gpmc_a8.gpio1[24] - USR_LED_3 */
                >;
        };
 
        uart0_pins: pinmux-uart0-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* (E15) uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* (E16) uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        uart4_pins: pinmux-uart4-pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE6)       /* (T17) gpmc_wait0.uart4_rxd */
-                       AM33XX_IOPAD(0x874, PIN_OUTPUT_PULLDOWN | MUX_MODE6)    /* (U17) gpmc_wpn.uart4_txd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE6)      /* (T17) gpmc_wait0.uart4_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_OUTPUT_PULLDOWN, MUX_MODE6)     /* (U17) gpmc_wpn.uart4_txd */
                >;
        };
 };
index 35527fd..7ed27b5 100644 (file)
        cpsw_default: cpsw_default {
                pinctrl-single,pins = <
                        /* Slave 1 */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txen.rgmii1_tctl */
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxdv.rgmii1_rctl */
-                       AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd3.rgmii1_td3 */
-                       AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd2.rgmii1_td2 */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd1.rgmii1_td1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd0.rgmii1_td0 */
-                       AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txclk.rgmii1_tclk */
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxclk.rgmii1_rclk */
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxd3.rgmii1_rd3 */
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxd2.rgmii1_rd2 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxd1.rgmii1_rd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* mii1_rxd0.rgmii1_rd0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2)   /* mii1_txen.rgmii1_tctl */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE2)    /* mii1_rxdv.rgmii1_rctl */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd3.rgmii1_td3 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd2.rgmii1_td2 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd1.rgmii1_td1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE2)    /* mii1_txd0.rgmii1_td0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE2)  /* mii1_txclk.rgmii1_tclk */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE2)   /* mii1_rxclk.rgmii1_rclk */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE2)     /* mii1_rxd3.rgmii1_rd3 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE2)     /* mii1_rxd2.rgmii1_rd2 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE2)     /* mii1_rxd1.rgmii1_rd1 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE2)     /* mii1_rxd0.rgmii1_rd0 */
                >;
        };
 
        cpsw_sleep: cpsw_sleep {
                pinctrl-single,pins = <
                        /* Slave 1 reset value */
-                       AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
                        /* MDIO */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)                      /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        davinci_mdio_sleep: davinci_mdio_sleep {
                pinctrl-single,pins = <
                        /* MDIO reset value */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        usb_hub_ctrl: usb_hub_ctrl {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x944, PIN_OUTPUT_PULLUP | MUX_MODE7)     /* rmii1_refclk.gpio0_29 */
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7)     /* rmii1_refclk.gpio0_29 */
                >;
        };
 
        mpu6050_pins: pinmux_mpu6050_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x968, PIN_INPUT | MUX_MODE7)    /* uart0_ctsn.gpio1_8 */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT, MUX_MODE7)    /* uart0_ctsn.gpio1_8 */
                >;
        };
 
        lps3331ap_pins: pinmux_lps3331ap_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x868, PIN_INPUT | MUX_MODE7)     /* gpmc_a10.gpio1_26 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT, MUX_MODE7)     /* gpmc_a10.gpio1_26 */
                >;
        };
 };
index 917d7cc..07c46a5 100644 (file)
        lcd_pins_default: lcd_pins_default {
                pinctrl-single,pins = <
                        /* gpmc_ad8.lcd_data23 */
-                       AM33XX_IOPAD(0x820, PIN_OUTPUT | MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_OUTPUT, MUX_MODE1)
                        /* gpmc_ad9.lcd_data22 */
-                       AM33XX_IOPAD(0x824, PIN_OUTPUT | MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_OUTPUT, MUX_MODE1)
                        /* gpmc_ad10.lcd_data21 */
-                       AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT, MUX_MODE1)
                        /* gpmc_ad11.lcd_data20 */
-                       AM33XX_IOPAD(0x82c, PIN_OUTPUT | MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_OUTPUT, MUX_MODE1)
                        /* gpmc_ad12.lcd_data19 */
-                       AM33XX_IOPAD(0x830, PIN_OUTPUT | MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_OUTPUT, MUX_MODE1)
                        /* gpmc_ad13.lcd_data18 */
-                       AM33XX_IOPAD(0x834, PIN_OUTPUT | MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_OUTPUT, MUX_MODE1)
                        /* gpmc_ad14.lcd_data17 */
-                       AM33XX_IOPAD(0x838, PIN_OUTPUT | MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_OUTPUT, MUX_MODE1)
                        /* gpmc_ad15.lcd_data16 */
-                       AM33XX_IOPAD(0x83c, PIN_OUTPUT | MUX_MODE1)
-                       /* lcd_data0.lcd_data0 */
-                       AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data1.lcd_data1 */
-                       AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data2.lcd_data2 */
-                       AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data3.lcd_data3 */
-                       AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data4.lcd_data4 */
-                       AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data5.lcd_data5 */
-                       AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data6.lcd_data6 */
-                       AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data7.lcd_data7 */
-                       AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data8.lcd_data8 */
-                       AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data9.lcd_data9 */
-                       AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data10.lcd_data10 */
-                       AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data11.lcd_data11 */
-                       AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data12.lcd_data12 */
-                       AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data13.lcd_data13 */
-                       AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data14.lcd_data14 */
-                       AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_data15.lcd_data15 */
-                       AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_vsync.lcd_vsync */
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_hsync.lcd_hsync */
-                       AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_pclk.lcd_pclk */
-                       AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0)
-                       /* lcd_ac_bias_en.lcd_ac_bias_en */
-                       AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_OUTPUT, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 
        lcd_pins_sleep: lcd_pins_sleep {
                pinctrl-single,pins = <
                        /* gpmc_ad8.lcd_data23 */
-                       AM33XX_IOPAD(0x820, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_INPUT_PULLDOWN, MUX_MODE7)
                        /* gpmc_ad9.lcd_data22 */
-                       AM33XX_IOPAD(0x824, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_INPUT_PULLDOWN, MUX_MODE7)
                        /* gpmc_ad10.lcd_data21 */
-                       AM33XX_IOPAD(0x828, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_INPUT_PULLDOWN, MUX_MODE7)
                        /* gpmc_ad11.lcd_data20 */
-                       AM33XX_IOPAD(0x82c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_INPUT_PULLDOWN, MUX_MODE7)
                        /* gpmc_ad12.lcd_data19 */
-                       AM33XX_IOPAD(0x830, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLDOWN, MUX_MODE7)
                        /* gpmc_ad13.lcd_data18 */
-                       AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLDOWN, MUX_MODE7)
                        /* gpmc_ad14.lcd_data17 */
-                       AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_INPUT_PULLDOWN, MUX_MODE7)
                        /* gpmc_ad15.lcd_data16 */
-                       AM33XX_IOPAD(0x83c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       /* lcd_data0.lcd_data0 */
-                       AM33XX_IOPAD(0x8a0, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data1.lcd_data1 */
-                       AM33XX_IOPAD(0x8a4, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data2.lcd_data2 */
-                       AM33XX_IOPAD(0x8a8, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data3.lcd_data3 */
-                       AM33XX_IOPAD(0x8ac, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data4.lcd_data4 */
-                       AM33XX_IOPAD(0x8b0, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data5.lcd_data5 */
-                       AM33XX_IOPAD(0x8b4, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data6.lcd_data6 */
-                       AM33XX_IOPAD(0x8b8, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data7.lcd_data7 */
-                       AM33XX_IOPAD(0x8bc, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data8.lcd_data8 */
-                       AM33XX_IOPAD(0x8c0, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data9.lcd_data9 */
-                       AM33XX_IOPAD(0x8c4, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data10.lcd_data10 */
-                       AM33XX_IOPAD(0x8c8, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data11.lcd_data11 */
-                       AM33XX_IOPAD(0x8cc, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data12.lcd_data12 */
-                       AM33XX_IOPAD(0x8d0, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data13.lcd_data13 */
-                       AM33XX_IOPAD(0x8d4, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data14.lcd_data14 */
-                       AM33XX_IOPAD(0x8d8, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_data15.lcd_data15 */
-                       AM33XX_IOPAD(0x8dc, PULL_DISABLE | MUX_MODE7)
-                       /* lcd_vsync.lcd_vsync */
-                       AM33XX_IOPAD(0x8e0, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       /* lcd_hsync.lcd_hsync */
-                       AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       /* lcd_pclk.lcd_pclk */
-                       AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       /* lcd_ac_bias_en.lcd_ac_bias_en */
-                       AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PULL_DISABLE, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 };
index bfbe27a..5b03685 100644 (file)
        clkout2_pin: pinmux_clkout2_pin {
                pinctrl-single,pins = <
                        /* xdma_event_intr1.clkout2 */
-                       AM33XX_IOPAD(0x9b4, PIN_INPUT | MUX_MODE6)
+                       AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_INPUT, MUX_MODE6)
                >;
        };
 
        cpsw_default: cpsw_default {
                pinctrl-single,pins = <
                        /* Slave 1 */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE0)
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        cpsw_sleep: cpsw_sleep {
                pinctrl-single,pins = <
                        /* Slave 1 reset value */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
-                       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)
-                       /* mdio_clk.mdio_clk */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        davinci_mdio_sleep: davinci_mdio_sleep {
                pinctrl-single,pins = <
                        /* MDIO reset value */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        ehrpwm1_pins: pinmux_ehrpwm1 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x84c, PIN_OUTPUT | MUX_MODE6) /* gpmc_a3.gpio1_19 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_OUTPUT, MUX_MODE6) /* gpmc_a3.gpio1_19 */
                >;
        };
 
        emmc_pins: pinmux_emmc_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x880, PIN_INPUT | MUX_MODE2)
-                       AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2)
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1)
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1)
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1)
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1)
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1)
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1)
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1)
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE1)
                >;
        };
 
        i2c0_pins: pinmux_i2c0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT | MUX_MODE0)
-                       AM33XX_IOPAD(0x98c, PIN_INPUT | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT, MUX_MODE0)
                >;
        };
 
        mmc1_pins: pinmux_mmc1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE5)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE5)
                >;
        };
 
        mmc3_pins: pinmux_mmc3_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x830, PIN_INPUT | MUX_MODE3)
-                       AM33XX_IOPAD(0x834, PIN_INPUT | MUX_MODE3)
-                       AM33XX_IOPAD(0x838, PIN_INPUT | MUX_MODE3)
-                       AM33XX_IOPAD(0x83c, PIN_INPUT | MUX_MODE3)
-                       AM33XX_IOPAD(0x888, PIN_INPUT | MUX_MODE3)
-                       AM33XX_IOPAD(0x88c, PIN_INPUT | MUX_MODE3)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT, MUX_MODE3)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT, MUX_MODE3)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_INPUT, MUX_MODE3)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT, MUX_MODE3)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_INPUT, MUX_MODE3)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CLK, PIN_INPUT, MUX_MODE3)
                >;
        };
 
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x968, PIN_INPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x96c, PIN_OUTPUT | MUX_MODE0)
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 
        uart1_pins: pinmux_uart1 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0)
-                       AM33XX_IOPAD(0x97C, PIN_OUTPUT | MUX_MODE0)
-                       AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0)
-                       AM33XX_IOPAD(0x984, PIN_OUTPUT | MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT, MUX_MODE0)
                >;
        };
 
        uart2_pins: pinmux_uart2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1)
-                       AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE1)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE1)
                >;
        };
 
        uart4_pins: pinmux_uart4_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE6)
-                       AM33XX_IOPAD(0x874, PIN_OUTPUT_PULLUP | MUX_MODE6)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE6)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_OUTPUT_PULLUP, MUX_MODE6)
                >;
        };
 
        user_leds_s0: user_leds_s0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x820, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x824, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x82c, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x840, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x844, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x848, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x858, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x85c, PIN_OUTPUT_PULLUP | MUX_MODE7)
-                       AM33XX_IOPAD(0x860, PIN_INPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x864, PIN_INPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x868, PIN_INPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x86c, PIN_INPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x878, PIN_OUTPUT_PULLUP | MUX_MODE7)
-                       AM33XX_IOPAD(0x87c, PIN_INPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x894, PIN_INPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x958, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x95c, PIN_OUTPUT | MUX_MODE7)
-                       AM33XX_IOPAD(0x964, PIN_OUTPUT_PULLUP | MUX_MODE7)
-                       AM33XX_IOPAD(0x9a0, PIN_OUTPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x9a4, PIN_OUTPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x9a8, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLUP | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT_PULLUP, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_INPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_OUTPUT_PULLUP, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_INPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_ADVN_ALE, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_OEN_REN, PIN_INPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WEN, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN0_CLE, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_OUTPUT, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, PIN_OUTPUT_PULLUP, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_OUTPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLUP, MUX_MODE7)
                >;
        };
 };
index 38d57b8..1ac0c8a 100644 (file)
 
        audio_pins: pinmux_audio_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* mcasp0_ahcklx.mcasp0_ahclkx */
-                       AM33XX_IOPAD(0x994, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* mcasp0_fsx.mcasp0_fsx */
-                       AM33XX_IOPAD(0x990, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* mcasp0_aclkx.mcasp0_aclkx */
-                       AM33XX_IOPAD(0x998, PIN_INPUT_PULLDOWN | MUX_MODE0)     /* mcasp0_axr0.mcasp0_axr0 */
-                       AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mcasp0_ahclkr.mcasp0_axr2 */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
                >;
        };
 
        audio_pa_pins: pinmux_audio_pa_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* SoundPA_en - mcasp0_aclkr.gpio3_18 */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_INPUT_PULLDOWN, MUX_MODE7)  /* SoundPA_en - mcasp0_aclkr.gpio3_18 */
                >;
        };
 
        audio_mclk_pins: pinmux_audio_mclk_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_a11.gpio1_27 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* gpmc_a11.gpio1_27 */
                >;
        };
 
        backlight0_pins: pinmux_backlight0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE7)     /* gpmc_wen.gpio2_4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WEN, PIN_OUTPUT, MUX_MODE7)      /* gpmc_wen.gpio2_4 */
                >;
        };
 
        backlight1_pins: pinmux_backlight1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE7)     /* gpmc_ad10.gpio0_26 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT, MUX_MODE7)     /* gpmc_ad10.gpio0_26 */
                >;
        };
 
        lcd_pins: pinmux_lcd_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data0.lcd_data0 */
-                       AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data1.lcd_data1 */
-                       AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data2.lcd_data2 */
-                       AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)     /* lcd_data3.lcd_data3 */
-                       AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data4.lcd_data4 */
-                       AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data5.lcd_data5 */
-                       AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data6.lcd_data6 */
-                       AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)     /* lcd_data7.lcd_data7 */
-                       AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data8.lcd_data8 */
-                       AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data9.lcd_data9 */
-                       AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data10.lcd_data10 */
-                       AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)     /* lcd_data11.lcd_data11 */
-                       AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)     /* lcd_data12.lcd_data12 */
-                       AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)     /* lcd_data13.lcd_data13 */
-                       AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)     /* lcd_data14.lcd_data14 */
-                       AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)     /* lcd_data15.lcd_data15 */
-                       AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* lcd_vsync.lcd_vsync */
-                       AM33XX_IOPAD(0x8e4, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* lcd_hsync.lcd_hsync */
-                       AM33XX_IOPAD(0x8e8, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* lcd_pclk.lcd_pclk */
-                       AM33XX_IOPAD(0x8ec, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* lcd_ac_bias_en.lcd_ac_bias_en */
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        led_pins: pinmux_led_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE7)     /* gpmc_a5.gpio1_21 */
-                       AM33XX_IOPAD(0x858, PIN_OUTPUT | MUX_MODE7)     /* gpmc_a6.gpio1_22 */
-                       AM33XX_IOPAD(0x85c, PIN_OUTPUT | MUX_MODE7)     /* gpmc_a7.gpio1_23 */
-                       AM33XX_IOPAD(0x860, PIN_OUTPUT | MUX_MODE7)     /* gpmc_a8.gpio1_24 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT, MUX_MODE7)       /* gpmc_a5.gpio1_21 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT, MUX_MODE7)       /* gpmc_a6.gpio1_22 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT, MUX_MODE7)       /* gpmc_a7.gpio1_23 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT, MUX_MODE7)       /* gpmc_a8.gpio1_24 */
                >;
        };
 
        uart0_pins: pinmux_uart0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        uart1_pins: pinmux_uart1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart1_rxd.uart1_rxd */
-                       AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart1_txd.uart1_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        uart4_pins: pinmux_uart4_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE6)       /* gpmc_wait0.uart4_rxd */
-                       AM33XX_IOPAD(0x874, PIN_OUTPUT_PULLDOWN | MUX_MODE6)    /* gpmc_wpn.uart4_txd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE6)      /* gpmc_wait0.uart4_rxd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_OUTPUT_PULLDOWN, MUX_MODE6)     /* gpmc_wpn.uart4_txd */
                >;
        };
 
        i2c0_pins: pinmux_i2c0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_sda.i2c0_sda */
-                       AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)       /* i2c0_scl.i2c0_scl */
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        i2c2_pins: pinmux_i2c2_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE3)       /* uart1_ctsn.i2c2_sda */
-                       AM33XX_IOPAD(0x97c, PIN_INPUT_PULLUP | MUX_MODE3)       /* uart1_rtsn.i2c2_scl */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3)      /* uart1_ctsn.i2c2_sda */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLUP, MUX_MODE3)      /* uart1_rtsn.i2c2_scl */
                >;
        };
 
        cpsw_default: cpsw_default {
                pinctrl-single,pins = <
                        /* Slave 1 */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxerr.mii1_rxerr */
-                       AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* mii1_txen.mii1_txen */
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxdv.mii1_rxdv */
-                       AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* mii1_txd3.mii1_txd3 */
-                       AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* mii1_txd2.mii1_txd2 */
-                       AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* mii1_txd1.mii1_txd1 */
-                       AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* mii1_txd0.mii1_txd0 */
-                       AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_txclk.mii1_txclk */
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxclk.mii1_rxclk */
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxd3.mii1_rxd3 */
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxd2.mii1_rxd2 */
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxd1.mii1_rxd1 */
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE0)       /* mii1_rxd0.mii1_rxd0 */
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLUP, MUX_MODE0)
                >;
        };
 
        cpsw_sleep: cpsw_sleep {
                pinctrl-single,pins = <
                        /* Slave 1 reset value */
-                       AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        davinci_mdio_default: davinci_mdio_default {
                pinctrl-single,pins = <
                        /* MDIO */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)       /* mdio_data.mdio_data */
-                       AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)                      /* mdio_clk.mdio_clk */
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
                        /* Ethernet */
-                       AM33XX_IOPAD(0x838, PIN_INPUT_PULLUP | MUX_MODE7)       /* Ethernet_nRST - gpmc_ad14.gpio1_14 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_INPUT_PULLUP, MUX_MODE7)       /* Ethernet_nRST - gpmc_ad14.gpio1_14 */
                >;
        };
 
        davinci_mdio_sleep: davinci_mdio_sleep {
                pinctrl-single,pins = <
                        /* MDIO reset value */
-                       AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
+                       AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
                >;
        };
 
        mmc1_pins: pinmux_mmc1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x96c, PIN_INPUT | MUX_MODE7)              /* uart0_rtsn.gpio1_9 */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT, MUX_MODE7)             /* uart0_rtsn.gpio1_9 */
                >;
        };
 
        emmc_pwrseq_pins: pinmux_emmc_pwrseq_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* gpmc_a4.gpio1_20 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT_PULLUP, MUX_MODE7)        /* gpmc_a4.gpio1_20 */
                >;
        };
 
        emmc_pins: pinmux_emmc_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2)       /* gpmc_csn1.mmc1_clk */
-                       AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2)       /* gpmc_csn2.mmc1_cmd */
-                       AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad0.mmc1_dat0 */
-                       AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad1.mmc1_dat1 */
-                       AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad2.mmc1_dat2 */
-                       AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad3.mmc1_dat3 */
-                       AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad4.mmc1_dat4 */
-                       AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad5.mmc1_dat5 */
-                       AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad6.mmc1_dat6 */
-                       AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1)       /* gpmc_ad7.mmc1_dat7 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2)       /* gpmc_csn1.mmc1_clk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2)       /* gpmc_csn2.mmc1_cmd */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad0.mmc1_dat0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad1.mmc1_dat1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad2.mmc1_dat2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad3.mmc1_dat3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad4.mmc1_dat4 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad5.mmc1_dat5 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad6.mmc1_dat6 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE1)        /* gpmc_ad7.mmc1_dat7 */
                >;
        };
 
        ehrpwm1_pins: pinmux_ehrpwm1a_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x848, PIN_OUTPUT | MUX_MODE6)     /* gpmc_a2.ehrpwm1a */
-                       AM33XX_IOPAD(0x84c, PIN_OUTPUT | MUX_MODE6)     /* gpmc_a3.ehrpwm1b */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT, MUX_MODE6)       /* gpmc_a2.ehrpwm1a */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_OUTPUT, MUX_MODE6)       /* gpmc_a3.ehrpwm1b */
                >;
        };
 
        rtc0_irq_pins: pinmux_rtc0_irq_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x824, PIN_INPUT_PULLUP | MUX_MODE7)     /* gpmc_ad9.gpio0_23 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_INPUT_PULLUP, MUX_MODE7)     /* gpmc_ad9.gpio0_23 */
                >;
        };
 
        spi0_pins: pinmux_spi0_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0)       /* SPI0_MOSI - spi0_d0.spi0_d0 */
-                       AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0)       /* SPI0_MISO - spi0_d1.spi0_d1 */
-                       AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0)       /* SPI0_CLK  - spi0_clk.spi0_clk */
-                       AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0)       /* SPI0_CS0 (NBATTSS) - spi0_cs0.spi0_cs0 */
-                       AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE0)       /* SPI0_CS1 (FPGA_FLASH_NCS) - spi0_cs1.spi0_cs1 */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLUP, MUX_MODE0) /* SPI0_MOSI */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE0) /* SPI0_MISO */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE0)        /* SPI0_CS0 (NBATTSS) */
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT_PULLUP, MUX_MODE0)        /* SPI0_CS1 (FPGA_FLASH_NCS) */
                >;
        };
 
        lwb_pins: pinmux_lwb_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x830, PIN_INPUT_PULLUP | MUX_MODE7)       /* nKbdInt - gpmc_ad12.gpio1_12 */
-                       AM33XX_IOPAD(0x834, PIN_INPUT_PULLUP | MUX_MODE7)       /* nKbdReset - gpmc_ad13.gpio1_13 */
-                       AM33XX_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE7)       /* USB1_enPower - gpmc_a1.gpio1_17 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLUP, MUX_MODE7)       /* nKbdInt - gpmc_ad12.gpio1_12 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLUP, MUX_MODE7)       /* nKbdReset - gpmc_ad13.gpio1_13 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLUP, MUX_MODE7) /* USB1_enPower - gpmc_a1.gpio1_17 */
                        /* PDI Bus - Battery system */
-                       AM33XX_IOPAD(0x840, PIN_INPUT_PULLUP | MUX_MODE7)       /* nBattReset  gpmc_a0.gpio1_16 */
-                       AM33XX_IOPAD(0x83c, PIN_INPUT_PULLUP | MUX_MODE7)       /* BattPDIData gpmc_ad15.gpio1_15 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_INPUT_PULLUP, MUX_MODE7) /* nBattReset  gpmc_a0.gpio1_16 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLUP, MUX_MODE7)       /* BattPDIData gpmc_ad15.gpio1_15 */
                        /* FPGA */
-                       AM33XX_IOPAD(0x820, PIN_INPUT_PULLUP | MUX_MODE7)       /* FPGA_DONE - gpmc_ad8.gpio0_22 */
-                       AM33XX_IOPAD(0x840, PIN_INPUT_PULLUP | MUX_MODE7)       /* FPGA_NRST - gpmc_a0.gpio1_16 */
-                       AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* FPGA_RUN - gpmc_a1.gpio1_17 */
-                       AM33XX_IOPAD(0x864, PIN_INPUT_PULLUP | MUX_MODE7)       /* ENFPGA - gpmc_a9.gpio1_25 */
-                       AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* FPGA_PROGRAM - gpmc_a10.gpio1_26 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_INPUT_PULLUP, MUX_MODE7)        /* FPGA_DONE - gpmc_ad8.gpio0_22 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_INPUT_PULLUP, MUX_MODE7) /* FPGA_NRST - gpmc_a0.gpio1_16 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE7)       /* FPGA_RUN - gpmc_a1.gpio1_17 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLUP, MUX_MODE7) /* ENFPGA - gpmc_a9.gpio1_25 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE7)      /* FPGA_PROGRAM - gpmc_a10.gpio1_26 */
                >;
        };
 };
index 8ce5417..b7d28a2 100644 (file)
 &am33xx_pinmux {
        mcasp0_pins: pinmux_mcasp0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9AC, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_ahclkx.mcasp0_ahclkx */
-                       AM33XX_IOPAD(0x990, PIN_INPUT_PULLDOWN | MUX_MODE0)  /* mcasp0_aclkx.mcasp0_aclkx */
-                       AM33XX_IOPAD(0x994, PIN_INPUT_PULLDOWN | MUX_MODE0)  /* mcasp0_fsx.mcasp0_fsx */
-                       AM33XX_IOPAD(0x998, PIN_INPUT_PULLDOWN | MUX_MODE0)  /* mcasp0_axr0.mcasp0_axr0 */
-                       AM33XX_IOPAD(0x9A8, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_axr1.mcasp0_axr1 */
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_INPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR1, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 };
@@ -84,8 +84,8 @@
 &am33xx_pinmux {
        dcan1_pins: pinmux_dcan1 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x968, PIN_OUTPUT_PULLUP | MUX_MODE2) /* uart0_ctsn.d_can1_tx */
-                       AM33XX_IOPAD(0x96c, PIN_INPUT_PULLUP | MUX_MODE2) /* uart0_rtsn.d_can1_rx */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT_PULLUP, MUX_MODE2) /* uart0_ctsn.d_can1_tx */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLUP, MUX_MODE2) /* uart0_rtsn.d_can1_rx */
                >;
        };
 };
 &am33xx_pinmux {
        ethernet1_pins: pinmux_ethernet1 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x840, PIN_OUTPUT | MUX_MODE1)             /* gpmc_a0.mii2_txen */
-                       AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* gpmc_a1.mii2_rxdv */
-                       AM33XX_IOPAD(0x848, PIN_OUTPUT | MUX_MODE1)             /* gpmc_a2.mii2_txd3 */
-                       AM33XX_IOPAD(0x84c, PIN_OUTPUT | MUX_MODE1)             /* gpmc_a3.mii2_txd2 */
-                       AM33XX_IOPAD(0x850, PIN_OUTPUT | MUX_MODE1)             /* gpmc_a4.mii2_txd1 */
-                       AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE1)             /* gpmc_a5.mii2_txd0 */
-                       AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* gpmc_a6.mii2_txclk */
-                       AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* gpmc_a7.mii2_rxclk */
-                       AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* gpmc_a8.mii2_rxd3 */
-                       AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* gpmc_a9.mii2_rxd2 */
-                       AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* gpmc_a10.mii2_rxd1 */
-                       AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* gpmc_a11.mii2_rxd0 */
-                       AM33XX_IOPAD(0x874, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* gpmc_wpn.mii2_rxerr */
-                       AM33XX_IOPAD(0x878, PIN_INPUT_PULLDOWN | MUX_MODE1)     /* gpmc_ben1.mii2_col */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_OUTPUT, MUX_MODE1)               /* gpmc_a0.mii2_txen */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT_PULLDOWN, MUX_MODE1)       /* gpmc_a1.mii2_rxdv */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT, MUX_MODE1)               /* gpmc_a2.mii2_txd3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_OUTPUT, MUX_MODE1)               /* gpmc_a3.mii2_txd2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_OUTPUT, MUX_MODE1)               /* gpmc_a4.mii2_txd1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT, MUX_MODE1)               /* gpmc_a5.mii2_txd0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_INPUT_PULLDOWN, MUX_MODE1)       /* gpmc_a6.mii2_txclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_INPUT_PULLDOWN, MUX_MODE1)       /* gpmc_a7.mii2_rxclk */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_INPUT_PULLDOWN, MUX_MODE1)       /* gpmc_a8.mii2_rxd3 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLDOWN, MUX_MODE1)       /* gpmc_a9.mii2_rxd2 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLDOWN, MUX_MODE1)      /* gpmc_a10.mii2_rxd1 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLDOWN, MUX_MODE1)      /* gpmc_a11.mii2_rxd0 */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_INPUT_PULLDOWN, MUX_MODE1)      /* gpmc_wpn.mii2_rxerr */
+                       AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT_PULLDOWN, MUX_MODE1)     /* gpmc_ben1.mii2_col */
                >;
        };
 };
 &am33xx_pinmux {
        mmc1_pins: pinmux_mmc1 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat3.mmc0_dat3 */
-                       AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat2.mmc0_dat2 */
-                       AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat1.mmc0_dat1 */
-                       AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_dat0.mmc0_dat0 */
-                       AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_clk.mmc0_clk */
-                       AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)       /* mmc0_cmd.mmc0_cmd */
-                       AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE7)       /* spi0_cs1.mmc0_sdcd */
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT2, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT1, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT_PULLUP, MUX_MODE7)        /* spi0_cs1.mmc0_sdcd */
                >;
        };
 };
 &am33xx_pinmux {
        uart0_pins: pinmux_uart0 {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)    /* uart0_rxd.uart0_rxd */
-                       AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
+                       AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 
        uart1_pins: pinmux_uart1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart1_rxd.uart1_rxd */
-                       AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart1_txd.uart1_txd */
-                       AM33XX_IOPAD(0x978, PIN_INPUT | MUX_MODE0)              /* uart1_ctsn.uart1_ctsn */
-                       AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart1_rtsn.uart1_rtsn */
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT, MUX_MODE0)
+                       AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
                >;
        };
 };
index 9dfd80e..9b8b132 100644 (file)
@@ -80,6 +80,7 @@
                pinctrl-names = "default", "sleep";
                pinctrl-0 = <&matrix_keypad_default>;
                pinctrl-1 = <&matrix_keypad_sleep>;
+               wakeup-source;
 
                row-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH         /* Bank0, pin12 */
                             &gpio0 13 GPIO_ACTIVE_HIGH         /* Bank0, pin13 */
                        regulator-name = "vdcdc3";
                        regulator-boot-on;
                        regulator-always-on;
+                       regulator-state-mem {
+                               regulator-on-in-suspend;
+                       };
+                       regulator-state-disk {
+                               regulator-off-in-suspend;
+                       };
                };
 
                dcdc4: regulator-dcdc4 {
                        regulator-name = "v1_0bat";
                        regulator-min-microvolt = <1000000>;
                        regulator-max-microvolt = <1000000>;
+                       regulator-boot-on;
+                       regulator-always-on;
                };
 
                dcdc6: regulator-dcdc6 {
                        regulator-name = "v1_8bat";
                        regulator-min-microvolt = <1800000>;
                        regulator-max-microvolt = <1800000>;
+                       regulator-boot-on;
+                       regulator-always-on;
                };
 
                ldo1: regulator-ldo1 {
diff --git a/arch/arm/boot/dts/am5718.dtsi b/arch/arm/boot/dts/am5718.dtsi
new file mode 100644 (file)
index 0000000..d51007c
--- /dev/null
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include "dra72x.dtsi"
+
+/ {
+       compatible = "ti,am5718", "ti,dra7";
+};
+
+/*
+ * These modules are not present on AM5718
+ *
+ * ATL
+ * VCP1, VCP2
+ * MLB
+ * ISS
+ * USB3, USB4
+ */
+
+&usb3_tm {
+       status = "disabled";
+};
+
+&usb4_tm {
+       status = "disabled";
+};
+
+&atl_tm {
+       status = "disabled";
+};
index 6432309..66116ad 100644 (file)
@@ -7,7 +7,7 @@
  */
 /dts-v1/;
 
-#include "dra72x.dtsi"
+#include "am5718.dtsi"
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include "dra7-mmc-iodelay.dtsi"
diff --git a/arch/arm/boot/dts/am5728.dtsi b/arch/arm/boot/dts/am5728.dtsi
new file mode 100644 (file)
index 0000000..82e5427
--- /dev/null
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include "dra74x.dtsi"
+
+/ {
+       compatible = "ti,am5728", "ti,dra7";
+};
+
+/*
+ * These modules are not present on AM5728
+ *
+ * EVE1, EVE2
+ * ATL
+ * VCP1, VCP2
+ * MLB
+ * ISS
+ * USB3, USB4
+ */
+
+&usb3_tm {
+       status = "disabled";
+};
+
+&usb4_tm {
+       status = "disabled";
+};
+
+&atl_tm {
+       status = "disabled";
+};
index b2fb6e0..4f83522 100644 (file)
@@ -8,15 +8,14 @@
 
 /dts-v1/;
 
-#include "dra74x.dtsi"
+#include "am5728.dtsi"
 #include "dra7-mmc-iodelay.dtsi"
 #include "dra74x-mmc-iodelay.dtsi"
 #include "am572x-idk-common.dtsi"
 
 / {
        model = "TI AM5728 IDK";
-       compatible = "ti,am5728-idk", "ti,am5728", "ti,dra742", "ti,dra74",
-                    "ti,dra7";
+       compatible = "ti,am5728-idk", "ti,am5728", "ti,dra7";
 };
 
 &mmc1 {
diff --git a/arch/arm/boot/dts/am5748.dtsi b/arch/arm/boot/dts/am5748.dtsi
new file mode 100644 (file)
index 0000000..5e12975
--- /dev/null
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include "dra76x.dtsi"
+
+/ {
+       compatible = "ti,am5748", "ti,dra762", "ti,dra7";
+};
+
+/*
+ * These modules are not present on AM5748
+ *
+ * EVE1, EVE2
+ * ATL
+ * VCP1, VCP2
+ * MLB
+ * ISS
+ * USB3, USB4
+ */
+
+&usb3_tm {
+       status = "disabled";
+};
+
+&usb4_tm {
+       status = "disabled";
+};
+
+&atl_tm {
+       status = "disabled";
+};
index 378dfa7..dc5141c 100644 (file)
@@ -6,14 +6,14 @@
 
 /dts-v1/;
 
-#include "dra76x.dtsi"
+#include "am5748.dtsi"
 #include "dra7-mmc-iodelay.dtsi"
 #include "dra76x-mmc-iodelay.dtsi"
 #include "am572x-idk-common.dtsi"
 
 / {
        model = "TI AM5748 IDK";
-       compatible = "ti,am5728-idk", "ti,dra762", "ti,dra7";
+       compatible = "ti,am5748-idk", "ti,am5748", "ti,dra762", "ti,dra7";
 };
 
 &qspi {
index 1e6620f..2341a56 100644 (file)
@@ -7,7 +7,7 @@
  */
 /dts-v1/;
 
-#include "dra74x.dtsi"
+#include "am5728.dtsi"
 #include "am57xx-commercial-grade.dtsi"
 #include "dra74x-mmc-iodelay.dtsi"
 #include <dt-bindings/gpio/gpio.h>
index 4748ce8..0460de0 100644 (file)
@@ -13,7 +13,7 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include "dra74x.dtsi"
+#include "am5728.dtsi"
 
 / {
        model = "CompuLab CL-SOM-AM57x";
index 96c1870..3f4bb44 100644 (file)
                                reg = <0x20300 0x34>, <0x20704 0x4>, <0x18260 0x4>;
                                clocks = <&coreclk 2>, <&refclk>;
                                clock-names = "nbclk", "fixed";
+                               interrupts-extended = <&gic GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
+                                                     <&gic GIC_SPI  9 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        cpurst: cpurst@20800 {
index 2375449..556ed46 100644 (file)
 
        chosen {
                stdout-path = &uart5;
-               bootargs = "console=ttyS4,115200 earlyprintk";
+               bootargs = "console=tty0 console=ttyS4,115200 earlyprintk";
        };
 
        memory@80000000 {
                reg = <0x80000000 0x20000000>;
        };
+
+       reserved-memory {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               gfx_memory: framebuffer {
+                       size = <0x01000000>;
+                       alignment = <0x01000000>;
+                       compatible = "shared-dma-pool";
+                       reusable;
+               };
+       };
 };
 
 &fmc {
@@ -27,6 +40,7 @@
                status = "okay";
                m25p,fast-read;
                label = "bmc";
+#include "openbmc-flash-layout.dtsi"
        };
 };
 
 &uhci {
        status = "okay";
 };
+
+&gfx {
+     status = "okay";
+     memory-region = <&gfx_memory>;
+};
index 9f194b5..43aba40 100644 (file)
        memory@80000000 {
                reg = <0x80000000 0x20000000>;
        };
+
+       ast-adc-hwmon {
+               compatible = "iio-hwmon";
+               io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 3>,
+                             <&adc 4>, <&adc 5>, <&adc 6>, <&adc 7>;
+       };
 };
 
 &pinctrl {
index 4c2dcac..c4521ed 100644 (file)
        status = "okay";
 };
 
+&vuart {
+       // VUART Host Console
+       status = "okay";
+};
+
 &uart1 {
        // Host Console
        status = "okay";
index b854ac0..b249da8 100644 (file)
@@ -32,9 +32,9 @@
                        no-map;
                };
 
-               flash_memory: region@98000000 {
+               flash_memory: region@5c000000 {
                        no-map;
-                       reg = <0x98000000 0x01000000>; /* 16MB */
+                       reg = <0x5C000000 0x02000000>; /* 32MB */
                };
        };
 
index 76fe994..418a198 100644 (file)
                        reg = <0x9ef00000 0x00100000>;
                        no-map;
                };
+
+               gfx_memory: framebuffer {
+                       size = <0x01000000>;
+                       alignment = <0x01000000>;
+                       compatible = "shared-dma-pool";
+                       reusable;
+               };
        };
 
        leds {
 
 &gfx {
        status = "okay";
+       memory-region = <&gfx_memory>;
 };
 
 &pinctrl {
index ad54117..f1356ca 100644 (file)
                        no-map;
                        reg = <0x98000000 0x04000000>; /* 64M */
                };
+
+               gfx_memory: framebuffer {
+                       size = <0x01000000>;
+                       alignment = <0x01000000>;
+                       compatible = "shared-dma-pool";
+                       reusable;
+               };
        };
 
        gpio-keys {
                status = "okay";
                label = "bmc";
                m25p,fast-read;
-#include "openbmc-flash-layout.dtsi"
+
+               partitions {
+                       #address-cells = < 1 >;
+                       #size-cells = < 1 >;
+                       compatible = "fixed-partitions";
+                       u-boot@0 {
+                               reg = < 0 0x60000 >;
+                               label = "u-boot";
+                       };
+                       u-boot-env@60000 {
+                               reg = < 0x60000 0x20000 >;
+                               label = "u-boot-env";
+                       };
+                       obmc-ubi@80000 {
+                               reg = < 0x80000 0x1F80000 >;
+                               label = "obmc-ubi";
+                       };
+               };
        };
 
        flash@1 {
                status = "okay";
-               label = "alt";
+               label = "alt-bmc";
                m25p,fast-read;
+
+               partitions {
+                       #address-cells = < 1 >;
+                       #size-cells = < 1 >;
+                       compatible = "fixed-partitions";
+                       u-boot@0 {
+                               reg = < 0 0x60000 >;
+                               label = "alt-u-boot";
+                       };
+                       u-boot-env@60000 {
+                               reg = < 0x60000 0x20000 >;
+                               label = "alt-u-boot-env";
+                       };
+                       obmc-ubi@80000 {
+                               reg = < 0x80000 0x1F80000 >;
+                               label = "alt-obmc-ubi";
+                       };
+               };
+
        };
 };
 
 
 &gfx {
        status = "okay";
+       memory-region = <&gfx_memory>;
 };
 
 &pinctrl {
 &adc {
        status = "okay";
 };
+
+&vhub {
+       status = "okay";
+};
index 9549f86..5d7050d 100644 (file)
                                clock-names = "PCLK";
                        };
 
+                       rtc: rtc@1e781000 {
+                               compatible = "aspeed,ast2400-rtc";
+                               reg = <0x1e781000 0x18>;
+                               status = "disabled";
+                       };
+
                        uart1: serial@1e783000 {
                                compatible = "ns16550a";
                                reg = <0x1e783000 0x20>;
index 85ed9db..4345c31 100644 (file)
                                compatible = "aspeed,ast2500-gfx", "syscon";
                                reg = <0x1e6e6000 0x1000>;
                                reg-io-width = <4>;
+                               clocks = <&syscon ASPEED_CLK_GATE_D1CLK>;
+                               resets = <&syscon ASPEED_RESET_CRT1>;
+                               status = "disabled";
+                               interrupts = <0x19>;
                        };
 
                        adc: adc@1e6e9000 {
                                status = "disabled";
                        };
 
+                       video: video@1e700000 {
+                               compatible = "aspeed,ast2500-video-engine";
+                               reg = <0x1e700000 0x1000>;
+                               clocks = <&syscon ASPEED_CLK_GATE_VCLK>,
+                                        <&syscon ASPEED_CLK_GATE_ECLK>;
+                               clock-names = "vclk", "eclk";
+                               interrupts = <7>;
+                               status = "disabled";
+                       };
+
                        sram: sram@1e720000 {
                                compatible = "mmio-sram";
                                reg = <0x1e720000 0x9000>;      // 36K
                                #interrupt-cells = <2>;
                        };
 
+                       rtc: rtc@1e781000 {
+                               compatible = "aspeed,ast2500-rtc";
+                               reg = <0x1e781000 0x18>;
+                               status = "disabled";
+                       };
+
                        timer: timer@1e782000 {
                                /* This timer is a Faraday FTTMR010 derivative */
                                compatible = "aspeed,ast2400-timer";
index 33a159c..7788d5d 100644 (file)
@@ -1,47 +1,10 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * at91-sama5d27_som1.dtsi - Device Tree file for SAMA5D27 SoM1 board
  *
  *  Copyright (c) 2017, Microchip Technology Inc.
  *                2017 Cristian Birsan <cristian.birsan@microchip.com>
  *                2017 Claudiu Beznea <claudiu.beznea@microchip.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 #include "sama5d2.dtsi"
 #include "sama5d2-pinfunc.h"
index a481805..89f0c99 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * at91-sama5d27_som1_ek.dts - Device Tree file for SAMA5D27-SOM1-EK board
  *
@@ -5,44 +6,6 @@
  *                2016 Nicolas Ferre <nicolas.ferre@atmel.com>
  *                2017 Cristian Birsan <cristian.birsan@microchip.com>
  *                2017 Claudiu Beznea <claudiu.beznea@microchip.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 /dts-v1/;
 #include "at91-sama5d27_som1.dtsi"
index fa54e88..808e399 100644 (file)
@@ -1,52 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * at91-sama5d2_xplained.dts - Device Tree file for SAMA5D2 Xplained board
  *
  *  Copyright (C) 2015 Atmel,
  *                2015 Nicolas Ferre <nicolas.ferre@atmel.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 /dts-v1/;
 #include "sama5d2.dtsi"
 #include "sama5d2-pinfunc.h"
 #include <dt-bindings/mfd/atmel-flexcom.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/regulator/active-semi,8945a-regulator.h>
 
 / {
        model = "Atmel SAMA5D2 Xplained";
                                                        regulator-name = "VDD_1V35";
                                                        regulator-min-microvolt = <1350000>;
                                                        regulator-max-microvolt = <1350000>;
+                                                       regulator-allowed-modes = <ACT8945A_REGULATOR_MODE_FIXED>,
+                                                                                 <ACT8945A_REGULATOR_MODE_LOWPOWER>;
+                                                       regulator-initial-mode = <ACT8945A_REGULATOR_MODE_FIXED>;
                                                        regulator-always-on;
+
+                                                       regulator-state-mem {
+                                                               regulator-on-in-suspend;
+                                                               regulator-suspend-min-microvolt=<1400000>;
+                                                               regulator-suspend-max-microvolt=<1400000>;
+                                                               regulator-changeable-in-suspend;
+                                                               regulator-mode=<ACT8945A_REGULATOR_MODE_LOWPOWER>;
+                                                       };
                                                };
 
                                                vdd_1v2_reg: REG_DCDC2 {
                                                        regulator-name = "VDD_1V2";
                                                        regulator-min-microvolt = <1100000>;
                                                        regulator-max-microvolt = <1300000>;
+                                                       regulator-allowed-modes = <ACT8945A_REGULATOR_MODE_FIXED>,
+                                                                                 <ACT8945A_REGULATOR_MODE_LOWPOWER>;
+                                                       regulator-initial-mode = <ACT8945A_REGULATOR_MODE_FIXED>;
                                                        regulator-always-on;
+
+                                                       regulator-state-mem {
+                                                               regulator-off-in-suspend;
+                                                       };
                                                };
 
                                                vdd_3v3_reg: REG_DCDC3 {
                                                        regulator-name = "VDD_3V3";
                                                        regulator-min-microvolt = <3300000>;
                                                        regulator-max-microvolt = <3300000>;
+                                                       regulator-allowed-modes = <ACT8945A_REGULATOR_MODE_FIXED>,
+                                                                                 <ACT8945A_REGULATOR_MODE_LOWPOWER>;
+                                                       regulator-initial-mode = <ACT8945A_REGULATOR_MODE_FIXED>;
                                                        regulator-always-on;
+
+                                                       regulator-state-mem {
+                                                               regulator-off-in-suspend;
+                                                       };
                                                };
 
                                                vdd_fuse_reg: REG_LDO1 {
                                                        regulator-name = "VDD_FUSE";
                                                        regulator-min-microvolt = <2500000>;
                                                        regulator-max-microvolt = <2500000>;
+                                                       regulator-allowed-modes = <ACT8945A_REGULATOR_MODE_NORMAL>,
+                                                                                 <ACT8945A_REGULATOR_MODE_LOWPOWER>;
+                                                       regulator-initial-mode = <ACT8945A_REGULATOR_MODE_NORMAL>;
                                                        regulator-always-on;
+
+                                                       regulator-state-mem {
+                                                               regulator-off-in-suspend;
+                                                       };
                                                };
 
                                                vdd_3v3_lp_reg: REG_LDO2 {
                                                        regulator-name = "VDD_3V3_LP";
                                                        regulator-min-microvolt = <3300000>;
                                                        regulator-max-microvolt = <3300000>;
+                                                       regulator-allowed-modes = <ACT8945A_REGULATOR_MODE_NORMAL>,
+                                                                                 <ACT8945A_REGULATOR_MODE_LOWPOWER>;
+                                                       regulator-initial-mode = <ACT8945A_REGULATOR_MODE_NORMAL>;
                                                        regulator-always-on;
+
+                                                       regulator-state-mem {
+                                                               regulator-off-in-suspend;
+                                                       };
                                                };
 
                                                vdd_led_reg: REG_LDO3 {
                                                        regulator-name = "VDD_LED";
                                                        regulator-min-microvolt = <3300000>;
                                                        regulator-max-microvolt = <3300000>;
+                                                       regulator-allowed-modes = <ACT8945A_REGULATOR_MODE_NORMAL>,
+                                                                                 <ACT8945A_REGULATOR_MODE_LOWPOWER>;
+                                                       regulator-initial-mode = <ACT8945A_REGULATOR_MODE_NORMAL>;
                                                        regulator-always-on;
+
+                                                       regulator-state-mem {
+                                                               regulator-off-in-suspend;
+                                                       };
                                                };
 
                                                vdd_sdhc_1v8_reg: REG_LDO4 {
                                                        regulator-name = "VDD_SDHC_1V8";
                                                        regulator-min-microvolt = <1800000>;
                                                        regulator-max-microvolt = <1800000>;
+                                                       regulator-allowed-modes = <ACT8945A_REGULATOR_MODE_NORMAL>,
+                                                                                 <ACT8945A_REGULATOR_MODE_LOWPOWER>;
+                                                       regulator-initial-mode = <ACT8945A_REGULATOR_MODE_NORMAL>;
                                                        regulator-always-on;
+
+                                                       regulator-state-mem {
+                                                               regulator-off-in-suspend;
+                                                       };
                                                };
                                        };
 
index 43aef56..fdfc37d 100644 (file)
@@ -1,46 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * at91-sama5d4_xplained.dts - Device Tree file for SAMA5D4 Xplained board
  *
  *  Copyright (C) 2015 Atmel,
  *                2015 Josh Wu <josh.wu@atmel.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 /dts-v1/;
 #include "sama5d4.dtsi"
index 12d5af9..0cc1cff 100644 (file)
@@ -1,46 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * at91-sama5d4ek.dts - Device Tree file for SAMA5D4 Evaluation Kit
  *
  *  Copyright (C) 2014 Atmel,
  *                2014 Nicolas Ferre <nicolas.ferre@atmel.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 /dts-v1/;
 #include "sama5d4.dtsi"
index 4302772..15050fd 100644 (file)
@@ -1,47 +1,10 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for VInCo platform
  *
  *  Copyright (C) 2014 Atmel,
  *                2014 Nicolas Ferre <nicolas.ferre@atmel.com>
  *   2015 Gregory CLEMENT <gregory.clement@free-electrons.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 /dts-v1/;
 #include "sama5d4.dtsi"
index 07d1b57..81f808a 100644 (file)
@@ -1,46 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for Atmel at91sam9260 Evaluation Kit
  *
  *  Copyright (C) 2016 Atmel,
  *               2016 Nicolas Ferre <nicolas.ferre@atmel.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 /dts-v1/;
 #include "at91sam9260.dtsi"
index 1304452..3f9d8ca 100644 (file)
@@ -1,46 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * at91sam9xe.dtsi - Device Tree Include file for AT91SAM9XE family SoC
  *
  *  Copyright (C) 2015 Atmel,
  *                2015 Alexandre Belloni <alexandre.Belloni@free-electrons.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 #include "at91sam9260.dtsi"
index bd83962..1dfeece 100644 (file)
                        status = "disabled";
                };
        };
+
+       usb_power_supply: usb-power-supply {
+               compatible = "x-powers,axp813-usb-power-supply";
+       };
 };
index 414f1cd..fe9f0bc 100644 (file)
                        ranges = <0x0 0x3a000 0x1000>;
                };
 
-               target-module@3c000 {                   /* 0x4843c000, ap 23 08.0 */
+               atl_tm: target-module@3c000 {           /* 0x4843c000, ap 23 08.0 */
                        compatible = "ti,sysc-omap4", "ti,sysc";
                        reg = <0x3c000 0x4>;
                        reg-names = "rev";
                        };
                };
 
-               target-module@100000 {                  /* 0x48900000, ap 85 04.0 */
+               usb3_tm: target-module@100000 {         /* 0x48900000, ap 85 04.0 */
                        compatible = "ti,sysc-omap4", "ti,sysc";
                        ti,hwmods = "usb_otg_ss3";
                        reg = <0x100000 0x4>,
                        };
                };
 
-               target-module@140000 {                  /* 0x48940000, ap 75 3c.0 */
+               usb4_tm: target-module@140000 {         /* 0x48940000, ap 75 3c.0 */
                        compatible = "ti,sysc-omap4", "ti,sysc";
                        ti,hwmods = "usb_otg_ss4";
                        reg = <0x140000 0x4>,
index 2bc9add..d87e932 100644 (file)
                                ti,hwmods = "pcie1";
                                phys = <&pcie1_phy>;
                                phy-names = "pcie-phy0";
+                               ti,syscon-lane-sel = <&scm_conf_pcie 0x18>;
                                interrupt-map-mask = <0 0 0 7>;
                                interrupt-map = <0 0 0 1 &pcie1_intc 1>,
                                                <0 0 0 2 &pcie1_intc 2>,
                                phys = <&pcie1_phy>;
                                phy-names = "pcie-phy0";
                                ti,syscon-unaligned-access = <&scm_conf1 0x14 1>;
+                               ti,syscon-lane-sel = <&scm_conf_pcie 0x18>;
                                status = "disabled";
                        };
                };
index 1bb8e5c..abfff54 100644 (file)
@@ -25,7 +25,7 @@
        };
 
        chosen {
-               bootargs = "ignore_loglevel root=/dev/nfs ip=dhcp";
+               bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
                stdout-path = "serial1:115200n8";
        };
 
index 5892a9f..8ce3a77 100644 (file)
                };
        };
 
-       soc: soc {
-               compatible = "simple-bus";
+       fixed-rate-clocks {
                #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               fixed-rate-clocks {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               #size-cells = <0>;
 
-                       xusbxti: clock@0 {
-                               compatible = "fixed-clock";
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               reg = <0>;
-                               clock-frequency = <0>;
-                               #clock-cells = <0>;
-                               clock-output-names = "xusbxti";
-                       };
+               xusbxti: clock@0 {
+                       compatible = "fixed-clock";
+                       reg = <0>;
+                       clock-frequency = <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "xusbxti";
+               };
 
-                       xxti: clock@1 {
-                               compatible = "fixed-clock";
-                               reg = <1>;
-                               clock-frequency = <0>;
-                               #clock-cells = <0>;
-                               clock-output-names = "xxti";
-                       };
+               xxti: clock@1 {
+                       compatible = "fixed-clock";
+                       reg = <1>;
+                       clock-frequency = <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "xxti";
+               };
 
-                       xtcxo: clock@2 {
-                               compatible = "fixed-clock";
-                               reg = <2>;
-                               clock-frequency = <0>;
-                               #clock-cells = <0>;
-                               clock-output-names = "xtcxo";
-                       };
+               xtcxo: clock@2 {
+                       compatible = "fixed-clock";
+                       reg = <2>;
+                       clock-frequency = <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "xtcxo";
                };
+       };
+
+       pmu {
+               compatible = "arm,cortex-a7-pmu";
+               interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       soc: soc {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
 
                sysram@2020000 {
                        compatible = "mmio-sram";
                        status = "disabled";
                };
 
-               pmu {
-                       compatible = "arm,cortex-a7-pmu";
-                       interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
-               };
-
                ppmu_dmc0: ppmu_dmc0@106a0000 {
                        compatible = "samsung,exynos-ppmu";
                        reg = <0x106a0000 0x2000>;
index 6085e92..36ccf22 100644 (file)
                serial3 = &serial_3;
        };
 
+       pmu: pmu {
+               compatible = "arm,cortex-a9-pmu";
+               interrupt-parent = <&combiner>;
+               interrupts = <2 2>, <3 2>;
+       };
+
        soc: soc {
                compatible = "simple-bus";
                #address-cells = <1>;
                        reg = <0x10440000 0x1000>;
                };
 
-               pmu: pmu {
-                       compatible = "arm,cortex-a9-pmu";
-                       interrupt-parent = <&combiner>;
-                       interrupts = <2 2>, <3 2>;
-               };
-
                sys_reg: syscon@10010000 {
                        compatible = "samsung,exynos4-sysreg", "syscon";
                        reg = <0x10010000 0x400>;
                        status = "disabled";
                };
 
-               amba {
+               amba: amba {
                        #address-cells = <1>;
                        #size-cells = <1>;
                        compatible = "simple-bus";
index dd9ec05..36b1ede 100644 (file)
@@ -30,8 +30,8 @@
        };
 
        chosen {
-               bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
-               stdout-path = &serial_2;
+               bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M init=/linuxrc";
+               stdout-path = "serial2:115200n8";
        };
 
        mmc_reg: voltage-regulator {
index 7a3e621..77fc11e 100644 (file)
@@ -26,8 +26,8 @@
        };
 
        chosen {
-               bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc";
-               stdout-path = &serial_1;
+               bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M init=/linuxrc";
+               stdout-path = "serial1:115200n8";
        };
 
        fixed-rate-clocks {
index 8dbc47d..6882480 100644 (file)
@@ -26,8 +26,8 @@
        };
 
        chosen {
-               bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rootwait earlyprintk panic=5";
-               stdout-path = &serial_2;
+               bootargs = "root=/dev/mmcblk0p5 rootwait earlyprintk panic=5";
+               stdout-path = "serial2:115200n8";
        };
 
        regulators {
index 5c3d986..bf092e9 100644 (file)
@@ -24,8 +24,8 @@
        };
 
        chosen {
-               bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rw rootwait earlyprintk panic=5 maxcpus=1";
-               stdout-path = &serial_2;
+               bootargs = "root=/dev/mmcblk0p5 rw rootwait earlyprintk panic=5 maxcpus=1";
+               stdout-path = "serial2:115200n8";
        };
 
 
        };
 };
 
+&amba {
+       mdma0: mdma@12840000 {
+               compatible = "arm,pl330", "arm,primecell";
+               reg = <0x12840000 0x1000>;
+               interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&clock CLK_MDMA>;
+               clock-names = "apb_pclk";
+               #dma-cells = <1>;
+               #dma-channels = <8>;
+               #dma-requests = <1>;
+               power-domains = <&pd_lcd0>;
+       };
+};
+
 &camera {
        status = "okay";
 
 };
 
 &mdma1 {
-       reg = <0x12840000 0x1000>;
+       /* Use the secure mdma0 */
+       status = "disabled";
 };
 
 &mixer {
index 2bdf899..96d9988 100644 (file)
@@ -34,8 +34,6 @@
        fan0: pwm-fan {
                compatible = "pwm-fan";
                pwms = <&pwm 0 10000 0>;
-               cooling-min-state = <0>;
-               cooling-max-state = <3>;
                #cooling-cells = <2>;
                cooling-levels = <0 102 170 230>;
        };
        };
 };
 
+&adc {
+       vdd-supply = <&ldo10_reg>;
+       /* Nothing connected to ADC inputs, keep it disabled */
+};
+
 /* Supply for LAN9730/SMSC95xx */
 &buck8_reg {
        regulator-name = "BUCK8_P3V3";
index 346f719..698de43 100644 (file)
@@ -25,8 +25,7 @@
        };
 
        chosen {
-               bootargs ="console=ttySAC2,115200";
-               stdout-path = &serial_2;
+               stdout-path = "serial2:115200n8";
        };
 
        firmware@203f000 {
index 5c5c288..e70fb6e 100644 (file)
@@ -23,8 +23,8 @@
        };
 
        chosen {
-               bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc";
-               stdout-path = &serial_1;
+               bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M init=/linuxrc";
+               stdout-path = "serial1:115200n8";
        };
 
        fixed-rate-clocks {
index 327ee98..aac5339 100644 (file)
@@ -22,6 +22,7 @@
        };
 
        chosen {
-               bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rootwait earlyprintk panic=5";
+               bootargs = "root=/dev/mmcblk0p5 rootwait earlyprintk panic=5";
+               stdout-path = "serial2:115200n8";
        };
 };
index 26ad6ab..e5c041e 100644 (file)
                };
 
                adc: adc@126c0000 {
-                       compatible = "samsung,exynos-adc-v1";
+                       compatible = "samsung,exynos4212-adc";
                        reg = <0x126C0000 0x100>;
                        interrupt-parent = <&combiner>;
                        interrupts = <10 3>;
index d5e6618..6dc9694 100644 (file)
@@ -24,7 +24,8 @@
        };
 
        chosen {
-               bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
+               bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M init=/linuxrc";
+               stdout-path = "serial2:115200n8";
        };
 
        vdd: fixed-regulator-vdd {
index 80986b9..d5e0392 100644 (file)
                };
        };
 
+       pmu {
+               compatible = "arm,cortex-a15-pmu";
+               interrupt-parent = <&combiner>;
+               interrupts = <1 2>, <22 4>;
+       };
+
        soc: soc {
                sysram@2020000 {
                        compatible = "mmio-sram";
                        power-domains = <&pd_mau>;
                };
 
-               timer {
-                       compatible = "arm,armv7-timer";
-                       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)>;
-                       /*
-                        * Unfortunately we need this since some versions
-                        * of U-Boot on Exynos don't set the CNTFRQ register,
-                        * so we need the value from DT.
-                        */
-                       clock-frequency = <24000000>;
-               };
-
                mct@101c0000 {
                        compatible = "samsung,exynos4210-mct";
                        reg = <0x101C0000 0x800>;
                        };
                };
 
-               pmu {
-                       compatible = "arm,cortex-a15-pmu";
-                       interrupt-parent = <&combiner>;
-                       interrupts = <1 2>, <22 4>;
-               };
-
                pinctrl_0: pinctrl@11400000 {
                        compatible = "samsung,exynos5250-pinctrl";
                        reg = <0x11400000 0x1000>;
                       };
                };
        };
+
+       timer {
+               compatible = "arm,armv7-timer";
+               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)>;
+               /*
+                * Unfortunately we need this since some versions
+                * of U-Boot on Exynos don't set the CNTFRQ register,
+                * so we need the value from DT.
+                */
+               clock-frequency = <24000000>;
+       };
 };
 
 &dp {
index b1edb20..17e2f3e 100644 (file)
                #gpio-cells = <2>;
 
                interrupt-controller;
+               interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
                #interrupt-cells = <2>;
        };
 
                #gpio-cells = <2>;
 
                interrupt-controller;
+               interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
                #interrupt-cells = <2>;
        };
 
index fa19c59..36a2b77 100644 (file)
@@ -19,7 +19,7 @@
        };
 
        chosen {
-               bootargs = "console=ttySAC2,115200";
+               stdout-path = "serial2:115200n8";
        };
 
        fin_pll: xxti {
index 5516785..3581b57 100644 (file)
        #size-cells = <1>;
 
        aliases {
+               i2c0 = &hsi2c_0;
+               i2c1 = &hsi2c_1;
+               i2c2 = &hsi2c_2;
+               i2c3 = &hsi2c_3;
                pinctrl0 = &pinctrl_0;
                pinctrl1 = &pinctrl_1;
                pinctrl2 = &pinctrl_2;
                        wakeup-interrupt-controller {
                                compatible = "samsung,exynos4210-wakeup-eint";
                                interrupt-parent = <&gic>;
-                               interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
                        };
                };
 
                        #size-cells = <0>;
                        clocks = <&clock_fsys FSYS_CLK_MMC0>, <&clock_top TOP_SCLK_MMC0>;
                        clock-names = "biu", "ciu";
+                       assigned-clocks =
+                               <&clock_top TOP_MOUT_SCLK_FSYS_MMC0_SDCLKIN_A>,
+                               <&clock_top TOP_MOUT_SCLK_FSYS_MMC0_SDCLKIN_B>,
+                               <&clock_top TOP_SCLK_MMC0>;
+                       assigned-clock-parents =
+                               <&clock_top TOP_MOUT_BUSTOP_PLL_USER>,
+                               <&clock_top TOP_MOUT_SCLK_FSYS_MMC0_SDCLKIN_A>;
+                       assigned-clock-rates = <0>, <0>, <800000000>;
                        fifo-depth = <64>;
                        status = "disabled";
                };
                        #size-cells = <0>;
                        clocks = <&clock_fsys FSYS_CLK_MMC1>, <&clock_top TOP_SCLK_MMC1>;
                        clock-names = "biu", "ciu";
+                       assigned-clocks =
+                               <&clock_top TOP_MOUT_SCLK_FSYS_MMC1_SDCLKIN_A>,
+                               <&clock_top TOP_MOUT_SCLK_FSYS_MMC1_SDCLKIN_B>,
+                               <&clock_top TOP_SCLK_MMC1>;
+                       assigned-clock-parents =
+                               <&clock_top TOP_MOUT_BUSTOP_PLL_USER>,
+                               <&clock_top TOP_MOUT_SCLK_FSYS_MMC1_SDCLKIN_A>;
+                       assigned-clock-rates = <0>, <0>, <800000000>;
                        fifo-depth = <64>;
                        status = "disabled";
                };
                        #size-cells = <0>;
                        clocks = <&clock_fsys FSYS_CLK_MMC2>, <&clock_top TOP_SCLK_MMC2>;
                        clock-names = "biu", "ciu";
+                       assigned-clocks =
+                               <&clock_top TOP_MOUT_SCLK_FSYS_MMC2_SDCLKIN_A>,
+                               <&clock_top TOP_MOUT_SCLK_FSYS_MMC2_SDCLKIN_B>,
+                               <&clock_top TOP_SCLK_MMC2>;
+                       assigned-clock-parents =
+                               <&clock_top TOP_MOUT_BUSTOP_PLL_USER>,
+                               <&clock_top TOP_MOUT_SCLK_FSYS_MMC2_SDCLKIN_A>;
+                       assigned-clock-rates = <0>, <0>, <800000000>;
                        fifo-depth = <64>;
                        status = "disabled";
                };
+
+               hsi2c_0: hsi2c@12da0000 {
+                       compatible = "samsung,exynos5260-hsi2c";
+                       reg = <0x12DA0000 0x1000>;
+                       interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c0_hs_bus>;
+                       clocks = <&clock_peri PERI_CLK_HSIC0>;
+                       clock-names = "hsi2c";
+                       status = "disabled";
+               };
+
+               hsi2c_1: hsi2c@12db0000 {
+                       compatible = "samsung,exynos5260-hsi2c";
+                       reg = <0x12DB0000 0x1000>;
+                       interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c1_hs_bus>;
+                       clocks = <&clock_peri PERI_CLK_HSIC1>;
+                       clock-names = "hsi2c";
+                       status = "disabled";
+               };
+
+               hsi2c_2: hsi2c@12dc0000 {
+                       compatible = "samsung,exynos5260-hsi2c";
+                       reg = <0x12DC0000 0x1000>;
+                       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c2_hs_bus>;
+                       clocks = <&clock_peri PERI_CLK_HSIC2>;
+                       clock-names = "hsi2c";
+                       status = "disabled";
+               };
+
+               hsi2c_3: hsi2c@12dd0000 {
+                       compatible = "samsung,exynos5260-hsi2c";
+                       reg = <0x12DD0000 0x1000>;
+                       interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c3_hs_bus>;
+                       clocks = <&clock_peri PERI_CLK_HSIC3>;
+                       clock-names = "hsi2c";
+                       status = "disabled";
+               };
        };
 };
 
index 434a759..8f9e08f 100644 (file)
@@ -38,8 +38,6 @@
        fan0: pwm-fan {
                compatible = "pwm-fan";
                pwms = <&pwm 0 20972 0>;
-               cooling-min-state = <0>;
-               cooling-max-state = <3>;
                #cooling-cells = <2>;
                cooling-levels = <0 130 170 230>;
        };
index 8fc8c84..dffa5e3 100644 (file)
@@ -19,7 +19,7 @@
        };
 
        chosen {
-               bootargs = "console=ttySAC2,115200";
+               stdout-path = "serial2:115200n8";
        };
 
        fin_pll: xxti {
index 3447160..dbf0306 100644 (file)
@@ -24,7 +24,7 @@
        };
 
        chosen {
-               bootargs = "console=ttySAC3,115200";
+               stdout-path = "serial3:115200n8";
        };
 
        firmware@2073000 {
        };
 };
 
+&adc {
+       vdd-supply = <&ldo4_reg>;
+       status = "okay";
+};
+
+&cci {
+       status = "disabled";
+};
+
 &cpu0 {
        cpu-supply = <&buck2_reg>;
 };
        cpu-supply = <&buck6_reg>;
 };
 
-&usbdrd_dwc3_1 {
-       dr_mode = "host";
+&cpu0_thermal {
+       trips {
+               cpu0_alert0: cpu-alert-0 {
+                       temperature = <60000>; /* millicelsius */
+                       hysteresis = <5000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu0_alert1: cpu-alert-1 {
+                       temperature = <80000>; /* millicelsius */
+                       hysteresis = <10000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu0_alert2: cpu-alert-2 {
+                       temperature = <110000>; /* millicelsius */
+                       hysteresis = <10000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu0_crit0: cpu-crit-0 {
+                       temperature = <120000>; /* millicelsius */
+                       hysteresis = <0>; /* millicelsius */
+                       type = "critical";
+               };
+       };
+
+       cooling-maps {
+               /*
+                * Reduce the CPU speed by 2 steps, down to: 1600 MHz
+                * and 1100 MHz.
+                */
+               map0 {
+                       trip = <&cpu0_alert0>;
+                       cooling-device = <&cpu0 0 2>,
+                                        <&cpu1 0 2>,
+                                        <&cpu2 0 2>,
+                                        <&cpu3 0 2>,
+                                        <&cpu4 0 2>,
+                                        <&cpu5 0 2>,
+                                        <&cpu6 0 2>,
+                                        <&cpu7 0 2>;
+               };
+
+               /*
+                * Reduce the CPU speed down to 1200 MHz big (6 steps)
+                * and 800 MHz LITTLE (5 steps).
+                */
+               map1 {
+                       trip = <&cpu0_alert1>;
+                       cooling-device = <&cpu0 3 6>,
+                                        <&cpu1 3 6>,
+                                        <&cpu2 3 6>,
+                                        <&cpu3 3 6>,
+                                        <&cpu4 3 5>,
+                                        <&cpu5 3 5>,
+                                        <&cpu6 3 5>,
+                                        <&cpu7 3 5>;
+               };
+
+               /*
+                * Reduce the CPU speed as much as possible, down to 700 MHz
+                * big (11 steps) and 600 MHz LITTLE (7 steps).
+                */
+               map2 {
+                       trip = <&cpu0_alert2>;
+                       cooling-device = <&cpu0 6 11>,
+                                        <&cpu1 6 11>,
+                                        <&cpu2 6 11>,
+                                        <&cpu3 6 11>,
+                                        <&cpu4 5 7>,
+                                        <&cpu5 5 7>,
+                                        <&cpu6 5 7>,
+                                        <&cpu7 5 7>;
+               };
+       };
 };
 
-&cci {
-       status = "disabled";
+&cpu1_thermal {
+       trips {
+               cpu1_alert0: cpu-alert-0 {
+                       temperature = <60000>; /* millicelsius */
+                       hysteresis = <5000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu1_alert1: cpu-alert-1 {
+                       temperature = <80000>; /* millicelsius */
+                       hysteresis = <10000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu1_alert2: cpu-alert-2 {
+                       temperature = <110000>; /* millicelsius */
+                       hysteresis = <10000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu1_crit0: cpu-crit-0 {
+                       temperature = <120000>; /* millicelsius */
+                       hysteresis = <0>; /* millicelsius */
+                       type = "critical";
+               };
+       };
+
+       cooling-maps {
+               map0 {
+                       trip = <&cpu1_alert0>;
+                       cooling-device = <&cpu0 0 2>,
+                                        <&cpu1 0 2>,
+                                        <&cpu2 0 2>,
+                                        <&cpu3 0 2>,
+                                        <&cpu4 0 2>,
+                                        <&cpu5 0 2>,
+                                        <&cpu6 0 2>,
+                                        <&cpu7 0 2>;
+               };
+
+               map1 {
+                       trip = <&cpu1_alert1>;
+                       cooling-device = <&cpu0 3 6>,
+                                        <&cpu1 3 6>,
+                                        <&cpu2 3 6>,
+                                        <&cpu3 3 6>,
+                                        <&cpu4 3 5>,
+                                        <&cpu5 3 5>,
+                                        <&cpu6 3 5>,
+                                        <&cpu7 3 5>;
+               };
+
+               map2 {
+                       trip = <&cpu1_alert2>;
+                       cooling-device = <&cpu0 6 11>,
+                                        <&cpu1 6 11>,
+                                        <&cpu2 6 11>,
+                                        <&cpu3 6 11>,
+                                        <&cpu4 5 7>,
+                                        <&cpu5 5 7>,
+                                        <&cpu6 5 7>,
+                                        <&cpu7 5 7>;
+               };
+       };
+};
+
+&cpu2_thermal {
+       trips {
+               cpu2_alert0: cpu-alert-0 {
+                       temperature = <60000>; /* millicelsius */
+                       hysteresis = <5000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu2_alert1: cpu-alert-1 {
+                       temperature = <80000>; /* millicelsius */
+                       hysteresis = <10000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu2_alert2: cpu-alert-2 {
+                       temperature = <110000>; /* millicelsius */
+                       hysteresis = <10000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu2_crit0: cpu-crit-0 {
+                       temperature = <120000>; /* millicelsius */
+                       hysteresis = <0>; /* millicelsius */
+                       type = "critical";
+               };
+       };
+
+       cooling-maps {
+               map0 {
+                       trip = <&cpu2_alert0>;
+                       cooling-device = <&cpu0 0 2>,
+                                        <&cpu1 0 2>,
+                                        <&cpu2 0 2>,
+                                        <&cpu3 0 2>,
+                                        <&cpu4 0 2>,
+                                        <&cpu5 0 2>,
+                                        <&cpu6 0 2>,
+                                        <&cpu7 0 2>;
+               };
+
+               map1 {
+                       trip = <&cpu2_alert1>;
+                       cooling-device = <&cpu0 3 6>,
+                                        <&cpu1 3 6>,
+                                        <&cpu2 3 6>,
+                                        <&cpu3 3 6>,
+                                        <&cpu4 3 5>,
+                                        <&cpu5 3 5>,
+                                        <&cpu6 3 5>,
+                                        <&cpu7 3 5>;
+               };
+
+               map2 {
+                       trip = <&cpu2_alert2>;
+                       cooling-device = <&cpu0 6 11>,
+                                        <&cpu1 6 11>,
+                                        <&cpu2 6 11>,
+                                        <&cpu3 6 11>,
+                                        <&cpu4 6 7>,
+                                        <&cpu5 6 7>,
+                                        <&cpu6 6 7>,
+                                        <&cpu7 6 7>;
+               };
+       };
+};
+
+&cpu3_thermal {
+       trips {
+               cpu3_alert0: cpu-alert-0 {
+                       temperature = <60000>; /* millicelsius */
+                       hysteresis = <5000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu3_alert1: cpu-alert-1 {
+                       temperature = <80000>; /* millicelsius */
+                       hysteresis = <10000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu3_alert2: cpu-alert-2 {
+                       temperature = <110000>; /* millicelsius */
+                       hysteresis = <10000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu3_crit0: cpu-crit-0 {
+                       temperature = <120000>; /* millicelsius */
+                       hysteresis = <0>; /* millicelsius */
+                       type = "critical";
+               };
+       };
+
+       cooling-maps {
+               map0 {
+                       trip = <&cpu3_alert0>;
+                       cooling-device = <&cpu0 0 2>,
+                                        <&cpu1 0 2>,
+                                        <&cpu2 0 2>,
+                                        <&cpu3 0 2>,
+                                        <&cpu4 0 2>,
+                                        <&cpu5 0 2>,
+                                        <&cpu6 0 2>,
+                                        <&cpu7 0 2>;
+               };
+
+               map1 {
+                       trip = <&cpu3_alert1>;
+                       cooling-device = <&cpu0 3 6>,
+                                        <&cpu1 3 6>,
+                                        <&cpu2 3 6>,
+                                        <&cpu3 3 6>,
+                                        <&cpu4 3 5>,
+                                        <&cpu5 3 5>,
+                                        <&cpu6 3 5>,
+                                        <&cpu7 3 5>;
+               };
+
+               map2 {
+                       trip = <&cpu3_alert2>;
+                       cooling-device = <&cpu0 6 11>,
+                                        <&cpu1 6 11>,
+                                        <&cpu2 6 11>,
+                                        <&cpu3 6 11>,
+                                        <&cpu4 5 7>,
+                                        <&cpu5 5 7>,
+                                        <&cpu6 5 7>,
+                                        <&cpu7 5 7>;
+               };
+       };
 };
 
 &hdmi {
                                regulator-name = "PVDD_APIO_1V8";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
                        };
 
                        ldo3_reg: LDO3 {
                                regulator-name = "PVDD_APIO_MMCON_1V8";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
+                               /*
+                                * Must be always on, even though there is
+                                * a consumer (mmc_0).  Otherwise the board
+                                * does not reboot with vendor U-Boot
+                                * (Linaro for Arndale Octa, v2012.07).
+                                */
                                regulator-always-on;
                        };
 
                                regulator-name = "PVDD_ABB_1V8";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
                        };
 
                        ldo9_reg: LDO9 {
 
                        ldo13_reg: LDO13 {
                                regulator-name = "PVDD_APIO_MMCOFF_2V8";
-                               regulator-min-microvolt = <2800000>;
+                               regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <2800000>;
                        };
 
+                       ldo14_reg: LDO14 {
+                               /* Unused */
+                               regulator-name = "PVDD_LDO14";
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3950000>;
+                       };
+
                        ldo15_reg: LDO15 {
                                regulator-name = "PVDD_PERI_2V8";
                                regulator-min-microvolt = <3300000>;
                                regulator-max-microvolt = <2200000>;
                        };
 
+                       ldo17_reg: LDO17 {
+                               /* Unused */
+                               regulator-name = "PVDD_LDO17";
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3950000>;
+                       };
+
                        ldo18_reg: LDO18 {
                                regulator-name = "PVDD_EMMC_1V8";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
                        };
 
+                       ldo22_reg: LDO22 {
+                               /* Unused */
+                               regulator-name = "PVDD_LDO22";
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <2375000>;
+                       };
+
                        ldo23_reg: LDO23 {
                                regulator-name = "PVDD_MIFS_1V1";
-                               regulator-min-microvolt = <1200000>;
-                               regulator-max-microvolt = <1200000>;
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1100000>;
                                regulator-always-on;
                        };
 
                                regulator-max-microvolt = <2800000>;
                        };
 
+                       ldo25_reg: LDO25 {
+                               /* Unused */
+                               regulator-name = "PVDD_LDO25";
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3950000>;
+                       };
+
                        ldo26_reg: LDO26 {
                                regulator-name = "PVDD_CAM0_AF_2V8";
                                regulator-min-microvolt = <3000000>;
 
                        ldo27_reg: LDO27 {
                                regulator-name = "PVDD_G3DS_1V0";
-                               regulator-min-microvolt = <1200000>;
-                               regulator-max-microvolt = <1200000>;
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1100000>;
                        };
 
                        ldo28_reg: LDO28 {
                                regulator-max-microvolt = <1800000>;
                        };
 
+                       ldo30_reg: LDO30 {
+                               /* Unused */
+                               regulator-name = "PVDD_LDO30";
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3950000>;
+                       };
+
                        ldo31_reg: LDO31 {
                                regulator-name = "PVDD_PERI_1V8";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
                        };
 
+                       ldo34_reg: LDO34 {
+                               /* Unused */
+                               regulator-name = "PVDD_LDO34";
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3950000>;
+                       };
+
                        ldo35_reg: LDO35 {
                                regulator-name = "PVDD_CAM0_DVDD_1V2";
                                regulator-min-microvolt = <1200000>;
                                regulator-max-microvolt = <1200000>;
                        };
 
+                       ldo36_reg: LDO36 {
+                               /* Unused */
+                               regulator-name = "PVDD_LDO36";
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3950000>;
+                       };
+
+                       ldo37_reg: LDO37 {
+                               /* Unused */
+                               regulator-name = "PVDD_LDO37";
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3950000>;
+                       };
+
                        ldo38_reg: LDO38 {
                                regulator-name = "PVDD_CAM0_AVDD_2V8";
                                regulator-min-microvolt = <2800000>;
 
 &mmc_0 {
        status = "okay";
-       broken-cd;
+       non-removable;
        card-detect-delay = <200>;
        samsung,dw-mshc-ciu-div = <3>;
        samsung,dw-mshc-sdr-timing = <0 4>;
        pinctrl-names = "default";
        pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8>;
        vmmc-supply = <&ldo10_reg>;
+       vqmmc-supply = <&ldo3_reg>;
        bus-width = <8>;
        cap-mmc-highspeed;
+       mmc-hs200-1_8v;
 };
 
 &mmc_2 {
        status = "okay";
        card-detect-delay = <200>;
        samsung,dw-mshc-ciu-div = <3>;
-       samsung,dw-mshc-sdr-timing = <2 3>;
-       samsung,dw-mshc-ddr-timing = <1 2>;
+       samsung,dw-mshc-sdr-timing = <0 4>;
+       samsung,dw-mshc-ddr-timing = <0 2>;
        pinctrl-names = "default";
        pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
        vmmc-supply = <&ldo19_reg>;
        vqmmc-supply = <&ldo13_reg>;
        bus-width = <4>;
        cap-sd-highspeed;
+       sd-uhs-sdr50;
+       sd-uhs-sdr104;
+       sd-uhs-ddr50;
 };
 
 &pinctrl_0 {
        clocks = <&clock CLK_RTC>, <&s2mps11_osc S2MPS11_CLK_AP>;
        clock-names = "rtc", "rtc_src";
 };
+
+&usbdrd_dwc3_1 {
+       dr_mode = "host";
+};
index 3cf9050..8240e51 100644 (file)
@@ -21,7 +21,8 @@
        };
 
        chosen {
-               bootargs = "console=ttySAC2,115200 init=/linuxrc";
+               bootargs = "init=/linuxrc";
+               stdout-path = "serial2:115200n8";
        };
 
        fixed-rate-clocks {
index aaff158..5fb2326 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
  *
- * SAMSUNG EXYNOS54200 SoC device nodes are listed in this file.
+ * SAMSUNG EXYNOS5420 SoC device nodes are listed in this file.
  * EXYNOS5420 based board files can include this file and provide
  * values for board specfic bindings.
  */
index 51a843b..c3c2d85 100644 (file)
                        "Headphone Jack", "HPL",
                        "Headphone Jack", "HPR",
                        "Headphone Jack", "MICBIAS",
-                       "IN1", "Headphone Jack",
+                       "IN12", "Headphone Jack",
                        "Speakers", "SPKL",
                        "Speakers", "SPKR",
                        "I2S Playback", "Mixer DAI TX",
-                       "HiFi Playback", "Mixer DAI TX";
+                       "HiFi Playback", "Mixer DAI TX",
+                       "Mixer DAI RX", "HiFi Capture";
 
                assigned-clocks = <&clock CLK_MOUT_EPLL>,
                                <&clock CLK_MOUT_MAU_EPLL>,
index 5f195ad..93a48f2 100644 (file)
@@ -44,8 +44,6 @@
        fan0: pwm-fan {
                compatible = "pwm-fan";
                pwms = <&pwm 0 20972 0>;
-               cooling-min-state = <0>;
-               cooling-max-state = <3>;
                #cooling-cells = <2>;
                cooling-levels = <0 130 170 230>;
        };
index de26e5e..ae866bc 100644 (file)
                usbdrdphy1 = &usbdrd_phy1;
        };
 
-       soc: soc {
-               arm_a7_pmu: arm-a7-pmu {
-                       compatible = "arm,cortex-a7-pmu";
-                       interrupt-parent = <&gic>;
-                       interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
-                       status = "disabled";
-               };
+       arm_a7_pmu: arm-a7-pmu {
+               compatible = "arm,cortex-a7-pmu";
+               interrupt-parent = <&gic>;
+               interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
 
-               arm_a15_pmu: arm-a15-pmu {
-                       compatible = "arm,cortex-a15-pmu";
-                       interrupt-parent = <&combiner>;
-                       interrupts = <1 2>,
-                                    <7 0>,
-                                    <16 6>,
-                                    <19 2>;
-                       status = "disabled";
-               };
+       arm_a15_pmu: arm-a15-pmu {
+               compatible = "arm,cortex-a15-pmu";
+               interrupt-parent = <&combiner>;
+               interrupts = <1 2>,
+                            <7 0>,
+                            <16 6>,
+                            <19 2>;
+               status = "disabled";
+       };
 
+       soc: soc {
                sysram@2020000 {
                        compatible = "mmio-sram";
                        reg = <0x02020000 0x54000>;
index 592111c..cfbfbc9 100644 (file)
                        /* 32MB of flash */
                        reg = <0x30000000 0x02000000>;
 
-                       /*
-                        * This "RedBoot" is the Storlink derivative.
-                        */
-                       partition@0 {
-                               label = "RedBoot";
-                               reg = <0x00000000 0x00040000>;
-                               read-only;
-                       };
-                       /*
-                        * This firmware image contains the kernel catenated
-                        * with the squashfs root filesystem. For some reason
-                        * this is called "upgrade" on the vendor system.
-                        */
-                       partition@40000 {
-                               label = "upgrade";
-                               reg = <0x00040000 0x01f40000>;
-                               read-only;
-                       };
-                       /* RGDB, Residental Gateway Database? */
-                       partition@1f80000 {
-                               label = "rgdb";
-                               reg = <0x01f80000 0x00040000>;
-                               read-only;
-                       };
-                       /*
-                        * This partition contains MAC addresses for WAN,
-                        * WLAN and LAN, and the country code (for wireless
-                        * I guess).
-                        */
-                       partition@1fc0000 {
-                               label = "nvram";
-                               reg = <0x01fc0000 0x00020000>;
-                               read-only;
-                       };
-                       partition@1fe0000 {
-                               label = "LangPack";
-                               reg = <0x01fe0000 0x00020000>;
-                               read-only;
+                       partitions {
+                               compatible = "fixed-partitions";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+
+                               /*
+                                * This "RedBoot" is the Storlink derivative.
+                                */
+                               partition@0 {
+                                       label = "RedBoot";
+                                       reg = <0x00000000 0x00040000>;
+                                       read-only;
+                               };
+                               /*
+                                * This firmware image contains the kernel catenated
+                                * with the squashfs root filesystem. For some reason
+                                * this is called "upgrade" on the vendor system.
+                                */
+                               partition@40000 {
+                                       label = "upgrade";
+                                       reg = <0x00040000 0x01f40000>;
+                                       read-only;
+                               };
+                               /* RGDB, Residental Gateway Database? */
+                               partition@1f80000 {
+                                       label = "rgdb";
+                                       reg = <0x01f80000 0x00040000>;
+                                       read-only;
+                               };
+                               /*
+                                * This partition contains MAC addresses for WAN,
+                                * WLAN and LAN, and the country code (for wireless
+                                * I guess).
+                                */
+                               partition@1fc0000 {
+                                       label = "nvram";
+                                       reg = <0x01fc0000 0x00020000>;
+                                       read-only;
+                               };
+                               partition@1fe0000 {
+                                       label = "LangPack";
+                                       reg = <0x01fe0000 0x00020000>;
+                                       read-only;
+                               };
                        };
                };
 
index 59cadee..9cbdc1a 100644 (file)
                gpio0 = &gpio1;
                gpio1 = &gpio2;
                gpio2 = &gpio3;
+               i2c0 = &i2c1;
+               i2c1 = &i2c2;
+               i2c2 = &i2c3;
+               mmc0 = &esdhc1;
+               mmc1 = &esdhc2;
+               mmc2 = &esdhc3;
                serial0 = &uart1;
                serial1 = &uart2;
                serial2 = &uart3;
diff --git a/arch/arm/boot/dts/imx50-kobo-aura.dts b/arch/arm/boot/dts/imx50-kobo-aura.dts
new file mode 100644 (file)
index 0000000..a0eaf86
--- /dev/null
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2019 Jonathan Neuschäfer
+//
+// The Kobo Aura e-book reader, model N514. The mainboard is marked as E606F0B.
+
+/dts-v1/;
+#include "imx50.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "Kobo Aura (N514)";
+       compatible = "kobo,aura", "fsl,imx50";
+
+       chosen {
+               stdout-path = "serial1:115200n8";
+       };
+
+       memory@70000000 {
+               device_type = "memory";
+               reg = <0x70000000 0x10000000>;
+       };
+
+       gpio-leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_leds>;
+
+               on {
+                       label = "kobo_aura:orange:on";
+                       gpios = <&gpio6 24 GPIO_ACTIVE_LOW>;
+                       panic-indicator;
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpiokeys>;
+
+               power {
+                       label = "Power Button";
+                       gpios = <&gpio4 10 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_POWER>;
+               };
+
+               hallsensor {
+                       label = "Hallsensor";
+                       gpios = <&gpio5 15 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_RESERVED>;
+                       linux,input-type = <EV_SW>;
+               };
+
+               frontlight {
+                       label = "Frontlight";
+                       gpios = <&gpio4 1 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_DISPLAYTOGGLE>;
+               };
+       };
+
+       sd2_pwrseq: pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_sd2_reset>;
+               reset-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>;
+       };
+
+       sd2_vmmc: gpio-regulator {
+               compatible = "regulator-gpio";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_sd2_vmmc>;
+               regulator-name = "vmmc";
+               states = <3300000 0>;
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               enable-gpio = <&gpio4 12 GPIO_ACTIVE_LOW>;
+               startup-delay-us = <100000>;
+       };
+};
+
+&esdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_sd1>;
+       max-frequency = <50000000>;
+       bus-width = <4>;
+       cd-gpios = <&gpio5 17 GPIO_ACTIVE_LOW>;
+       disable-wp;
+       status = "okay";
+
+       /* External µSD card */
+};
+
+&esdhc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_sd2>;
+       bus-width = <4>;
+       max-frequency = <50000000>;
+       disable-wp;
+       mmc-pwrseq = <&sd2_pwrseq>;
+       vmmc-supply = <&sd2_vmmc>;
+       status = "okay";
+
+       /* CyberTan WC121 SDIO WiFi (BCM43362) */
+};
+
+&esdhc3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_sd3>;
+       bus-width = <8>;
+       non-removable;
+       max-frequency = <50000000>;
+       disable-wp;
+       status = "okay";
+
+       /* Internal eMMC */
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       /* TODO: ektf2132 touch controller at 0x15 */
+};
+
+&i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+
+       /* TODO: TPS65185 PMIC for E Ink at 0x68 */
+};
+
+&i2c3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+
+       /* TODO: embedded controller at 0x43 */
+};
+
+&iomuxc {
+       pinctrl_gpiokeys: gpiokeys {
+               fsl,pins = <
+                       MX50_PAD_CSPI_MISO__GPIO4_10            0x0
+                       MX50_PAD_SD2_D7__GPIO5_15               0x0
+                       MX50_PAD_KEY_ROW0__GPIO4_1              0x0
+               >;
+       };
+
+       pinctrl_i2c1: i2c1 {
+               fsl,pins = <
+                       MX50_PAD_I2C1_SCL__I2C1_SCL             0x400001fd
+                       MX50_PAD_I2C1_SDA__I2C1_SDA             0x400001fd
+               >;
+       };
+
+       pinctrl_i2c2: i2c2 {
+               fsl,pins = <
+                       MX50_PAD_I2C2_SCL__I2C2_SCL             0x400001fd
+                       MX50_PAD_I2C2_SDA__I2C2_SDA             0x400001fd
+               >;
+       };
+
+       pinctrl_i2c3: i2c3 {
+               fsl,pins = <
+                       MX50_PAD_I2C3_SCL__I2C3_SCL             0x400001fd
+                       MX50_PAD_I2C3_SDA__I2C3_SDA             0x400001fd
+               >;
+       };
+
+       pinctrl_leds: leds {
+               fsl,pins = <
+                       MX50_PAD_PWM1__GPIO6_24                 0x0
+               >;
+       };
+
+       pinctrl_sd1: sd1 {
+               fsl,pins = <
+                       MX50_PAD_SD1_CMD__ESDHC1_CMD            0x1e4
+                       MX50_PAD_SD1_CLK__ESDHC1_CLK            0xd4
+                       MX50_PAD_SD1_D0__ESDHC1_DAT0            0x1d4
+                       MX50_PAD_SD1_D1__ESDHC1_DAT1            0x1d4
+                       MX50_PAD_SD1_D2__ESDHC1_DAT2            0x1d4
+                       MX50_PAD_SD1_D3__ESDHC1_DAT3            0x1d4
+
+                       MX50_PAD_SD2_CD__GPIO5_17               0x0
+               >;
+       };
+
+       pinctrl_sd2: sd2 {
+               fsl,pins = <
+                       MX50_PAD_SD2_CMD__ESDHC2_CMD            0x1e4
+                       MX50_PAD_SD2_CLK__ESDHC2_CLK            0xd4
+                       MX50_PAD_SD2_D0__ESDHC2_DAT0            0x1d4
+                       MX50_PAD_SD2_D1__ESDHC2_DAT1            0x1d4
+                       MX50_PAD_SD2_D2__ESDHC2_DAT2            0x1d4
+                       MX50_PAD_SD2_D3__ESDHC2_DAT3            0x1d4
+               >;
+       };
+
+       pinctrl_sd2_reset: sd2-reset {
+               fsl,pins = <
+                       MX50_PAD_ECSPI2_MOSI__GPIO4_17          0x0
+               >;
+       };
+
+       pinctrl_sd2_vmmc: sd2-vmmc {
+               fsl,pins = <
+                       MX50_PAD_ECSPI1_SCLK__GPIO4_12          0x0
+               >;
+       };
+
+       pinctrl_sd3: sd3 {
+               fsl,pins = <
+                       MX50_PAD_SD3_CMD__ESDHC3_CMD            0x1e4
+                       MX50_PAD_SD3_CLK__ESDHC3_CLK            0xd4
+                       MX50_PAD_SD3_D0__ESDHC3_DAT0            0x1d4
+                       MX50_PAD_SD3_D1__ESDHC3_DAT1            0x1d4
+                       MX50_PAD_SD3_D2__ESDHC3_DAT2            0x1d4
+                       MX50_PAD_SD3_D3__ESDHC3_DAT3            0x1d4
+                       MX50_PAD_SD3_D4__ESDHC3_DAT4            0x1d4
+                       MX50_PAD_SD3_D5__ESDHC3_DAT5            0x1d4
+                       MX50_PAD_SD3_D6__ESDHC3_DAT6            0x1d4
+                       MX50_PAD_SD3_D7__ESDHC3_DAT7            0x1d4
+               >;
+       };
+
+       pinctrl_uart2: uart2 {
+               fsl,pins = <
+                       MX50_PAD_UART2_TXD__UART2_TXD_MUX       0x1e4
+                       MX50_PAD_UART2_RXD__UART2_RXD_MUX       0x1e4
+               >;
+       };
+
+       pinctrl_usbphy: usbphy {
+               fsl,pins = <
+                       MX50_PAD_ECSPI2_SS0__GPIO4_19           0x0
+               >;
+       };
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+};
+
+&usbotg {
+       phy_type = "utmi_wide";
+       dr_mode = "peripheral";
+       status = "okay";
+};
+
+&usbphy0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbphy>;
+       vbus-detect-gpio = <&gpio4 19 GPIO_ACTIVE_LOW>;
+};
index ee1e3e8..0bfe7c9 100644 (file)
                gpio3 = &gpio4;
                gpio4 = &gpio5;
                gpio5 = &gpio6;
+               i2c0 = &i2c1;
+               i2c1 = &i2c2;
+               i2c2 = &i2c3;
+               mmc0 = &esdhc1;
+               mmc1 = &esdhc2;
+               mmc2 = &esdhc3;
+               mmc3 = &esdhc4;
                serial0 = &uart1;
                serial1 = &uart2;
                serial2 = &uart3;
                serial3 = &uart4;
                serial4 = &uart5;
+               spi0 = &ecspi1;
+               spi1 = &ecspi2;
+               spi2 = &cspi;
        };
 
        cpus {
                };
        };
 
+       usbphy0: usbphy-0 {
+               compatible = "usb-nop-xceiv";
+               clocks = <&clks IMX5_CLK_USB_PHY1_GATE>;
+               clock-names = "main_clk";
+               #phy-cells = <0>;
+               status = "okay";
+       };
+
        soc {
                #address-cells = <1>;
                #size-cells = <1>;
                                compatible = "fsl,imx50-usb", "fsl,imx27-usb";
                                reg = <0x53f80000 0x0200>;
                                interrupts = <18>;
-                               clocks = <&clks IMX5_CLK_USB_PHY1_GATE>;
+                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
+                               fsl,usbphy = <&usbphy0>;
                                status = "disabled";
                        };
 
                                reg = <0x63fb0000 0x4000>;
                                interrupts = <6>;
                                clocks = <&clks IMX5_CLK_SDMA_GATE>,
-                                        <&clks IMX5_CLK_SDMA_GATE>;
+                                        <&clks IMX5_CLK_AHB>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
                                fsl,sdma-ram-script-name = "imx/sdma/sdma-imx50.bin";
index a8220f0..3596060 100644 (file)
@@ -1,42 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
 /*
  * Copyright (C) 2017 Zodiac Inflight Innovations
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     version 2 as published by the Free Software Foundation.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
index a5ee25c..0a4b9a5 100644 (file)
                                reg = <0x83fb0000 0x4000>;
                                interrupts = <6>;
                                clocks = <&clks IMX5_CLK_SDMA_GATE>,
-                                        <&clks IMX5_CLK_SDMA_GATE>;
+                                        <&clks IMX5_CLK_AHB>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
                                fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin";
index db2e5bc..d1770e1 100644 (file)
@@ -52,7 +52,7 @@
        clock-frequency = <400000>;
        status = "okay";
 
-       stmpe610@41 {
+       touchscreen@41 {
                compatible = "st,stmpe610";
                reg = <0x41>;
                id = <0>;
diff --git a/arch/arm/boot/dts/imx53-m53menlo.dts b/arch/arm/boot/dts/imx53-m53menlo.dts
new file mode 100644 (file)
index 0000000..f0a3fde
--- /dev/null
@@ -0,0 +1,311 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Marek Vasut <marex@denx.de>
+ */
+
+/dts-v1/;
+#include "imx53-m53.dtsi"
+
+/ {
+       model = "MENLO M53 EMBEDDED DEVICE";
+       compatible = "menlo,m53menlo", "fsl,imx53";
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_led>;
+
+               user1 {
+                       label = "TestLed601";
+                       gpios = <&gpio6 1 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "mmc0";
+               };
+
+               user2 {
+                       label = "TestLed602";
+                       gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+               };
+
+               eth {
+                       label = "EthLedYe";
+                       gpios = <&gpio2 11 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "none";
+               };
+       };
+
+       panel {
+               compatible = "edt,etm070080dh6";
+               enable-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>;
+
+               port {
+                       panel_in: endpoint {
+                               remote-endpoint = <&lvds0_out>;
+                       };
+               };
+       };
+
+       reg_usbh1_vbus: regulator-usbh1-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio1 2 GPIO_ACTIVE_LOW>;
+       };
+};
+
+&can1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_can1>;
+       status = "okay";
+};
+
+&can2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_can2>;
+       status = "okay";
+};
+
+&clks {
+       assigned-clocks = <&clks IMX5_CLK_CKO1_SEL>,
+                         <&clks IMX5_CLK_CKO1_PODF>,
+                         <&clks IMX5_CLK_CKO1>;
+       assigned-clock-parents = <&clks IMX5_CLK_AHB>;
+       assigned-clock-rates = <133333334>, <33333334>, <33333334>;
+};
+
+&esdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc1>;
+       cd-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
+       wp-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec>;
+       phy-mode = "rmii";
+       status = "okay";
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       touchscreen@38 {
+               compatible = "edt,edt-ft5x06";
+               reg = <0x38>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_edt_ft5x06>;
+               interrupt-parent = <&gpio6>;
+               interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
+               reset-gpios = <&gpio2 9 GPIO_ACTIVE_LOW>;
+               wake-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
+       };
+
+       eeprom@50 {
+               compatible = "atmel,24c64";
+               reg = <0x50>;
+               pagesize = <32>;
+       };
+
+       dac@60 {
+               compatible = "microchip,mcp4725";
+               reg = <0x60>;
+       };
+};
+
+&i2c2 {
+       touchscreen@41 {
+               status = "disabled";
+       };
+};
+
+&i2c3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hog>;
+
+       imx53-m53evk {
+               hoggrp {
+                       fsl,pins = <
+                               MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK       0x1c4
+                               MX53_PAD_EIM_EB3__GPIO2_31              0x1d5
+                               MX53_PAD_PATA_DA_0__GPIO7_6             0x1d5
+                               MX53_PAD_GPIO_19__CCM_CLKO              0x1d5
+                               MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK       0x1d5
+                               MX53_PAD_CSI0_DAT4__GPIO5_22            0x1d5
+                               MX53_PAD_CSI0_DAT5__GPIO5_23            0x1d5
+                               MX53_PAD_CSI0_DAT6__GPIO5_24            0x1d5
+                               MX53_PAD_CSI0_DAT7__GPIO5_25            0x1d5
+                               MX53_PAD_CSI0_DAT8__GPIO5_26            0x1d5
+                               MX53_PAD_CSI0_DAT9__GPIO5_27            0x1d5
+                               MX53_PAD_CSI0_DAT10__GPIO5_28           0x1d5
+                               MX53_PAD_CSI0_DAT11__GPIO5_29           0x1d5
+                               MX53_PAD_CSI0_DAT14__GPIO6_0            0x1d5
+                       >;
+               };
+
+               pinctrl_led: ledgrp {
+                       fsl,pins = <
+                               MX53_PAD_CSI0_DAT15__GPIO6_1            0x1d5
+                               MX53_PAD_CSI0_DAT16__GPIO6_2            0x1d5
+                       >;
+               };
+
+               pinctrl_can1: can1grp {
+                       fsl,pins = <
+                               MX53_PAD_GPIO_7__CAN1_TXCAN             0x1c4
+                               MX53_PAD_GPIO_8__CAN1_RXCAN             0x1c4
+                       >;
+               };
+
+               pinctrl_can2: can2grp {
+                       fsl,pins = <
+                               MX53_PAD_KEY_COL4__CAN2_TXCAN           0x1c4
+                               MX53_PAD_KEY_ROW4__CAN2_RXCAN           0x1c4
+                       >;
+               };
+
+               pinctrl_display_gpio: display-gpiogrp {
+                       fsl,pins = <
+                               MX53_PAD_CSI0_DAT12__GPIO5_30           0x1d5 /* Reset */
+                               MX53_PAD_CSI0_DAT13__GPIO5_31           0x1d5 /* Interrupt */
+                       >;
+               };
+
+               pinctrl_edt_ft5x06: edt-ft5x06grp {
+                       fsl,pins = <
+                               MX53_PAD_PATA_DATA9__GPIO2_9            0x1d5 /* Reset */
+                               MX53_PAD_CSI0_DAT19__GPIO6_5            0x1d5 /* Interrupt */
+                               MX53_PAD_PATA_DATA10__GPIO2_10          0x1d5 /* Wake */
+                       >;
+               };
+
+               pinctrl_esdhc1: esdhc1grp {
+                       fsl,pins = <
+                               MX53_PAD_SD1_DATA0__ESDHC1_DAT0         0x1d5
+                               MX53_PAD_SD1_DATA1__ESDHC1_DAT1         0x1d5
+                               MX53_PAD_SD1_DATA2__ESDHC1_DAT2         0x1d5
+                               MX53_PAD_SD1_DATA3__ESDHC1_DAT3         0x1d5
+                               MX53_PAD_SD1_CMD__ESDHC1_CMD            0x1d5
+                               MX53_PAD_SD1_CLK__ESDHC1_CLK            0x1d5
+                       >;
+               };
+
+               pinctrl_fec: fecgrp {
+                       fsl,pins = <
+                               MX53_PAD_FEC_MDC__FEC_MDC               0x4
+                               MX53_PAD_FEC_MDIO__FEC_MDIO             0x1fc
+                               MX53_PAD_FEC_REF_CLK__FEC_TX_CLK        0x180
+                               MX53_PAD_FEC_RX_ER__FEC_RX_ER           0x180
+                               MX53_PAD_FEC_CRS_DV__FEC_RX_DV          0x180
+                               MX53_PAD_FEC_RXD1__FEC_RDATA_1          0x180
+                               MX53_PAD_FEC_RXD0__FEC_RDATA_0          0x180
+                               MX53_PAD_FEC_TX_EN__FEC_TX_EN           0x4
+                               MX53_PAD_FEC_TXD1__FEC_TDATA_1          0x4
+                               MX53_PAD_FEC_TXD0__FEC_TDATA_0          0x4
+                       >;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <
+                               MX53_PAD_EIM_D21__I2C1_SCL              0x400001e4
+                               MX53_PAD_EIM_D28__I2C1_SDA              0x400001e4
+                       >;
+               };
+
+               pinctrl_i2c3: i2c3grp {
+                       fsl,pins = <
+                               MX53_PAD_GPIO_6__I2C3_SDA               0x400001e4
+                               MX53_PAD_GPIO_5__I2C3_SCL               0x400001e4
+                       >;
+               };
+
+               pinctrl_lvds0: lvds0grp {
+                       /* LVDS pins only have pin mux configuration */
+                       fsl,pins = <
+                               MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK     0x80000000
+                               MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0     0x80000000
+                               MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1     0x80000000
+                               MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2     0x80000000
+                               MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3     0x80000000
+                       >;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <
+                               MX53_PAD_PATA_DIOW__UART1_TXD_MUX       0x1e4
+                               MX53_PAD_PATA_DMACK__UART1_RXD_MUX      0x1e4
+                       >;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <
+                               MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX  0x1e4
+                               MX53_PAD_PATA_DMARQ__UART2_TXD_MUX      0x1e4
+                       >;
+               };
+
+               pinctrl_usb: usbgrp {
+                       fsl,pins = <
+                               MX53_PAD_GPIO_2__GPIO1_2                0x1d5
+                               MX53_PAD_GPIO_3__USBOH3_USBH1_OC        0x1d5
+                       >;
+               };
+       };
+};
+
+&ldb {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_lvds0>;
+       status = "okay";
+
+       lvds0: lvds-channel@0 {
+               reg = <0>;
+               fsl,data-mapping = "spwg";
+               fsl,data-width = <18>;
+               status = "okay";
+
+               port@2 {
+                       reg = <2>;
+
+                       lvds0_out: endpoint {
+                               remote-endpoint = <&panel_in>;
+                       };
+               };
+       };
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+};
+
+&usbh1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usb>;
+       vbus-supply = <&reg_usbh1_vbus>;
+       phy_type = "utmi";
+       dr_mode = "peripheral";
+       status = "okay";
+};
+
+&usbotg {
+       dr_mode = "peripheral";
+       status = "okay";
+};
index b330030..9b672ed 100644 (file)
                                reg = <0x63fb0000 0x4000>;
                                interrupts = <6>;
                                clocks = <&clks IMX5_CLK_SDMA_GATE>,
-                                        <&clks IMX5_CLK_SDMA_GATE>;
+                                        <&clks IMX5_CLK_AHB>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
                                fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
index fb01fa6..2a6ce87 100644 (file)
@@ -88,6 +88,7 @@
                regulator-min-microvolt = <5000000>;
                regulator-max-microvolt = <5000000>;
                gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
+               startup-delay-us = <70000>;
                enable-active-high;
        };
 
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
                gpio = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+               startup-delay-us = <70000>;
                enable-active-high;
                regulator-always-on;
        };
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-reset-duration = <10>;
        phy-reset-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
        phy-supply = <&reg_enet>;
                gpio-cfg = <
                        0x0000 /* 0:Default */
                        0x0000 /* 1:Default */
-                       0x0013 /* 2:FN_DMICCLK */
+                       0x0000 /* 2:FN_DMICCLK */
                        0x0000 /* 3:Default */
-                       0x8014 /* 4:FN_DMICCDAT */
+                       0x0000 /* 4:FN_DMICCDAT */
                        0x0000 /* 5:Default */
                >;
        };
diff --git a/arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts b/arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts
new file mode 100644 (file)
index 0000000..9eb2b73
--- /dev/null
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 Eckelmann AG.
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "imx6dl.dtsi"
+
+/ {
+       model = "Eckelmann CI 4X10 Board";
+       compatible = "eckelmann,imx6dl-ci4x10", "fsl,imx6dl";
+
+       chosen {
+               stdout-path = &uart3;
+       };
+
+       memory@10000000 {
+               device_type = "memory";
+               reg = <0x10000000 0x40000000>;
+       };
+
+       rmii_clk: clock-rmii {
+               /* This clock is provided by the phy (KSZ8091RNB) */
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <50000000>;
+       };
+
+       reg_usb_h1_vbus: regulator-usb-h1-vbus {
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_reg_usb_h1_vbus>;
+               compatible = "regulator-fixed";
+               regulator-name = "usb_h1_vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       siox {
+               compatible = "eckelmann,siox-gpio";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_siox>;
+               din-gpios = <&gpio6 11 GPIO_ACTIVE_HIGH>;
+               dout-gpios = <&gpio6 8 GPIO_ACTIVE_HIGH>;
+               dclk-gpios = <&gpio6 9 GPIO_ACTIVE_HIGH>;
+               dld-gpios = <&gpio6 10 GPIO_ACTIVE_HIGH>;
+       };
+};
+
+&can1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_flexcan1>;
+       status = "okay";
+};
+
+&can2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_flexcan2>;
+       status = "okay";
+};
+
+&ecspi2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ecspi2>;
+       cs-gpios = <&gpio5 12 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+
+       flash@0 {
+               compatible = "everspin,mr25h256";
+               reg = <0>;
+               spi-max-frequency = <15000000>;
+       };
+};
+
+&ecspi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ecspi1>;
+       cs-gpios = <&gpio5 25 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+
+       tpm@0 {
+               compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+               reg = <0>;
+               spi-max-frequency = <10000000>;
+       };
+};
+
+&gpio2 {
+       gpio-line-names = "buzzer", "", "", "", "", "", "", "",
+                         "", "", "", "", "", "", "", "",
+                         "", "", "", "", "", "", "", "",
+                         "", "", "", "", "", "", "", "";
+};
+
+&gpio4 {
+       gpio-line-names = "", "", "", "", "", "", "", "in2",
+                         "prio2", "prio1", "aux", "", "", "", "", "",
+                         "", "", "", "", "", "", "", "",
+                         "", "", "", "", "", "", "", "";
+};
+
+&gpio6 {
+       gpio-line-names = "", "", "", "", "", "", "", "",
+                         "", "", "", "", "", "", "", "in1",
+                         "", "", "", "", "", "", "", "",
+                         "", "", "", "", "", "", "", "";
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       temperature-sensor@49 {
+               compatible = "ad,ad7414";
+               reg = <0x49>;
+       };
+
+       rtc@51 {
+               compatible = "nxp,pcf2127";
+               reg = <0x51>;
+       };
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hog>;
+
+       pinctrl_hog: hog {
+               fsl,pins = <
+                       MX6QDL_PAD_NANDF_D0__GPIO2_IO00         0x00000018 /* buzzer */
+                       MX6QDL_PAD_KEY_COL1__GPIO4_IO08         0x00000018 /* OUT_1 */
+                       MX6QDL_PAD_KEY_ROW1__GPIO4_IO09         0x00000018 /* OUT_2 */
+                       MX6QDL_PAD_KEY_COL2__GPIO4_IO10         0x00000018 /* OUT_3 */
+                       MX6QDL_PAD_NANDF_CS2__GPIO6_IO15        0x00000000 /* In1 */
+                       MX6QDL_PAD_KEY_ROW0__GPIO4_IO07         0x00000000 /* In2 */
+                       MX6QDL_PAD_GPIO_9__GPIO1_IO09           0x00000018 /* unused watchdog pin */
+                       MX6QDL_PAD_SD1_DAT2__GPIO1_IO19         0x00000018 /* unused watchdog pin */
+
+               >;
+       };
+
+       pinctrl_ecspi1: ecspi1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_CSI0_DAT4__ECSPI1_SCLK       0x000100a0
+                       MX6QDL_PAD_CSI0_DAT5__ECSPI1_MOSI       0x000100a0
+                       MX6QDL_PAD_CSI0_DAT6__ECSPI1_MISO       0x000100a0
+                       MX6QDL_PAD_CSI0_DAT7__GPIO5_IO25        0x000100a0
+               >;
+       };
+
+       pinctrl_ecspi2: ecspi2grp {
+               fsl,pins = <
+                       MX6QDL_PAD_DISP0_DAT19__ECSPI2_SCLK     0x000100b1
+                       MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI         0x000100b1
+                       MX6QDL_PAD_EIM_OE__ECSPI2_MISO          0x000100b1
+                       MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12      0x000100b1
+               >;
+       };
+
+       pinctrl_enet: enetgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_16__ENET_REF_CLK        0x4001b0a8
+                       MX6QDL_PAD_ENET_MDIO__ENET_MDIO         0x0001b098
+                       MX6QDL_PAD_ENET_MDC__ENET_MDC           0x0001b098
+                       MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0     0x0001b098
+                       MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1     0x0001b098
+                       MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN       0x0001b098
+                       MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER       0x0001b0b0
+                       MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0     0x0001b0b0
+                       MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1     0x0001b0b0
+                       MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN      0x0001b0b0
+                       MX6QDL_PAD_SD1_CMD__GPIO1_IO18          0x00000018
+               >;
+       };
+
+       pinctrl_flexcan1: flexcan1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_7__FLEXCAN1_TX          0x0001b020
+                       MX6QDL_PAD_GPIO_8__FLEXCAN1_RX          0x0001b0b0
+               >;
+       };
+
+       pinctrl_flexcan2: flexcan2grp {
+               fsl,pins = <
+                       MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX        0x0001b020
+                       MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX        0x0001b0b0
+               >;
+       };
+
+       pinctrl_i2c1: i2c1grp {
+               fsl,pins = <
+                       /* without SION i2c doesn't detect bus busy */
+                       MX6QDL_PAD_CSI0_DAT9__I2C1_SCL          0x4001b820
+                       MX6QDL_PAD_CSI0_DAT8__I2C1_SDA          0x4001b820
+               >;
+       };
+
+       pinctrl_pcie: pciegrp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD1_CLK__GPIO1_IO20          0x00000018
+               >;
+       };
+
+       pinctrl_reg_usb_h1_vbus: reg_usb_h1_vbusgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_EIM_D31__GPIO3_IO31          0x0001b0b0
+               >;
+       };
+
+       pinctrl_siox: sioxgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_NANDF_CS0__GPIO6_IO11        0x0001b010      /* DIN */
+                       MX6QDL_PAD_NANDF_ALE__GPIO6_IO08        0x0001b010      /* DOUT */
+                       MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09       0x0001b010      /* DCLK */
+                       MX6QDL_PAD_NANDF_RB0__GPIO6_IO10        0x0001b010      /* DLD */
+               >;
+       };
+
+       pinctrl_uart1_dte: uart1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_CSI0_DAT11__UART1_TX_DATA    0x0001b010
+                       MX6QDL_PAD_CSI0_DAT10__UART1_RX_DATA    0x0001b010
+                       MX6QDL_PAD_EIM_D19__UART1_RTS_B         0x0001b010
+                       MX6QDL_PAD_EIM_D20__UART1_CTS_B         0x0001b010
+                       MX6QDL_PAD_EIM_D23__GPIO3_IO23          0x0001b010      /* DCD */
+                       MX6QDL_PAD_EIM_D24__GPIO3_IO24          0x0001b010      /* DTR */
+                       MX6QDL_PAD_EIM_D25__GPIO3_IO25          0x0001b010      /* DSR */
+               >;
+       };
+
+       pinctrl_uart2_dte: uart2grp {
+               fsl,pins = <
+                       MX6QDL_PAD_EIM_D27__UART2_TX_DATA       0x0001b010
+                       MX6QDL_PAD_EIM_D26__UART2_RX_DATA       0x0001b010
+                       MX6QDL_PAD_EIM_D28__UART2_RTS_B         0x0001b010
+                       MX6QDL_PAD_EIM_D29__UART2_CTS_B         0x0001b010
+                       MX6QDL_PAD_NANDF_D1__GPIO2_IO01         0x0001b010      /* DCD */
+                       MX6QDL_PAD_GPIO_18__GPIO7_IO13          0x0001b010      /* DTR */
+                       MX6QDL_PAD_NANDF_CS3__GPIO6_IO16        0x0001b010      /* DSR */
+               >;
+       };
+
+       pinctrl_uart3_dce: uart3grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD4_CLK__UART3_RX_DATA       0x0001b010
+                       MX6QDL_PAD_SD4_CMD__UART3_TX_DATA       0x0001b010
+               >;
+       };
+
+       pinctrl_uart4_dce: uart4grp {
+               fsl,pins = <
+                       MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA    0x0001b010
+                       MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA    0x0001b010
+                       MX6QDL_PAD_CSI0_DAT17__GPIO6_IO03       0x0001b010
+               >;
+       };
+
+       pinctrl_uart5_dce: uart5grp {
+               fsl,pins = <
+                       MX6QDL_PAD_CSI0_DAT15__UART5_RX_DATA    0x0001b010
+                       MX6QDL_PAD_CSI0_DAT14__UART5_TX_DATA    0x0001b010
+                       MX6QDL_PAD_CSI0_DAT19__GPIO6_IO05       0x0001b010      /* RTS */
+               >;
+       };
+
+       pinctrl_usbh1: usbh1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_EIM_D30__USB_H1_OC           0x0001b0b0
+               >;
+       };
+
+       pinctrl_usdhc3: usdhc3grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD3_CMD__SD3_CMD             0x00017059
+                       MX6QDL_PAD_SD3_CLK__SD3_CLK             0x00010059
+                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0          0x00017059
+                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1          0x00017059
+                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2          0x00017059
+                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3          0x00017059
+                       MX6QDL_PAD_SD3_DAT4__SD3_DATA4          0x00017059
+                       MX6QDL_PAD_SD3_DAT5__SD3_DATA5          0x00017059
+                       MX6QDL_PAD_SD3_DAT6__SD3_DATA6          0x00017059
+                       MX6QDL_PAD_SD3_DAT7__SD3_DATA7          0x00017059
+               >;
+       };
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rmii";
+       phy-reset-gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
+       phy-handle = <&phy>;
+       clocks = <&clks IMX6QDL_CLK_ENET>, <&clks IMX6QDL_CLK_ENET>, <&rmii_clk>;
+       status = "okay";
+
+       mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               phy: ethernet-phy@1 {
+                       compatible = "ethernet-phy-ieee802.3-c22";
+                       reg = <1>;
+               };
+       };
+};
+
+&pcie {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pcie>;
+       reset-gpio = <&gpio1 20 GPIO_ACTIVE_LOW>;
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1_dte>;
+       uart-has-rtscts;
+       fsl,dte-mode;
+       dcd-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
+       dtr-gpios = <&gpio3 24 GPIO_ACTIVE_LOW>;
+       dsr-gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2_dte>;
+       uart-has-rtscts;
+       fsl,dte-mode;
+       dcd-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+       dtr-gpios = <&gpio7 13 GPIO_ACTIVE_LOW>;
+       dsr-gpios = <&gpio6 16 GPIO_ACTIVE_LOW>;
+       status = "okay";
+};
+
+&uart3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart3_dce>;
+       status = "okay";
+};
+
+&uart4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart4_dce>;
+       rts-gpios = <&gpio6 3 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+};
+
+&uart5 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart5_dce>;
+       rts-gpios = <&gpio6 5 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+};
+
+&usbh1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbh1>;
+       vbus-supply = <&reg_usb_h1_vbus>;
+       status = "okay";
+};
+
+&usbotg {
+       dr_mode = "peripheral";
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       bus-width = <8>;
+       non-removable;
+       status = "okay";
+};
index 65c184b..d9de49e 100644 (file)
@@ -92,7 +92,7 @@
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-reset-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
        interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
                              <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
index 660d52a..ff3283c 100644 (file)
        model = "Freescale i.MX6 DualLite/Solo SABRE Automotive Board";
        compatible = "fsl,imx6dl-sabreauto", "fsl,imx6dl";
 };
+
+&cpu0 {
+       operating-points = <
+               /* kHz    uV */
+               996000  1275000
+               792000  1175000
+               396000  1150000
+       >;
+       fsl,soc-operating-points = <
+               /* ARM kHz  SOC-PU uV */
+               996000  1200000
+               792000  1175000
+               396000  1175000
+       >;
+};
index adc9455..37c6340 100644 (file)
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        status = "okay";
 };
 
index 56e5b50..cb0a5f7 100644 (file)
 /dts-v1/;
 #include "imx6q.dtsi"
 #include "imx6qdl-gw54xx.dtsi"
+#include <dt-bindings/media/tda1997x.h>
 
 / {
        model = "Gateworks Ventana i.MX6 Dual/Quad GW54XX";
        compatible = "gw,imx6q-gw54xx", "gw,ventana", "fsl,imx6q";
+
+       sound-digital {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "tda1997x-audio";
+
+               simple-audio-card,dai-link@0 {
+                       format = "i2s";
+
+                       cpu {
+                               sound-dai = <&ssi2>;
+                       };
+
+                       codec {
+                               bitclock-master;
+                               frame-master;
+                               sound-dai = <&hdmi_receiver>;
+                       };
+               };
+       };
 };
 
 &i2c3 {
                        };
                };
        };
+
+       hdmi_receiver: hdmi-receiver@48 {
+               compatible = "nxp,tda19971";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_tda1997x>;
+               reg = <0x48>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+               DOVDD-supply = <&reg_3p3v>;
+               AVDD-supply = <&sw4_reg>;
+               DVDD-supply = <&sw4_reg>;
+               #sound-dai-cells = <0>;
+               nxp,audout-format = "i2s";
+               nxp,audout-layout = <0>;
+               nxp,audout-width = <16>;
+               nxp,audout-mclk-fs = <128>;
+               /*
+                * The 8bpp YUV422 semi-planar mode outputs CbCr[11:4]
+                * and Y[11:4] across 16bits in the same cycle
+                * which we map to VP[15:08]<->CSI_DATA[19:12]
+                */
+               nxp,vidout-portcfg =
+                       /*G_Y_11_8<->VP[15:12]<->CSI_DATA[19:16]*/
+                       < TDA1997X_VP24_V15_12 TDA1997X_G_Y_11_8 >,
+                       /*G_Y_7_4<->VP[11:08]<->CSI_DATA[15:12]*/
+                       < TDA1997X_VP24_V11_08 TDA1997X_G_Y_7_4 >,
+                       /*R_CR_CBCR_11_8<->VP[07:04]<->CSI_DATA[11:08]*/
+                       < TDA1997X_VP24_V07_04 TDA1997X_R_CR_CBCR_11_8 >,
+                       /*R_CR_CBCR_7_4<->VP[03:00]<->CSI_DATA[07:04]*/
+                       < TDA1997X_VP24_V03_00 TDA1997X_R_CR_CBCR_7_4 >;
+
+               port {
+                       tda1997x_to_ipu1_csi0_mux: endpoint {
+                               remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
+                               bus-width = <16>;
+                               hsync-active = <1>;
+                               vsync-active = <1>;
+                               data-active = <1>;
+                       };
+               };
+       };
+};
+
+&ipu1_csi0_from_ipu1_csi0_mux {
+       bus-width = <16>;
+};
+
+&ipu1_csi0_mux_from_parallel_sensor {
+       remote-endpoint = <&tda1997x_to_ipu1_csi0_mux>;
+       bus-width = <16>;
+};
+
+&ipu1_csi0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ipu1_csi0>;
 };
 
 &ipu2_csi1_from_ipu2_csi1_mux {
                >;
        };
 
+       pinctrl_ipu1_csi0: ipu1_csi0grp {
+               fsl,pins = <
+                       MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04          0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05          0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06          0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07          0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08          0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09          0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19         0x1b0b0
+                       MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC           0x1b0b0
+                       MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK        0x1b0b0
+                       MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC          0x1b0b0
+               >;
+       };
+
        pinctrl_ipu2_csi1: ipu2_csi1grp {
                fsl,pins = <
                        MX6QDL_PAD_EIM_EB2__IPU2_CSI1_DATA19    0x1b0b0
                        MX6QDL_PAD_EIM_A16__IPU2_CSI1_PIXCLK    0x1b0b0
                >;
        };
+
+       pinctrl_tda1997x: tda1997xgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_7__GPIO1_IO07   0x1b0b0
+               >;
+       };
 };
index 45eb0b7..d96ae54 100644 (file)
@@ -21,6 +21,8 @@
 
        panel-lvds0 {
                compatible = "okaya,rs800480t-7x0gp";
+               power-supply = <&reg_lcd_reset>;
+               backlight = <&backlight>;
 
                port {
                        panel_in_lvds0: endpoint {
@@ -38,7 +40,6 @@
                regulator-max-microvolt = <3300000>;
                gpio = <&gpio4 17 GPIO_ACTIVE_HIGH>;
                enable-active-high;
-               regulator-always-on;
                vin-supply = <&reg_3v3>;
                startup-delay-us = <500000>;
        };
@@ -52,7 +53,6 @@
                regulator-max-microvolt = <3300000>;
                gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>;
                enable-active-high;
-               regulator-always-on;
                vin-supply = <&reg_lcd>;
        };
 };
index d8ccb53..84b30bd 100644 (file)
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-reset-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
index 2ce8399..bfff87c 100644 (file)
@@ -98,7 +98,7 @@
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
index 0f0743d..a1c5e69 100644 (file)
@@ -1,42 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
 /*
  * Copyright (C) 2016-2017 Zodiac Inflight Innovations
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     version 2 as published by the Free Software Foundation.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
index 1ebf29f..4738c3c 100644 (file)
@@ -51,7 +51,7 @@
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-reset-duration = <10>;
        phy-reset-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
        status = "okay";
index 397e205..70d2661 100644 (file)
@@ -77,8 +77,6 @@
 
        pwm_fan: pwm-fan {
                compatible = "pwm-fan";
-               cooling-min-state = <0>;
-               cooling-max-state = <4>;
                #cooling-cells = <2>;
                pwms = <&pwm4 0 50000>;
                cooling-levels = <0 64 127 191 255>;
index 81b2fcf..e4d1c52 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/sound/fsl-imx-audmux.h>
 
 / {
        /* these are used by bootloader for disabling nodes */
                };
        };
 
-       sound {
+       sound-analog {
                compatible = "fsl,imx6q-ventana-sgtl5000",
                             "fsl,imx-audio-sgtl5000";
                model = "sgtl5000-audio";
                ssi-controller = <&ssi1>;
-               audio-codec = <&codec>;
+               audio-codec = <&sgtl5000>;
                audio-routing =
                        "MIC_IN", "Mic Jack",
                        "Mic Jack", "Mic Bias",
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_audmux>; /* AUD4<->sgtl5000 */
        status = "okay";
+
+       ssi2 {
+               fsl,audmux-port = <1>;
+               fsl,port-config = <
+                       (IMX_AUDMUX_V2_PTCR_TFSDIR |
+                       IMX_AUDMUX_V2_PTCR_TFSEL(4+8) | /* RXFS */
+                       IMX_AUDMUX_V2_PTCR_TCLKDIR |
+                       IMX_AUDMUX_V2_PTCR_TCSEL(4+8) | /* RXC */
+                       IMX_AUDMUX_V2_PTCR_SYN)
+                       IMX_AUDMUX_V2_PDCR_RXDSEL(4)
+               >;
+       };
+
+       aud5 {
+               fsl,audmux-port = <4>;
+               fsl,port-config = <
+                       IMX_AUDMUX_V2_PTCR_SYN
+                       IMX_AUDMUX_V2_PDCR_RXDSEL(1)>;
+       };
 };
 
 &can1 {
        pinctrl-0 = <&pinctrl_i2c3>;
        status = "okay";
 
-       codec: sgtl5000@a {
+       sgtl5000: audio-codec@a {
                compatible = "fsl,sgtl5000";
                reg = <0x0a>;
                clocks = <&clks IMX6QDL_CLK_CKO>;
                        MX6QDL_PAD_SD2_DAT2__AUD4_TXD           0x110b0
                        MX6QDL_PAD_SD2_DAT1__AUD4_TXFS          0x130b0
                        MX6QDL_PAD_GPIO_0__CCM_CLKO1            0x130b0 /* AUD4_MCK */
+                       MX6QDL_PAD_EIM_D25__AUD5_RXC            0x130b0
+                       MX6QDL_PAD_DISP0_DAT19__AUD5_RXD        0x130b0
+                       MX6QDL_PAD_EIM_D24__AUD5_RXFS           0x130b0
                >;
        };
 
index 8e46a80..c23ba22 100644 (file)
@@ -46,6 +46,8 @@
  */
 
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/media/tda1997x.h>
+#include <dt-bindings/sound/fsl-imx-audmux.h>
 
 / {
        /* these are used by bootloader for disabling nodes */
                regulator-min-microvolt = <5000000>;
                regulator-max-microvolt = <5000000>;
        };
+
+       sound-digital {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "tda1997x-audio";
+
+               simple-audio-card,dai-link@0 {
+                       format = "i2s";
+
+                       cpu {
+                               sound-dai = <&ssi2>;
+                       };
+
+                       codec {
+                               bitclock-master;
+                               frame-master;
+                               sound-dai = <&hdmi_receiver>;
+                       };
+               };
+       };
+};
+
+&audmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_audmux>; /* AUD5<->tda1997x */
+       status = "okay";
+
+       ssi1 {
+               fsl,audmux-port = <0>;
+               fsl,port-config = <
+                       (IMX_AUDMUX_V2_PTCR_TFSDIR |
+                       IMX_AUDMUX_V2_PTCR_TFSEL(4+8) | /* RXFS */
+                       IMX_AUDMUX_V2_PTCR_TCLKDIR |
+                       IMX_AUDMUX_V2_PTCR_TCSEL(4+8) | /* RXC */
+                       IMX_AUDMUX_V2_PTCR_SYN)
+                       IMX_AUDMUX_V2_PDCR_RXDSEL(4)
+               >;
+       };
+
+       aud5 {
+               fsl,audmux-port = <4>;
+               fsl,port-config = <
+                       IMX_AUDMUX_V2_PTCR_SYN
+                       IMX_AUDMUX_V2_PDCR_RXDSEL(0)>;
+       };
 };
 
 &can1 {
                #gpio-cells = <2>;
        };
 
+       hdmi_receiver: hdmi-receiver@48 {
+               compatible = "nxp,tda19971";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_tda1997x>;
+               reg = <0x48>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+               DOVDD-supply = <&reg_3p3>;
+               AVDD-supply = <&reg_1p8b>;
+               DVDD-supply = <&reg_1p8a>;
+               #sound-dai-cells = <0>;
+               nxp,audout-format = "i2s";
+               nxp,audout-layout = <0>;
+               nxp,audout-width = <16>;
+               nxp,audout-mclk-fs = <128>;
+               /*
+                * The 8bpp YUV422 semi-planar mode outputs CbCr[11:4]
+                * and Y[11:4] across 16bits in the same cycle
+                * which we map to VP[15:08]<->CSI_DATA[19:12]
+                */
+               nxp,vidout-portcfg =
+                       /*G_Y_11_8<->VP[15:12]<->CSI_DATA[19:16]*/
+                       < TDA1997X_VP24_V15_12 TDA1997X_G_Y_11_8 >,
+                       /*G_Y_7_4<->VP[11:08]<->CSI_DATA[15:12]*/
+                       < TDA1997X_VP24_V11_08 TDA1997X_G_Y_7_4 >,
+                       /*R_CR_CBCR_11_8<->VP[07:04]<->CSI_DATA[11:08]*/
+                       < TDA1997X_VP24_V07_04 TDA1997X_R_CR_CBCR_11_8 >,
+                       /*R_CR_CBCR_7_4<->VP[03:00]<->CSI_DATA[07:04]*/
+                       < TDA1997X_VP24_V03_00 TDA1997X_R_CR_CBCR_7_4 >;
+
+               port {
+                       tda1997x_to_ipu1_csi0_mux: endpoint {
+                               remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
+                               bus-width = <16>;
+                               hsync-active = <1>;
+                               vsync-active = <1>;
+                               data-active = <1>;
+                       };
+               };
+       };
+};
+
+&ipu1_csi0_from_ipu1_csi0_mux {
+       bus-width = <16>;
+};
+
+&ipu1_csi0_mux_from_parallel_sensor {
+       remote-endpoint = <&tda1997x_to_ipu1_csi0_mux>;
+       bus-width = <16>;
+};
+
+&ipu1_csi0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ipu1_csi0>;
 };
 
 &pcie {
 };
 
 &iomuxc {
+       pinctrl_audmux: audmuxgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_DISP0_DAT19__AUD5_RXD        0x130b0
+                       MX6QDL_PAD_DISP0_DAT14__AUD5_RXC        0x130b0
+                       MX6QDL_PAD_DISP0_DAT13__AUD5_RXFS       0x130b0
+               >;
+       };
+
        pinctrl_flexcan1: flexcan1grp {
                fsl,pins = <
                        MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX        0x1b0b1
                >;
        };
 
+       pinctrl_ipu1_csi0: ipu1_csi0grp {
+               fsl,pins = <
+                       MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04          0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05          0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06          0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07          0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08          0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09          0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18         0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19         0x1b0b0
+                       MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC           0x1b0b0
+                       MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK        0x1b0b0
+                       MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC          0x1b0b0
+               >;
+       };
+
        pinctrl_pcie: pciegrp {
                fsl,pins = <
                        MX6QDL_PAD_GPIO_0__GPIO1_IO00           0x1b0b0 /* PCIE RST */
                >;
        };
 
+       pinctrl_tda1997x: tda1997xgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_7__GPIO1_IO07           0x1b0b0
+               >;
+       };
+
        pinctrl_uart2: uart2grp {
                fsl,pins = <
                        MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA      0x1b0b1
index 9cb9a74..aee9221 100644 (file)
        tlv320aic3105: codec@18 {
                compatible = "ti,tlv320aic3x";
                reg = <0x18>;
-               gpio-reset = <&gpio5 17 GPIO_ACTIVE_LOW>;
+               reset-gpios = <&gpio5 17 GPIO_ACTIVE_LOW>;
                clocks = <&clks IMX6QDL_CLK_CKO>;
                ai3x-micbias-vg = <2>; /* MICBIAS_2_5V */
                /* Regulators */
index 027df06..7e53ac6 100644 (file)
@@ -79,7 +79,7 @@
        status = "okay";
        cs-gpios = <&gpio4 24 0>;
 
-       flash@0 {
+       som_flash: flash@0 {
                compatible = "m25p80", "jedec,spi-nor";
                spi-max-frequency = <20000000>;
                reg = <0>;
        pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
 
-       eeprom@50 {
+       som_eeprom: eeprom@50 {
                compatible = "atmel,24c32";
                reg = <0x50>;
        };
index 1280de5..f3404dd 100644 (file)
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
                              <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
        fsl,err006687-workaround-present;
index a070506..185fb17 100644 (file)
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
index 4ccb7af..6d7f6b9 100644 (file)
@@ -53,7 +53,7 @@
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_microsom_enet_ar8035>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-reset-duration = <2>;
        phy-reset-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>;
        status = "okay";
index 8752a49..c41cac5 100644 (file)
                IOVDD-supply = <&reg_3p3v>;
                DVDD-supply = <&reg_3p3v>;
                ai3x-ocmv = <0>;
-               gpio-reset = <&gpio5 5 GPIO_ACTIVE_LOW>;
+               reset-gpios = <&gpio5 5 GPIO_ACTIVE_LOW>;
        };
 };
 
index b7d5fb4..50d9a98 100644 (file)
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-reset-gpios = <&gpio3 29 GPIO_ACTIVE_LOW>;
        interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
                              <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
index 69942c7..93be00a 100644 (file)
@@ -1,42 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
 /*
  * Copyright (C) 2016-2017 Zodiac Inflight Innovations
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     version 2 as published by the Free Software Foundation.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , 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.
  */
 
 #include <dt-bindings/gpio/gpio.h>
 
        panel {
                power-supply = <&reg_3p3v_display>;
+               backlight = <&sp_backlight>;
                status = "disabled";
 
                port {
                        compatible = "zii,rave-sp-watchdog";
                };
 
-               backlight {
+               sp_backlight: backlight {
                        compatible = "zii,rave-sp-backlight";
                };
 
                AVDD-supply = <&reg_3p3v>;
                IOVDD-supply = <&reg_3p3v>;
                DVDD-supply = <&vgen4_reg>;
-               gpio-reset = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+               reset-gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
        };
 
        accel@1c {
                };
        };
 
+       watchdog@38 {
+               compatible = "zii,rave-wdt";
+               reg = <0x38>;
+       };
+
        temp-sense@48 {
                compatible = "national,lm75";
                reg = <0x48>;
                AVDD-supply = <&reg_3p3v>;
                IOVDD-supply = <&reg_3p3v>;
                DVDD-supply = <&vgen4_reg>;
-               gpio-reset = <&gpio1 0 GPIO_ACTIVE_HIGH>;
+               reset-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
        };
 
        touchscreen@20 {
index fe17a34..b3a77bc 100644 (file)
@@ -4,6 +4,7 @@
 // Copyright 2011 Linaro Ltd.
 
 #include <dt-bindings/clock/imx6qdl-clock.h>
+#include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 / {
                        ranges = <0x81000000 0 0          0x01f80000 0 0x00010000 /* downstream I/O */
                                  0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable memory */
                        num-lanes = <1>;
+                       num-viewport = <4>;
                        interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
                        interrupt-names = "msi";
                        #interrupt-cells = <1>;
                                        status = "disabled";
                                };
 
+                               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;
+                               };
+
                                snvs_lpgpr: snvs-lpgpr {
                                        compatible = "fsl,imx6q-snvs-lpgpr";
                                };
                                compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
                                reg = <0x020ec000 0x4000>;
                                interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks IMX6QDL_CLK_SDMA>,
+                               clocks = <&clks IMX6QDL_CLK_IPG>,
                                         <&clks IMX6QDL_CLK_SDMA>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
                                reg = <0x021ac000 0x4000>;
                        };
 
-                       mmdc0: mmdc@21b0000 { /* MMDC0 */
+                       mmdc0: memory-controller@21b0000 { /* MMDC0 */
                                compatible = "fsl,imx6q-mmdc";
                                reg = <0x021b0000 0x4000>;
                                clocks = <&clks IMX6QDL_CLK_MMDC_P0_IPG>;
                        };
 
-                       mmdc1: mmdc@21b4000 { /* MMDC1 */
+                       mmdc1: memory-controller@21b4000 { /* MMDC1 */
+                               compatible = "fsl,imx6q-mmdc";
                                reg = <0x021b4000 0x4000>;
+                               status = "disabled";
                        };
 
                        weim: weim@21b8000 {
index 98bf7a6..57de447 100644 (file)
@@ -1,42 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
 /*
  * Copyright (C) 2016-2017 Zodiac Inflight Innovations
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     version 2 as published by the Free Software Foundation.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
index 4b4813f..9ddbeea 100644 (file)
                gpio2 = &gpio3;
                gpio3 = &gpio4;
                gpio4 = &gpio5;
+               i2c0 = &i2c1;
+               i2c1 = &i2c2;
+               i2c2 = &i2c3;
+               mmc0 = &usdhc1;
+               mmc1 = &usdhc2;
+               mmc2 = &usdhc3;
+               mmc3 = &usdhc4;
                serial0 = &uart1;
                serial1 = &uart2;
                serial2 = &uart3;
                                reg = <0x020ec000 0x4000>;
                                interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_SDMA>,
-                                        <&clks IMX6SL_CLK_SDMA>;
+                                        <&clks IMX6SL_CLK_AHB>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
                                /* imx6sl reuses imx6q sdma firmware */
                                status = "disabled";
                        };
 
-                       mmdc: mmdc@21b0000 {
+                       memory-controller@21b0000 {
                                compatible = "fsl,imx6sl-mmdc", "fsl,imx6q-mmdc";
                                reg = <0x021b0000 0x4000>;
                                clocks = <&clks IMX6SL_CLK_MMDC_P0_IPG>;
index 62847c6..1b4899f 100644 (file)
@@ -64,6 +64,7 @@
                                198000          1175000
                        >;
                        clock-latency = <61036>; /* two CLK32 periods */
+                       #cooling-cells = <2>;
                        clocks = <&clks IMX6SLL_CLK_ARM>,
                                 <&clks IMX6SLL_CLK_PLL2_PFD2>,
                                 <&clks IMX6SLL_CLK_STEP>,
                                compatible = "fsl,imx6sll-sdma", "fsl,imx35-sdma";
                                reg = <0x020ec000 0x4000>;
                                interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks IMX6SLL_CLK_SDMA>,
+                               clocks = <&clks IMX6SLL_CLK_IPG>,
                                         <&clks IMX6SLL_CLK_SDMA>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
index b0ee324..315044c 100644 (file)
@@ -75,7 +75,7 @@
 &fec1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet1>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-handle = <&ethphy1>;
        fsl,magic-packet;
        status = "okay";
index 08ede56..f6972de 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet1>;
        phy-supply = <&reg_enet_3v3>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-handle = <&ethphy1>;
        phy-reset-gpios = <&gpio2 7 GPIO_ACTIVE_LOW>;
        status = "okay";
index 5b16e65..b16a123 100644 (file)
                                compatible = "fsl,imx6sx-sdma", "fsl,imx6q-sdma";
                                reg = <0x020ec000 0x4000>;
                                interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks IMX6SX_CLK_SDMA>,
+                               clocks = <&clks IMX6SX_CLK_IPG>,
                                         <&clks IMX6SX_CLK_SDMA>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
                                status = "disabled";
                        };
 
-                       mmdc: mmdc@21b0000 {
+                       memory-controller@21b0000 {
                                compatible = "fsl,imx6sx-mmdc", "fsl,imx6q-mmdc";
                                reg = <0x021b0000 0x4000>;
                                clocks = <&clks IMX6SX_CLK_MMDC_P0_IPG>;
index 62ed30c..bbf010c 100644 (file)
                                             "fsl,imx35-sdma";
                                reg = <0x020ec000 0x4000>;
                                interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks IMX6UL_CLK_SDMA>,
+                               clocks = <&clks IMX6UL_CLK_IPG>,
                                         <&clks IMX6UL_CLK_SDMA>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
                                status = "disabled";
                        };
 
-                       mmdc: mmdc@21b0000 {
+                       memory-controller@21b0000 {
                                compatible = "fsl,imx6ul-mmdc", "fsl,imx6q-mmdc";
                                reg = <0x021b0000 0x4000>;
                                clocks = <&clks IMX6UL_CLK_MMDC_P0_IPG>;
diff --git a/arch/arm/boot/dts/imx7-mba7.dtsi b/arch/arm/boot/dts/imx7-mba7.dtsi
new file mode 100644 (file)
index 0000000..50abf18
--- /dev/null
@@ -0,0 +1,550 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
+/*
+ * Device Tree Include file for TQ Systems MBa7 carrier board.
+ *
+ * Copyright (C) 2016 TQ Systems GmbH
+ * Author: Markus Niebel <Markus.Niebel@tq-group.com>
+ * Copyright (C) 2019 Bruno Thomsen <bruno.thomsen@gmail.com>
+ *
+ * Note: This file does not include nodes for all peripheral devices.
+ * As device driver coverage increases additional nodes can be added.
+ */
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/net/ti-dp83867.h>
+
+/ {
+       beeper {
+               compatible = "gpio-beeper";
+               gpios = <&pca9555 0 GPIO_ACTIVE_HIGH>;
+       };
+
+       chosen {
+               stdout-path = &uart6;
+       };
+
+       gpio_buttons: gpio-keys {
+               compatible = "gpio-keys";
+
+               button-0 {
+                       /* #SWITCH_A */
+                       label = "S11";
+                       linux,code = <KEY_1>;
+                       gpios = <&pca9555 13 GPIO_ACTIVE_LOW>;
+               };
+
+               button-1 {
+                       /* #SWITCH_B */
+                       label = "S12";
+                       linux,code = <KEY_2>;
+                       gpios = <&pca9555 14 GPIO_ACTIVE_LOW>;
+               };
+
+               button-2 {
+                       /* #SWITCH_C */
+                       label = "S13";
+                       linux,code = <KEY_3>;
+                       gpios = <&pca9555 15 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       gpio-leds {
+               compatible = "gpio-leds";
+
+               led1 {
+                       label = "led1";
+                       gpios = <&pca9555 8 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "default-on";
+               };
+
+               led2 {
+                       label = "led2";
+                       gpios = <&pca9555 9 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       reg_sd1_vmmc: regulator-sd1-vmmc {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC3V3_SD1";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       reg_fec1_pwdn: regulator-fec1-pwdn {
+               compatible = "regulator-fixed";
+               regulator-name = "PWDN_FEC1";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+               gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_fec2_pwdn: regulator-fec2-pwdn {
+               compatible = "regulator-fixed";
+               regulator-name = "PWDN_FEC2";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+               gpio = <&gpio2 31 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "VBUS_USBOTG1";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_usb_otg2_vbus: regulator-usb-otg2-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "VBUS_USBOTG2";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_mpcie_1v5: regulator-mpcie-1v5 {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC1V5_MPCIE";
+               regulator-min-microvolt = <1500000>;
+               regulator-max-microvolt = <1500000>;
+               gpio = <&pca9555 12 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+               regulator-always-on;
+       };
+
+       reg_mpcie_3v3: regulator-mpcie-3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC3V3_MPCIE";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&pca9555 10 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+               regulator-always-on;
+       };
+
+       reg_mba_12v0: regulator-mba-12v0 {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC12V0_MBA7";
+               regulator-min-microvolt = <12000000>;
+               regulator-max-microvolt = <12000000>;
+               gpio = <&pca9555 11 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_lvds_transmitter: regulator-lvds-transmitter {
+               compatible = "regulator-fixed";
+               regulator-name = "#SHTDN_LVDS";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&pca9555 1 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_vref_1v8: regulator-vref-1v8 {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC1V8_REF";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-always-on;
+               vin-supply = <&sw2_reg>;
+       };
+
+       reg_audio_3v3: regulator-audio-3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC3V3_AUDIO";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+};
+
+&adc1 {
+       vref-supply = <&reg_vref_1v8>;
+       status = "okay";
+};
+
+&adc2 {
+       vref-supply = <&reg_vref_1v8>;
+       status = "okay";
+};
+
+&ecspi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ecspi1>;
+       num-chipselects = <3>;
+       cs-gpios = <&gpio4 0 GPIO_ACTIVE_LOW>, <&gpio4 1 GPIO_ACTIVE_LOW>,
+                  <&gpio4 2 GPIO_ACTIVE_LOW>;
+       status = "okay";
+};
+
+&ecspi2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ecspi2>;
+       num-chipselects = <1>;
+       status = "okay";
+};
+
+&fec1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet1>;
+       phy-mode = "rgmii-id";
+       phy-reset-gpios = <&gpio7 15 GPIO_ACTIVE_LOW>;
+       phy-reset-duration = <1>;
+       phy-reset-delay = <1>;
+       phy-supply = <&reg_fec1_pwdn>;
+       phy-handle = <&ethphy1_0>;
+       fsl,magic-packet;
+       status = "okay";
+
+       mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               ethphy1_0: ethernet-phy@0 {
+                       compatible = "ethernet-phy-ieee802.3-c22";
+                       reg = <0>;
+                       ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_50_NS>;
+                       ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_50_NS>;
+                       ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+                       /* LED1: Link/Activity, LED2: Error */
+                       ti,led-function = <0x0db0>;
+                       /* Active low, LED1 and LED2 driven by phy */
+                       ti,led-ctrl = <0x1001>;
+               };
+       };
+};
+
+&flexcan1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_flexcan1>;
+       status = "okay";
+};
+
+&flexcan2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_flexcan2>;
+       status = "okay";
+};
+
+&i2c1 {
+       lm75: temperature-sensor@49 {
+               compatible = "national,lm75";
+               reg = <0x49>;
+       };
+};
+
+&i2c2 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+
+       tlv320aic32x4: audio-codec@18 {
+               compatible = "ti,tlv320aic32x4";
+               reg = <0x18>;
+               clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+               clock-names = "mclk";
+               ldoin-supply = <&reg_audio_3v3>;
+               iov-supply = <&reg_audio_3v3>;
+       };
+
+       pca9555: gpio-expander@20 {
+               compatible = "nxp,pca9555";
+               reg = <0x20>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_pca9555>;
+               gpio-controller;
+               #gpio-cells = <2>;
+               interrupt-parent = <&gpio7>;
+               interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+};
+
+&i2c3 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hog_mba7_1>;
+
+       pinctrl_ecspi1: ecspi1grp {
+               fsl,pins = <
+                       MX7D_PAD_ECSPI1_MISO__ECSPI1_MISO               0x7c
+                       MX7D_PAD_ECSPI1_MOSI__ECSPI1_MOSI               0x74
+                       MX7D_PAD_ECSPI1_SCLK__ECSPI1_SCLK               0x74
+                       MX7D_PAD_UART1_RX_DATA__GPIO4_IO0               0x74
+                       MX7D_PAD_UART1_TX_DATA__GPIO4_IO1               0x74
+                       MX7D_PAD_UART2_RX_DATA__GPIO4_IO2               0x74
+               >;
+       };
+
+       pinctrl_ecspi2: ecspi2grp {
+               fsl,pins = <
+                       MX7D_PAD_ECSPI2_MISO__ECSPI2_MISO               0x7c
+                       MX7D_PAD_ECSPI2_MOSI__ECSPI2_MOSI               0x74
+                       MX7D_PAD_ECSPI2_SCLK__ECSPI2_SCLK               0x74
+                       MX7D_PAD_ECSPI2_SS0__ECSPI2_SS0                 0x74
+               >;
+       };
+
+       pinctrl_enet1: enet1grp {
+               fsl,pins = <
+                       MX7D_PAD_GPIO1_IO10__ENET1_MDIO                 0x02
+                       MX7D_PAD_GPIO1_IO11__ENET1_MDC                  0x00
+                       MX7D_PAD_ENET1_RGMII_TXC__ENET1_RGMII_TXC       0x71
+                       MX7D_PAD_ENET1_RGMII_TD0__ENET1_RGMII_TD0       0x71
+                       MX7D_PAD_ENET1_RGMII_TD1__ENET1_RGMII_TD1       0x71
+                       MX7D_PAD_ENET1_RGMII_TD2__ENET1_RGMII_TD2       0x71
+                       MX7D_PAD_ENET1_RGMII_TD3__ENET1_RGMII_TD3       0x71
+                       MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL 0x71
+                       MX7D_PAD_ENET1_RGMII_RXC__ENET1_RGMII_RXC       0x79
+                       MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0       0x79
+                       MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1       0x79
+                       MX7D_PAD_ENET1_RGMII_RD2__ENET1_RGMII_RD2       0x79
+                       MX7D_PAD_ENET1_RGMII_RD3__ENET1_RGMII_RD3       0x79
+                       MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL 0x79
+                       /* Reset: SION, 100kPU, SRE_FAST, DSE_X1 */
+                       MX7D_PAD_ENET1_COL__GPIO7_IO15          0x40000070
+                       /* INT/PWDN: SION, 100kPU, HYS, SRE_FAST, DSE_X1 */
+                       MX7D_PAD_GPIO1_IO09__GPIO1_IO9          0x40000078
+               >;
+       };
+
+       pinctrl_flexcan1: flexcan1grp {
+               fsl,pins = <
+                       MX7D_PAD_GPIO1_IO12__FLEXCAN1_RX        0x5a
+                       MX7D_PAD_GPIO1_IO13__FLEXCAN1_TX        0x52
+               >;
+       };
+
+       pinctrl_flexcan2: flexcan2grp {
+               fsl,pins = <
+                       MX7D_PAD_GPIO1_IO14__FLEXCAN2_RX        0x5a
+                       MX7D_PAD_GPIO1_IO15__FLEXCAN2_TX        0x52
+               >;
+       };
+
+       pinctrl_hog_mba7_1: hogmba71grp {
+               fsl,pins = <
+                       /* Limitation: WDOG2_B / WDOG2_RESET not usable */
+                       MX7D_PAD_ENET1_RX_CLK__GPIO7_IO13       0x4000007c
+                       MX7D_PAD_ENET1_CRS__GPIO7_IO14          0x40000074
+                       /* #BOOT_EN */
+                       MX7D_PAD_UART2_TX_DATA__GPIO4_IO3       0x40000010
+               >;
+       };
+
+       pinctrl_i2c2: i2c2grp {
+               fsl,pins = <
+                       MX7D_PAD_I2C2_SCL__I2C2_SCL             0x40000078
+                       MX7D_PAD_I2C2_SDA__I2C2_SDA             0x40000078
+               >;
+       };
+
+       pinctrl_i2c3: i2c3grp {
+               fsl,pins = <
+                       MX7D_PAD_I2C3_SCL__I2C3_SCL             0x40000078
+                       MX7D_PAD_I2C3_SDA__I2C3_SDA             0x40000078
+               >;
+       };
+
+
+       pinctrl_pca9555: pca95550grp {
+               fsl,pins = <
+                       MX7D_PAD_ENET1_TX_CLK__GPIO7_IO12       0x78
+               >;
+       };
+
+       pinctrl_uart3: uart3grp {
+               fsl,pins = <
+                       MX7D_PAD_UART3_RX_DATA__UART3_DCE_RX    0x7e
+                       MX7D_PAD_UART3_TX_DATA__UART3_DCE_TX    0x76
+                       MX7D_PAD_UART3_CTS_B__UART3_DCE_CTS     0x76
+                       MX7D_PAD_UART3_RTS_B__UART3_DCE_RTS     0x7e
+               >;
+       };
+
+       pinctrl_uart4: uart4grp {
+               fsl,pins = <
+                       MX7D_PAD_SAI2_TX_SYNC__UART4_DCE_RX     0x7e
+                       MX7D_PAD_SAI2_TX_BCLK__UART4_DCE_TX     0x76
+                       MX7D_PAD_SAI2_RX_DATA__UART4_DCE_CTS    0x76
+                       MX7D_PAD_SAI2_TX_DATA__UART4_DCE_RTS    0x7e
+               >;
+       };
+
+       pinctrl_uart5: uart5grp {
+               fsl,pins = <
+                       MX7D_PAD_I2C4_SCL__UART5_DCE_RX         0x7e
+                       MX7D_PAD_I2C4_SDA__UART5_DCE_TX         0x76
+               >;
+       };
+
+       pinctrl_uart6: uart6grp {
+               fsl,pins = <
+                       MX7D_PAD_EPDC_DATA08__UART6_DCE_RX      0x7d
+                       MX7D_PAD_EPDC_DATA09__UART6_DCE_TX      0x75
+                       MX7D_PAD_EPDC_DATA11__UART6_DCE_CTS     0x75
+                       MX7D_PAD_EPDC_DATA10__UART6_DCE_RTS     0x7d
+               >;
+       };
+
+       pinctrl_uart7: uart7grp {
+               fsl,pins = <
+                       MX7D_PAD_EPDC_DATA12__UART7_DCE_RX      0x7e
+                       MX7D_PAD_EPDC_DATA13__UART7_DCE_TX      0x76
+                       MX7D_PAD_EPDC_DATA15__UART7_DCE_CTS     0x76
+                       /* Limitation: RTS is not connected */
+                       MX7D_PAD_EPDC_DATA14__UART7_DCE_RTS     0x7e
+               >;
+       };
+
+       pinctrl_usdhc1_gpio: usdhc1grp_gpio {
+               fsl,pins = <
+                       /* WP */
+                       MX7D_PAD_SD1_WP__GPIO5_IO1              0x7c
+                       /* CD */
+                       MX7D_PAD_SD1_CD_B__GPIO5_IO0            0x7c
+                       /* VSELECT */
+                       MX7D_PAD_GPIO1_IO08__SD1_VSELECT        0x59
+               >;
+       };
+
+       pinctrl_usdhc1: usdhc1grp {
+               fsl,pins = <
+                       MX7D_PAD_SD1_CMD__SD1_CMD               0x5e
+                       MX7D_PAD_SD1_CLK__SD1_CLK               0x57
+                       MX7D_PAD_SD1_DATA0__SD1_DATA0           0x5e
+                       MX7D_PAD_SD1_DATA1__SD1_DATA1           0x5e
+                       MX7D_PAD_SD1_DATA2__SD1_DATA2           0x5e
+                       MX7D_PAD_SD1_DATA3__SD1_DATA3           0x5e
+               >;
+       };
+
+       pinctrl_usdhc1_100mhz: usdhc1grp_100mhz {
+               fsl,pins = <
+                       MX7D_PAD_SD1_CMD__SD1_CMD               0x5a
+                       MX7D_PAD_SD1_CLK__SD1_CLK               0x57
+                       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               0x57
+                       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_pwm1: pwm1grp {
+               fsl,pins = <
+                       /* LCD_CONTRAST */
+                       MX7D_PAD_LPSR_GPIO1_IO01__PWM1_OUT      0x50
+               >;
+       };
+
+       pinctrl_usbotg1: usbotg1grp {
+               fsl,pins = <
+                       MX7D_PAD_LPSR_GPIO1_IO04__USB_OTG1_OC   0x5c
+                       MX7D_PAD_LPSR_GPIO1_IO05__GPIO1_IO5     0x59
+               >;
+       };
+};
+
+&pwm1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm1>;
+       status = "okay";
+};
+
+&uart3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart3>;
+       assigned-clocks = <&clks IMX7D_UART3_ROOT_SRC>;
+       assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
+       status = "okay";
+};
+
+&uart4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart4>;
+       assigned-clocks = <&clks IMX7D_UART4_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_OSC_24M_CLK>;
+       status = "okay";
+};
+
+&uart6 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart6>;
+       assigned-clocks = <&clks IMX7D_UART6_ROOT_SRC>;
+       assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
+       status = "okay";
+};
+
+&uart7 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart7>;
+       assigned-clocks = <&clks IMX7D_UART7_ROOT_SRC>;
+       assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
+       uart-has-rtscts;
+       status = "okay";
+};
+
+&usbh {
+       status = "okay";
+};
+
+&usbotg1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg1>;
+       vbus-supply = <&reg_usb_otg1_vbus>;
+       srp-disable;
+       hnp-disable;
+       adp-disable;
+       dr_mode = "host";
+       status = "okay";
+};
+
+&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>;
+       vmmc-supply = <&reg_sd1_vmmc>;
+       bus-width = <4>;
+       no-1-8-v;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7-tqma7.dtsi b/arch/arm/boot/dts/imx7-tqma7.dtsi
new file mode 100644 (file)
index 0000000..9aaed85
--- /dev/null
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
+/*
+ * Device Tree Include file for TQ Systems TQMa7x boards with full mounted PCB.
+ *
+ * Copyright (C) 2016 TQ Systems GmbH
+ * Author: Markus Niebel <Markus.Niebel@tq-group.com>
+ * Copyright (C) 2019 Bruno Thomsen <bruno.thomsen@gmail.com>
+ */
+
+/ {
+       memory@80000000 {
+               device_type = "memory";
+               /* 512 MB - default configuration */
+               reg = <0x80000000 0x20000000>;
+       };
+};
+
+&cpu0 {
+       arm-supply = <&sw1a_reg>;
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       clock-frequency = <100000>;
+       status = "okay";
+
+       pfuze3000: pmic@8 {
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_pmic1>;
+               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>;
+                               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;
+                       };
+               };
+       };
+
+       /* NXP SE97BTP with temperature sensor + eeprom */
+       se97b: temperature-sensor-eeprom@1e {
+               compatible = "nxp,se97b", "jedec,jc-42.4-temp";
+               reg = <0x1e>;
+               status = "okay";
+       };
+
+       /* ST M24C64 */
+       m24c64: eeprom@50 {
+               compatible = "atmel,24c64";
+               reg = <0x50>;
+               pagesize = <32>;
+               status = "okay";
+       };
+
+       at24c02: eeprom@56 {
+               compatible = "atmel,24c02";
+               reg = <0x56>;
+               pagesize = <16>;
+               status = "okay";
+       };
+
+       ds1339: rtc@68 {
+               compatible = "dallas,ds1339";
+               reg = <0x68>;
+       };
+};
+
+&iomuxc {
+       pinctrl_i2c1: i2c1grp {
+               fsl,pins = <
+                       MX7D_PAD_I2C1_SDA__I2C1_SDA     0x40000078
+                       MX7D_PAD_I2C1_SCL__I2C1_SCL     0x40000078
+               >;
+       };
+
+       pinctrl_pmic1: pmic1grp {
+               fsl,pins = <
+                       MX7D_PAD_SD2_RESET_B__GPIO5_IO11        0x4000005C
+               >;
+       };
+
+       pinctrl_usdhc3: usdhc3grp {
+               fsl,pins = <
+                       MX7D_PAD_SD3_CMD__SD3_CMD               0x59
+                       MX7D_PAD_SD3_CLK__SD3_CLK               0x56
+                       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_100mhz: usdhc3grp_100mhz {
+               fsl,pins = <
+                       MX7D_PAD_SD3_CMD__SD3_CMD               0x5a
+                       MX7D_PAD_SD3_CLK__SD3_CLK               0x51
+                       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_200mhz: usdhc3grp_200mhz {
+               fsl,pins = <
+                       MX7D_PAD_SD3_CMD__SD3_CMD               0x5b
+                       MX7D_PAD_SD3_CLK__SD3_CLK               0x51
+                       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
+               >;
+       };
+};
+
+&iomuxc_lpsr {
+       pinctrl_wdog1: wdog1grp {
+               fsl,pins = <
+                       MX7D_PAD_LPSR_GPIO1_IO00__WDOG1_WDOG_B  0x30
+               >;
+       };
+};
+
+&sdma {
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default", "state_100mhz", "state_200mhz";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+       assigned-clocks = <&clks IMX7D_USDHC3_ROOT_CLK>;
+       assigned-clock-rates = <400000000>;
+       bus-width = <8>;
+       non-removable;
+       vmmc-supply = <&vgen4_reg>;
+       vqmmc-supply = <&sw2_reg>;
+       status = "okay";
+};
+
+&wdog1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_wdog1>;
+       /*
+        * Errata e10574:
+        * WDOG reset needs to run with WDOG_RESET_B signal enabled.
+        * X1-51 (WDOG1#) signal needs carrier board handling to reset
+        * TQMa7 on X1-22 (RESET_IN#).
+        */
+       fsl,ext-reset-output;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx7d-mba7.dts b/arch/arm/boot/dts/imx7d-mba7.dts
new file mode 100644 (file)
index 0000000..221274c
--- /dev/null
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
+/*
+ * Device Tree Source for TQ Systems TQMa7D board on MBa7 carrier board.
+ *
+ * Copyright (C) 2016 TQ Systems GmbH
+ * Author: Markus Niebel <Markus.Niebel@tq-group.com>
+ * Copyright (C) 2019 Bruno Thomsen <bruno.thomsen@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "imx7d-tqma7.dtsi"
+#include "imx7-mba7.dtsi"
+
+/ {
+       model = "TQ Systems TQMa7D board on MBa7 carrier board";
+       compatible = "tq,imx7d-mba7", "fsl,imx7d";
+};
+
+&fec2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet2>;
+       phy-mode = "rgmii-id";
+       phy-reset-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>;
+       phy-reset-duration = <1>;
+       phy-reset-delay = <1>;
+       phy-supply = <&reg_fec2_pwdn>;
+       phy-handle = <&ethphy2_0>;
+       fsl,magic-packet;
+       status = "okay";
+
+       mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               ethphy2_0: ethernet-phy@0 {
+                       compatible = "ethernet-phy-ieee802.3-c22";
+                       reg = <0>;
+                       ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_50_NS>;
+                       ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_50_NS>;
+                       ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+                       /* LED1: Link/Activity, LED2: error */
+                       ti,led-function = <0x0db0>;
+                       /* active low, LED1/2 driven by phy */
+                       ti,led-ctrl = <0x1001>;
+               };
+       };
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hog_mba7_1>;
+
+       pinctrl_enet2: enet2grp {
+               fsl,pins = <
+                       MX7D_PAD_SD2_CD_B__ENET2_MDIO                   0x02
+                       MX7D_PAD_SD2_WP__ENET2_MDC                      0x00
+                       MX7D_PAD_EPDC_GDSP__ENET2_RGMII_TXC             0x71
+                       MX7D_PAD_EPDC_SDCE2__ENET2_RGMII_TD0            0x71
+                       MX7D_PAD_EPDC_SDCE3__ENET2_RGMII_TD1            0x71
+                       MX7D_PAD_EPDC_GDCLK__ENET2_RGMII_TD2            0x71
+                       MX7D_PAD_EPDC_GDOE__ENET2_RGMII_TD3             0x71
+                       MX7D_PAD_EPDC_GDRL__ENET2_RGMII_TX_CTL          0x71
+                       MX7D_PAD_EPDC_SDCE1__ENET2_RGMII_RXC            0x79
+                       MX7D_PAD_EPDC_SDCLK__ENET2_RGMII_RD0            0x79
+                       MX7D_PAD_EPDC_SDLE__ENET2_RGMII_RD1             0x79
+                       MX7D_PAD_EPDC_SDOE__ENET2_RGMII_RD2             0x79
+                       MX7D_PAD_EPDC_SDSHR__ENET2_RGMII_RD3            0x79
+                       MX7D_PAD_EPDC_SDCE0__ENET2_RGMII_RX_CTL         0x79
+                       /* Reset: SION, 100kPU, SRE_FAST, DSE_X1 */
+                       MX7D_PAD_EPDC_BDR0__GPIO2_IO28          0x40000070
+                       /* INT/PWDN: SION, 100kPU, HYS, SRE_FAST, DSE_X1 */
+                       MX7D_PAD_EPDC_PWR_STAT__GPIO2_IO31      0x40000078
+               >;
+       };
+
+       pinctrl_pcie: pciegrp {
+               fsl,pins = <
+                       /* #pcie_wake */
+                       MX7D_PAD_EPDC_PWR_COM__GPIO2_IO30               0x70
+                       /* #pcie_rst */
+                       MX7D_PAD_SD2_CLK__GPIO5_IO12                    0x70
+                       /* #pcie_dis */
+                       MX7D_PAD_EPDC_BDR1__GPIO2_IO29                  0x70
+               >;
+       };
+};
+
+&iomuxc_lpsr {
+       pinctrl_usbotg2: usbotg2grp {
+               fsl,pins = <
+                       MX7D_PAD_LPSR_GPIO1_IO06__USB_OTG2_OC   0x5c
+                       MX7D_PAD_LPSR_GPIO1_IO07__GPIO1_IO7     0x59
+               >;
+       };
+};
+
+&pcie {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pcie>;
+       /* 1.5V logically from 3.3V */
+       /* probe deferral not supported */
+       /* pcie-bus-supply = <&reg_mpcie_1v5>; */
+       reset-gpio = <&gpio5 12 GPIO_ACTIVE_LOW>;
+       disable-gpio = <&gpio2 29 GPIO_ACTIVE_LOW>;
+       power-on-gpio = <&gpio2 30 GPIO_ACTIVE_LOW>;
+       status = "okay";
+};
+
+&usbotg2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg2>;
+       vbus-supply = <&reg_usb_otg2_vbus>;
+       srp-disable;
+       hnp-disable;
+       adp-disable;
+       dr_mode = "host";
+       status = "okay";
+};
index 3fd595a..6f50ebf 100644 (file)
@@ -92,7 +92,7 @@
                          <&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-mode = "rgmii-id";
        phy-handle = <&ethphy0>;
        fsl,magic-packet;
        phy-reset-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/imx7d-tqma7.dtsi b/arch/arm/boot/dts/imx7d-tqma7.dtsi
new file mode 100644 (file)
index 0000000..8ad3048
--- /dev/null
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
+/*
+ * Device Tree Include file for TQ Systems TQMa7D board with NXP i.MX7Dual SoC.
+ *
+ * Copyright (C) 2016 TQ Systems GmbH
+ * Author: Markus Niebel <Markus.Niebel@tq-group.com>
+ * Copyright (C) 2019 Bruno Thomsen <bruno.thomsen@gmail.com>
+ */
+
+#include "imx7d.dtsi"
+#include "imx7-tqma7.dtsi"
diff --git a/arch/arm/boot/dts/imx7d-zii-rpu2.dts b/arch/arm/boot/dts/imx7d-zii-rpu2.dts
new file mode 100644 (file)
index 0000000..3e467a9
--- /dev/null
@@ -0,0 +1,941 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Device tree file for ZII's RPU2 board
+ *
+ * RPU - Remote Peripheral Unit
+ *
+ * Copyright (C) 2019 Zodiac Inflight Innovations
+ */
+
+/dts-v1/;
+#include <dt-bindings/thermal/thermal.h>
+#include "imx7d.dtsi"
+
+/ {
+       model = "ZII RPU2 Board";
+       compatible = "zii,imx7d-rpu2", "fsl,imx7d";
+
+       chosen {
+               stdout-path = &uart1;
+       };
+
+       cs2000_ref: oscillator {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <24576000>;
+       };
+
+       cs2000_in_dummy: dummy-oscillator {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <0>;
+       };
+
+       gpio-leds {
+               compatible = "gpio-leds";
+               pinctrl-0 = <&pinctrl_leds_debug>;
+               pinctrl-names = "default";
+
+               debug {
+                       label = "zii:green:debug1";
+                       gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       iio-hwmon {
+               compatible = "iio-hwmon";
+               io-channels = <&adc1 0>, <&adc1 1>, <&adc1 2>, <&adc1 3>,
+                             <&adc2 1>;
+       };
+
+       reg_can1_stby: regulator-can1-stby {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_flexcan1_stby>;
+               regulator-name = "can1-3v3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_can2_stby: regulator-can2-stby {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_flexcan2_stby>;
+               regulator-name = "can2-3v3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_vref_1v8: regulator-vref-1v8 {
+               compatible = "regulator-fixed";
+               regulator-name = "vref-1v8";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-always-on;
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "GEN_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       reg_5p0v_main: regulator-5p0v-main {
+               compatible = "regulator-fixed";
+               regulator-name = "5V_MAIN";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+
+       sound1 {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "Audio Output 1";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,bitclock-master = <&sound1_codec>;
+               simple-audio-card,frame-master = <&sound1_codec>;
+               simple-audio-card,widgets =
+                       "Headphone", "Headphone Jack";
+               simple-audio-card,routing =
+                       "Headphone Jack", "HPLEFT",
+                       "Headphone Jack", "HPRIGHT",
+                       "LEFTIN", "HPL",
+                       "RIGHTIN", "HPR";
+               simple-audio-card,aux-devs = <&hpa1>;
+
+               simple-audio-card,cpu {
+                       sound-dai = <&sai1>;
+               };
+
+               sound1_codec: simple-audio-card,codec {
+                       sound-dai = <&codec1>;
+                       clocks = <&cs2000>;
+               };
+       };
+
+       sound2 {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "Audio Output 2";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,bitclock-master = <&sound2_codec>;
+               simple-audio-card,frame-master = <&sound2_codec>;
+               simple-audio-card,widgets =
+                       "Headphone", "Headphone Jack";
+               simple-audio-card,routing =
+                       "Headphone Jack", "HPLEFT",
+                       "Headphone Jack", "HPRIGHT",
+                       "LEFTIN", "HPL",
+                       "RIGHTIN", "HPR";
+               simple-audio-card,aux-devs = <&hpa2>;
+
+               simple-audio-card,cpu {
+                       sound-dai = <&sai2>;
+               };
+
+               sound2_codec: simple-audio-card,codec {
+                       sound-dai = <&codec2>;
+                       clocks = <&cs2000>;
+               };
+       };
+
+       sound3 {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "Audio Output 3";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,bitclock-master = <&sound3_codec>;
+               simple-audio-card,frame-master = <&sound3_codec>;
+               simple-audio-card,widgets =
+                       "Headphone", "Headphone Jack";
+               simple-audio-card,routing =
+                       "Headphone Jack", "HPLEFT",
+                       "Headphone Jack", "HPRIGHT",
+                       "LEFTIN", "HPL",
+                       "RIGHTIN", "HPR";
+               simple-audio-card,aux-devs = <&hpa3>;
+
+               simple-audio-card,cpu {
+                       sound-dai = <&sai3>;
+               };
+
+               sound3_codec: simple-audio-card,codec {
+                       sound-dai = <&codec3>;
+                       clocks = <&cs2000>;
+               };
+       };
+};
+
+&adc1 {
+       vref-supply = <&reg_vref_1v8>;
+       status = "okay";
+};
+
+&adc2 {
+       vref-supply = <&reg_vref_1v8>;
+       status = "okay";
+};
+
+&cpu0 {
+       arm-supply = <&sw1a_reg>;
+};
+
+&clks {
+       assigned-clocks = <&clks IMX7D_PLL_AUDIO_POST_DIV>;
+       assigned-clock-rates = <884736000>;
+};
+
+&ecspi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ecspi1>;
+       cs-gpios = <&gpio4 19 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+
+       flash@0 {
+               compatible = "jedec,spi-nor";
+               spi-max-frequency = <20000000>;
+               reg = <0>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+       };
+};
+
+&fec1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet1>;
+       assigned-clocks = <&clks IMX7D_ENET1_TIME_ROOT_SRC>,
+                         <&clks IMX7D_ENET1_TIME_ROOT_CLK>;
+       assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
+       assigned-clock-rates = <0>, <100000000>;
+       phy-mode = "rgmii";
+       status = "okay";
+
+       fixed-link {
+               speed = <1000>;
+               full-duplex;
+       };
+
+       mdio1: mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "okay";
+
+               switch: switch@0 {
+                       compatible = "marvell,mv88e6085";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_switch>;
+                       reg = <0>;
+                       eeprom-length = <512>;
+                       interrupt-parent = <&gpio1>;
+                       interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       label = "eth_cu_1000_1";
+                               };
+
+                               port@1 {
+                                       reg = <1>;
+                                       label = "eth_cu_1000_2";
+                               };
+
+                               port@2 {
+                                       reg = <2>;
+                                       label = "pic";
+
+                                       fixed-link {
+                                               speed = <100>;
+                                               full-duplex;
+                                       };
+                               };
+
+                               port@5 {
+                                       reg = <5>;
+                                       label = "cpu";
+                                       ethernet = <&fec1>;
+                                       phy-mode = "rgmii-id";
+
+                                       fixed-link {
+                                               speed = <1000>;
+                                               full-duplex;
+                                       };
+                               };
+
+                               port@6 {
+                                       reg = <6>;
+                                       label = "gigabit_proc";
+                                       ethernet = <&fec2>;
+                                       phy-mode = "rgmii-id";
+
+                                       fixed-link {
+                                               speed = <1000>;
+                                               full-duplex;
+                                       };
+                               };
+                       };
+               };
+       };
+};
+
+&fec2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet2>;
+       assigned-clocks = <&clks IMX7D_ENET2_TIME_ROOT_SRC>,
+                         <&clks IMX7D_ENET2_TIME_ROOT_CLK>;
+       assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
+       assigned-clock-rates = <0>, <100000000>;
+       phy-mode = "rgmii";
+       fsl,magic-packet;
+       status = "okay";
+
+       fixed-link {
+               speed = <1000>;
+               full-duplex;
+       };
+};
+
+&flexcan1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_flexcan1>;
+       xceiver-supply = <&reg_can1_stby>;
+       status = "okay";
+};
+
+&flexcan2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_flexcan2>;
+       xceiver-supply = <&reg_can2_stby>;
+       status = "okay";
+};
+
+&gpio1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_gpio1>;
+
+       gpio-line-names = "", "", "", "", "", "", "", "",
+                         "", "",
+                         "usb_1_en_b",
+                         "usb_2_en_b",
+                         "", "", "", "", "", "", "", "",
+                         "", "", "", "", "", "", "", "",
+                         "", "", "", "";
+};
+
+&gpio2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_gpio2>;
+
+       gpio-line-names = "12v_out_en_1",
+                         "12v_out_en_2",
+                         "12v_out_en_3",
+                         "28v_out_en_5",
+                         "28v_out_en_1",
+                         "28v_out_en_2",
+                         "28v_out_en_3",
+                         "28v_out_en_4",
+                         "", "",
+                         "usb_3_en_b",
+                         "usb_4_en_b",
+                         "", "", "", "", "", "", "", "",
+                         "", "", "", "", "", "", "", "",
+                         "", "", "", "";
+};
+
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       pmic: pmic@8 {
+               compatible = "fsl,pfuze3000";
+               reg = <0x08>;
+
+               regulators {
+                       sw1a_reg: sw1a {
+                               regulator-min-microvolt = <700000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-ramp-delay = <6250>;
+                       };
+
+                       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>;
+                               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;
+                       };
+               };
+       };
+
+       cs2000: clkgen@4e {
+               compatible = "cirrus,cs2000-cp";
+               reg = <0x4e>;
+               #clock-cells = <0>;
+               clock-names = "clk_in", "ref_clk";
+               clocks = <&cs2000_in_dummy>, <&cs2000_ref>;
+               assigned-clocks = <&cs2000>;
+               assigned-clock-rates = <24000000>;
+       };
+
+       eeprom@50 {
+               compatible = "atmel,24c04";
+               reg = <0x50>;
+       };
+
+       eeprom@52 {
+               compatible = "atmel,24c04";
+               reg = <0x52>;
+       };
+};
+
+&i2c2 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+
+       codec2: codec@18 {
+               compatible = "ti,tlv320dac3100";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_codec2>;
+               reg = <0x18>;
+               #sound-dai-cells = <0>;
+               HPVDD-supply = <&reg_3p3v>;
+               SPRVDD-supply = <&reg_3p3v>;
+               SPLVDD-supply = <&reg_3p3v>;
+               AVDD-supply = <&reg_3p3v>;
+               IOVDD-supply = <&reg_3p3v>;
+               DVDD-supply = <&vgen4_reg>;
+               gpio-reset = <&gpio1 6 GPIO_ACTIVE_LOW>;
+       };
+
+       hpa2: amp@60 {
+               compatible = "ti,tpa6130a2";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_tpa2>;
+               reg = <0x60>;
+               power-gpio = <&gpio3 27 GPIO_ACTIVE_HIGH>;
+               Vdd-supply = <&reg_5p0v_main>;
+       };
+};
+
+&i2c3 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+
+       codec3: codec@18 {
+               compatible = "ti,tlv320dac3100";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_codec3>;
+               reg = <0x18>;
+               #sound-dai-cells = <0>;
+               HPVDD-supply = <&reg_3p3v>;
+               SPRVDD-supply = <&reg_3p3v>;
+               SPLVDD-supply = <&reg_3p3v>;
+               AVDD-supply = <&reg_3p3v>;
+               IOVDD-supply = <&reg_3p3v>;
+               DVDD-supply = <&vgen4_reg>;
+               gpio-reset = <&gpio1 7 GPIO_ACTIVE_LOW>;
+       };
+
+       hpa3: amp@60 {
+               compatible = "ti,tpa6130a2";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_tpa3>;
+               reg = <0x60>;
+               power-gpio = <&gpio3 28 GPIO_ACTIVE_HIGH>;
+               Vdd-supply = <&reg_5p0v_main>;
+       };
+};
+
+&i2c4 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c4>;
+       status = "okay";
+
+       codec1: codec@18 {
+               compatible = "ti,tlv320dac3100";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_codec1>;
+               reg = <0x18>;
+               #sound-dai-cells = <0>;
+               HPVDD-supply = <&reg_3p3v>;
+               SPRVDD-supply = <&reg_3p3v>;
+               SPLVDD-supply = <&reg_3p3v>;
+               AVDD-supply = <&reg_3p3v>;
+               IOVDD-supply = <&reg_3p3v>;
+               DVDD-supply = <&vgen4_reg>;
+               gpio-reset = <&gpio1 5 GPIO_ACTIVE_LOW>;
+       };
+
+       hpa1: amp@60 {
+               compatible = "ti,tpa6130a2";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_tpa1>;
+               reg = <0x60>;
+               power-gpio = <&gpio3 26 GPIO_ACTIVE_HIGH>;
+               Vdd-supply = <&reg_5p0v_main>;
+       };
+};
+
+&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";
+};
+
+&sai2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_sai2>;
+       assigned-clocks = <&clks IMX7D_SAI2_ROOT_SRC>,
+                         <&clks IMX7D_SAI2_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>;
+       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";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       assigned-clocks = <&clks IMX7D_UART2_ROOT_SRC>;
+       assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
+       status = "okay";
+};
+
+&uart4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart4>;
+       assigned-clocks = <&clks IMX7D_UART4_ROOT_SRC>;
+       assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>;
+       status = "okay";
+
+       rave-sp {
+               compatible = "zii,rave-sp-rdu2";
+               current-speed = <1000000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               watchdog {
+                       compatible = "zii,rave-sp-watchdog";
+               };
+
+               eeprom@a3 {
+                       compatible = "zii,rave-sp-eeprom";
+                       reg = <0xa3 0x4000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       zii,eeprom-name = "main-eeprom";
+               };
+       };
+};
+
+&usbotg1 {
+       dr_mode = "host";
+       disable-over-current;
+       status = "okay";
+};
+
+&usbotg2 {
+       dr_mode = "host";
+       disable-over-current;
+       status = "okay";
+};
+
+&usdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc1>;
+       bus-width = <4>;
+       no-1-8-v;
+       no-sdio;
+       keep-power-in-suspend;
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       bus-width = <8>;
+       no-1-8-v;
+       non-removable;
+       no-sdio;
+       no-sd;
+       keep-power-in-suspend;
+       status = "okay";
+};
+
+&wdog1 {
+       status = "disabled";
+};
+
+&snvs_rtc {
+       status = "disabled";
+};
+
+&snvs_pwrkey {
+       status = "disabled";
+};
+
+&iomuxc {
+       pinctrl_ecspi1: ecspi1grp {
+               fsl,pins = <
+                       MX7D_PAD_ECSPI1_SCLK__ECSPI1_SCLK       0x2
+                       MX7D_PAD_ECSPI1_MOSI__ECSPI1_MOSI       0x2
+                       MX7D_PAD_ECSPI1_MISO__ECSPI1_MISO       0x2
+                       MX7D_PAD_ECSPI1_SS0__GPIO4_IO19         0x59
+               >;
+       };
+
+       pinctrl_enet1: enet1grp {
+               fsl,pins = <
+                       MX7D_PAD_SD2_CD_B__ENET1_MDIO                           0x3
+                       MX7D_PAD_SD2_WP__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
+                       MX7D_PAD_UART1_TX_DATA__ENET2_1588_EVENT0_OUT           0x1
+               >;
+       };
+
+       pinctrl_flexcan1: flexcan1grp {
+               fsl,pins = <
+                       MX7D_PAD_GPIO1_IO12__FLEXCAN1_RX        0x59
+                       MX7D_PAD_GPIO1_IO13__FLEXCAN1_TX        0x59
+               >;
+       };
+
+       pinctrl_flexcan1_stby: flexcan1stbygrp {
+               fsl,pins = <
+                       MX7D_PAD_GPIO1_IO08__GPIO1_IO8          0x59
+               >;
+       };
+
+       pinctrl_flexcan2: flexcan2grp {
+               fsl,pins = <
+                       MX7D_PAD_GPIO1_IO14__FLEXCAN2_RX        0x59
+                       MX7D_PAD_GPIO1_IO15__FLEXCAN2_TX        0x59
+               >;
+       };
+
+       pinctrl_flexcan2_stby: flexcan2stbygrp {
+               fsl,pins = <
+                       MX7D_PAD_GPIO1_IO09__GPIO1_IO9          0x59
+               >;
+       };
+
+       pinctrl_gpio1: gpio1grp {
+               fsl,pins = <
+                       MX7D_PAD_GPIO1_IO10__GPIO1_IO10         0x00
+                       MX7D_PAD_GPIO1_IO11__GPIO1_IO11         0x00
+               >;
+       };
+
+       pinctrl_gpio2: gpio2grp {
+               fsl,pins = <
+                       MX7D_PAD_EPDC_DATA00__GPIO2_IO0         0x00
+                       MX7D_PAD_EPDC_DATA01__GPIO2_IO1         0x00
+                       MX7D_PAD_EPDC_DATA02__GPIO2_IO2         0x00
+                       MX7D_PAD_EPDC_DATA03__GPIO2_IO3         0x03
+                       MX7D_PAD_EPDC_DATA04__GPIO2_IO4         0x03
+                       MX7D_PAD_EPDC_DATA05__GPIO2_IO5         0x03
+                       MX7D_PAD_EPDC_DATA06__GPIO2_IO6         0x03
+                       MX7D_PAD_EPDC_DATA07__GPIO2_IO7         0x03
+                       MX7D_PAD_EPDC_DATA10__GPIO2_IO10        0x00
+                       MX7D_PAD_EPDC_DATA11__GPIO2_IO11        0x00
+               >;
+       };
+
+       pinctrl_i2c1: i2c1grp {
+               fsl,pins = <
+                       MX7D_PAD_I2C1_SDA__I2C1_SDA             0x4000007f
+                       MX7D_PAD_I2C1_SCL__I2C1_SCL             0x4000007f
+               >;
+       };
+
+       pinctrl_i2c1_gpio: i2c1gpiogrp {
+               fsl,pins = <
+                       MX7D_PAD_I2C1_SDA__GPIO4_IO9            0x4000007f
+                       MX7D_PAD_I2C1_SCL__GPIO4_IO8            0x4000007f
+               >;
+       };
+
+       pinctrl_i2c2: i2c2grp {
+               fsl,pins = <
+                       MX7D_PAD_I2C2_SDA__I2C2_SDA             0x4000007f
+                       MX7D_PAD_I2C2_SCL__I2C2_SCL             0x4000007f
+               >;
+       };
+
+       pinctrl_i2c2_gpio: i2c2gpiogrp {
+               fsl,pins = <
+                       MX7D_PAD_I2C2_SDA__GPIO4_IO11           0x4000007f
+                       MX7D_PAD_I2C2_SCL__GPIO4_IO10           0x4000007f
+               >;
+       };
+
+       pinctrl_i2c3: i2c3grp {
+               fsl,pins = <
+                       MX7D_PAD_I2C3_SDA__I2C3_SDA             0x4000007f
+                       MX7D_PAD_I2C3_SCL__I2C3_SCL             0x4000007f
+               >;
+       };
+
+       pinctrl_i2c3_gpio: i2c3gpiogrp {
+               fsl,pins = <
+                       MX7D_PAD_I2C3_SDA__GPIO4_IO13           0x4000007f
+                       MX7D_PAD_I2C3_SCL__GPIO4_IO12           0x4000007f
+               >;
+       };
+
+       pinctrl_i2c4: i2c4grp {
+               fsl,pins = <
+                       MX7D_PAD_I2C4_SDA__I2C4_SDA             0x4000007f
+                       MX7D_PAD_I2C4_SCL__I2C4_SCL             0x4000007f
+               >;
+       };
+
+       pinctrl_i2c4_gpio: i2c4gpiogrp {
+               fsl,pins = <
+                       MX7D_PAD_SAI1_RX_BCLK__GPIO6_IO17       0x4000007f
+                       MX7D_PAD_SAI1_RX_SYNC__GPIO6_IO16       0x4000007f
+               >;
+       };
+
+       pinctrl_leds_debug: debuggrp {
+               fsl,pins = <
+                       MX7D_PAD_EPDC_DATA08__GPIO2_IO8         0x59
+               >;
+       };
+
+       pinctrl_sai1: sai1grp {
+               fsl,pins = <
+                       MX7D_PAD_SAI1_TX_BCLK__SAI1_TX_BCLK     0x1f
+                       MX7D_PAD_SAI1_TX_SYNC__SAI1_TX_SYNC     0x1f
+                       MX7D_PAD_SAI1_TX_DATA__SAI1_TX_DATA0    0x30
+               >;
+       };
+
+       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
+               >;
+       };
+
+       pinctrl_sai3: sai3grp {
+               fsl,pins = <
+                       MX7D_PAD_UART3_TX_DATA__SAI3_TX_BCLK    0x1f
+                       MX7D_PAD_UART3_CTS_B__SAI3_TX_SYNC      0x1f
+                       MX7D_PAD_UART3_RTS_B__SAI3_TX_DATA0     0x30
+               >;
+       };
+
+       pinctrl_tpa1: tpa6130-1grp {
+               fsl,pins = <
+                       MX7D_PAD_LCD_DATA21__GPIO3_IO26         0x40000038
+               >;
+       };
+
+       pinctrl_tpa2: tpa6130-2grp {
+               fsl,pins = <
+                       MX7D_PAD_LCD_DATA22__GPIO3_IO27         0x40000038
+               >;
+       };
+
+       pinctrl_tpa3: tpa6130-3grp {
+               fsl,pins = <
+                       MX7D_PAD_LCD_DATA23__GPIO3_IO28         0x40000038
+               >;
+       };
+
+       pinctrl_uart2: uart2grp {
+               fsl,pins = <
+                       MX7D_PAD_UART2_RX_DATA__UART2_DCE_RX    0x79
+                       MX7D_PAD_UART2_TX_DATA__UART2_DCE_TX    0x79
+               >;
+       };
+
+       pinctrl_uart4: uart4grp {
+               fsl,pins = <
+                       MX7D_PAD_SD2_DATA0__UART4_DCE_RX        0x79
+                       MX7D_PAD_SD2_DATA1__UART4_DCE_TX        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_usdhc3: usdhc3grp {
+               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_RESET_B__SD3_RESET_B       0x59
+               >;
+       };
+};
+
+&iomuxc_lpsr {
+       pinctrl_codec1: dac1grp {
+               fsl,pins = <
+                       MX7D_PAD_LPSR_GPIO1_IO05__GPIO1_IO5     0x40000038
+               >;
+       };
+
+       pinctrl_codec2: dac2grp {
+               fsl,pins = <
+                       MX7D_PAD_LPSR_GPIO1_IO06__GPIO1_IO6     0x40000038
+               >;
+       };
+
+       pinctrl_codec3: dac3grp {
+               fsl,pins = <
+                       MX7D_PAD_LPSR_GPIO1_IO07__GPIO1_IO7     0x40000038
+               >;
+       };
+
+       pinctrl_switch: switchgrp {
+               fsl,pins = <
+                       MX7D_PAD_LPSR_GPIO1_IO02__GPIO1_IO2     0x08
+               >;
+       };
+};
index 6eb98e7..f33b560 100644 (file)
                ranges = <0x81000000 0 0          0x4ff80000 0 0x00010000   /* downstream I/O */
                          0x82000000 0 0x40000000 0x40000000 0 0x0ff00000>; /* non-prefetchable memory */
                num-lanes = <1>;
+               num-viewport = <4>;
                interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
                interrupt-names = "msi";
                #interrupt-cells = <1>;
diff --git a/arch/arm/boot/dts/imx7s-mba7.dts b/arch/arm/boot/dts/imx7s-mba7.dts
new file mode 100644 (file)
index 0000000..a143d56
--- /dev/null
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
+/*
+ * Device Tree Source for TQ Systems TQMa7S board on MBa7 carrier board.
+ *
+ * Copyright (C) 2016 TQ Systems GmbH
+ * Author: Markus Niebel <Markus.Niebel@tq-group.com>
+ * Copyright (C) 2019 Bruno Thomsen <bruno.thomsen@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "imx7s-tqma7.dtsi"
+#include "imx7-mba7.dtsi"
+
+/ {
+       model = "TQ Systems TQMa7S board on MBa7 carrier board";
+       compatible = "tq,imx7s-mba7", "fsl,imx7s";
+};
diff --git a/arch/arm/boot/dts/imx7s-tqma7.dtsi b/arch/arm/boot/dts/imx7s-tqma7.dtsi
new file mode 100644 (file)
index 0000000..5f5433e
--- /dev/null
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
+/*
+ * Device Tree Include file for TQ Systems TQMa7S board with NXP i.MX7Solo SoC.
+ *
+ * Copyright (C) 2016 TQ Systems GmbH
+ * Author: Markus Niebel <Markus.Niebel@tq-group.com>
+ * Copyright (C) 2019 Bruno Thomsen <bruno.thomsen@gmail.com>
+ */
+
+#include "imx7s.dtsi"
+#include "imx7-tqma7.dtsi"
index 23431fa..d6b4888 100644 (file)
                regulator-always-on;
        };
 
+       reg_peri_3p15v: regulator-peri-3p15v {
+               compatible = "regulator-fixed";
+               regulator-name = "peri_3p15v_reg";
+               regulator-min-microvolt = <3150000>;
+               regulator-max-microvolt = <3150000>;
+               regulator-always-on;
+       };
+
        sound {
                compatible = "simple-audio-card";
                simple-audio-card,name = "imx7-sgtl5000";
        assigned-clock-rates = <884736000>;
 };
 
+&csi {
+       status = "okay";
+};
+
 &i2c1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c1>;
                        swbst_reg: swbst {
                                regulator-min-microvolt = <5000000>;
                                regulator-max-microvolt = <5150000>;
+                               regulator-boot-on;
+                               regulator-always-on;
                        };
 
                        snvs_reg: vsnvs {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
+
+       ov2680: camera@36 {
+               compatible = "ovti,ov2680";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_ov2680>;
+               reg = <0x36>;
+               clocks = <&osc>;
+               clock-names = "xvclk";
+               reset-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
+               DOVDD-supply = <&sw2_reg>;
+               DVDD-supply = <&sw2_reg>;
+               AVDD-supply = <&reg_peri_3p15v>;
+
+               port {
+                       ov2680_to_mipi: endpoint {
+                               remote-endpoint = <&mipi_from_sensor>;
+                               clock-lanes = <0>;
+                               data-lanes = <1>;
+                       };
+               };
+       };
 };
 
 &i2c3 {
        };
 };
 
+&mipi_csi {
+       clock-frequency = <166000000>;
+       fsl,csis-hs-settle = <3>;
+       status = "okay";
+
+       port@0 {
+               reg = <0>;
+
+               mipi_from_sensor: endpoint {
+                       remote-endpoint = <&ov2680_to_mipi>;
+                       data-lanes = <1>;
+               };
+
+       };
+};
+
 &sai1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_sai1>;
        status = "okay";
 };
 
+&video_mux {
+       status = "okay";
+};
+
 &wdog1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_wdog>;
                >;
        };
 
+       pinctrl_ov2680: ov2660grp {
+               fsl,pins = <
+                       MX7D_PAD_LPSR_GPIO1_IO03__GPIO1_IO3     0x14
+               >;
+       };
+
        pinctrl_sai1: sai1grp {
                fsl,pins = <
                        MX7D_PAD_SAI1_RX_DATA__SAI1_RX_DATA0    0x1f
index e88f53a..106711d 100644 (file)
@@ -8,6 +8,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/imx7-reset.h>
 #include "imx7d-pinfunc.h"
 
 / {
 
                        gpr: iomuxc-gpr@30340000 {
                                compatible = "fsl,imx7d-iomuxc-gpr",
-                                       "fsl,imx6q-iomuxc-gpr", "syscon";
+                                       "fsl,imx6q-iomuxc-gpr", "syscon",
+                                       "simple-mfd";
                                reg = <0x30340000 0x10000>;
+
+                               mux: mux-controller {
+                                       compatible = "mmio-mux";
+                                       #mux-control-cells = <0>;
+                                       mux-reg-masks = <0x14 0x00000010>;
+                               };
+
+                               video_mux: csi-mux {
+                                       compatible = "video-mux";
+                                       mux-controls = <&mux 0>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       status = "disabled";
+
+                                       port@0 {
+                                               reg = <0>;
+                                       };
+
+                                       port@1 {
+                                               reg = <1>;
+
+                                               csi_mux_from_mipi_vc0: endpoint {
+                                                       remote-endpoint = <&mipi_vc0_to_csi_mux>;
+                                               };
+                                       };
+
+                                       port@2 {
+                                               reg = <2>;
+
+                                               csi_mux_to_csi: endpoint {
+                                                       remote-endpoint = <&csi_from_csi_mux>;
+                                               };
+                                       };
+                               };
                        };
 
                        ocotp: ocotp-ctrl@30350000 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
 
-                                       pgc_pcie_phy: pgc-power-domain@1 {
+                                       pgc_mipi_phy: power-domain@0 {
+                                               #power-domain-cells = <0>;
+                                               reg = <0>;
+                                               power-supply = <&reg_1p0d>;
+                                       };
+
+                                       pgc_pcie_phy: power-domain@1 {
                                                #power-domain-cells = <0>;
                                                reg = <1>;
                                                power-supply = <&reg_1p0d>;
                                interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX7D_ADC_ROOT_CLK>;
                                clock-names = "adc";
+                               #io-channel-cells = <1>;
                                status = "disabled";
                        };
 
                                interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX7D_ADC_ROOT_CLK>;
                                clock-names = "adc";
+                               #io-channel-cells = <1>;
                                status = "disabled";
                        };
 
                                status = "disabled";
                        };
 
+                       csi: csi@30710000 {
+                               compatible = "fsl,imx7-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 = "axi", "mclk", "dcic";
+                               status = "disabled";
+
+                               port {
+                                       csi_from_csi_mux: endpoint {
+                                               remote-endpoint = <&csi_mux_to_csi>;
+                                       };
+                               };
+                       };
+
                        lcdif: lcdif@30730000 {
                                compatible = "fsl,imx7d-lcdif", "fsl,imx28-lcdif";
                                reg = <0x30730000 0x10000>;
                                clock-names = "pix", "axi";
                                status = "disabled";
                        };
+
+                       mipi_csi: mipi-csi@30750000 {
+                               compatible = "fsl,imx7-mipi-csi2";
+                               reg = <0x30750000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX7D_IPG_ROOT_CLK>,
+                                        <&clks IMX7D_MIPI_CSI_ROOT_CLK>,
+                                        <&clks IMX7D_MIPI_DPHY_ROOT_CLK>;
+                               clock-names = "pclk", "wrap", "phy";
+                               power-domains = <&pgc_mipi_phy>;
+                               phy-supply = <&reg_1p0d>;
+                               resets = <&src IMX7_RESET_MIPI_PHY_MRST>;
+                               reset-names = "mrst";
+                               status = "disabled";
+
+                               port@0 {
+                                       reg = <0>;
+                               };
+
+                               port@1 {
+                                       reg = <1>;
+
+                                       mipi_vc0_to_csi_mux: endpoint {
+                                               remote-endpoint = <&csi_mux_from_mipi_vc0>;
+                                       };
+                               };
+                       };
                };
 
                aips3: aips-bus@30800000 {
                                compatible = "fsl,imx7d-sdma", "fsl,imx35-sdma";
                                reg = <0x30bd0000 0x10000>;
                                interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks IMX7D_SDMA_CORE_CLK>,
-                                        <&clks IMX7D_AHB_CHANNEL_ROOT_CLK>;
+                               clocks = <&clks IMX7D_IPG_ROOT_CLK>,
+                                        <&clks IMX7D_SDMA_CORE_CLK>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
                                fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
index fca6e50..d6b7110 100644 (file)
                        status = "disabled";
                };
 
+               memory-controller@40ab0000 {
+                       compatible = "fsl,imx7ulp-mmdc", "fsl,imx6q-mmdc";
+                       reg = <0x40ab0000 0x1000>;
+                       clocks = <&pcc3 IMX7ULP_CLK_MMDC>;
+               };
+
                iomuxc1: pinctrl@40ac0000 {
                        compatible = "fsl,imx7ulp-iomuxc1";
                        reg = <0x40ac0000 0x1000>;
                        compatible = "fsl,imx7ulp-sim", "syscon";
                        reg = <0x410a3000 0x1000>;
                };
+
+               ocotp: ocotp-ctrl@410a6000 {
+                       compatible = "fsl,imx7ulp-ocotp", "syscon";
+                       reg = <0x410a6000 0x4000>;
+                       clocks = <&scg1 IMX7ULP_CLK_DUMMY>;
+               };
        };
 };
diff --git a/arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts b/arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts
new file mode 100644 (file)
index 0000000..8fcd958
--- /dev/null
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for Linksys NSLU2
+ */
+
+/dts-v1/;
+
+#include "intel-ixp42x.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "Linksys NSLU2 (Network Storage Link for USB 2.0 Disk Drives)";
+       compatible = "linksys,nslu2", "intel,ixp42x";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory@0 {
+               /* 32 MB SDRAM */
+               device_type = "memory";
+               reg = <0x00000000 0x2000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8 root=/dev/mtdblock2 rw rootfstype=squashfs,jffs2 rootwait";
+               stdout-path = "uart0:115200n8";
+       };
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               led-status {
+                       label = "nslu2:red:status";
+                       gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+               led-ready {
+                       label = "nslu2:green:ready";
+                       gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+               };
+               led-disk-1 {
+                       label = "nslu2:green:disk-1";
+                       gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+               led-disk-2 {
+                       label = "nslu2:green:disk-2";
+                       gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+
+               button-power {
+                       wakeup-source;
+                       linux,code = <KEY_POWER>;
+                       label = "power";
+                       gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
+               };
+               button-reset {
+                       wakeup-source;
+                       linux,code = <KEY_ESC>;
+                       label = "reset";
+                       gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       i2c {
+               compatible = "i2c-gpio";
+               sda-gpios = <&gpio0 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+               scl-gpios = <&gpio0 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               rtc@6f {
+                       compatible = "xicor,x1205";
+                       reg = <0x6f>;
+               };
+       };
+
+       gpio-poweroff {
+               compatible = "gpio-poweroff";
+               gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
+               timeout-ms = <5000>;
+       };
+
+       /* The first 16MB region on the expansion bus */
+       flash@50000000 {
+               compatible = "intel,ixp4xx-flash", "cfi-flash";
+               bank-width = <2>;
+               /*
+                * 8 MB of Flash in 0x20000 byte blocks
+                * mapped in at 0x50000000
+                */
+               reg = <0x50000000 0x800000>;
+
+               partitions {
+                       compatible = "redboot-fis";
+                       /* Eraseblock at 0x7e0000 */
+                       fis-index-block = <0x3f>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/intel-ixp42x.dtsi b/arch/arm/boot/dts/intel-ixp42x.dtsi
new file mode 100644 (file)
index 0000000..a9622ca
--- /dev/null
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for Intel XScale Network Processors
+ * in the IXP 42x series. This series has 32 interrupts.
+ */
+#include "intel-ixp4xx.dtsi"
+
+/ {
+       soc {
+               interrupt-controller@c8003000 {
+                       compatible = "intel,ixp42x-interrupt";
+               };
+
+               /*
+                * This is the USB Device Mode (UDC) controller, which is used
+                * to present the IXP4xx as a device on a USB bus.
+                */
+               usb@c800b000 {
+                       compatible = "intel,ixp4xx-udc";
+                       reg = <0xc800b000 0x1000>;
+                       interrupts = <12 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358.dts b/arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358.dts
new file mode 100644 (file)
index 0000000..ba1163a
--- /dev/null
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for Gateworks IXP43x-based Cambria GW2358
+ */
+
+/dts-v1/;
+
+#include "intel-ixp43x.dtsi"
+
+/ {
+       model = "Gateworks Cambria GW2358";
+       compatible = "gateworks,gw2358", "intel,ixp43x";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory@0 {
+               /* 128 MB SDRAM */
+               device_type = "memory";
+               reg = <0x00000000 0x8000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8 root=/dev/mtdblock2 rw rootfstype=squashfs,jffs2 rootwait";
+               stdout-path = "uart0:115200n8";
+       };
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               led-user {
+                       label = "gw2358:green:LED";
+                       gpios = <&pld1 0 GPIO_ACTIVE_LOW>;
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+
+       i2c {
+               compatible = "i2c-gpio";
+               sda-gpios = <&gpio0 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+               scl-gpios = <&gpio0 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               hwmon@28 {
+                       compatible = "adi,ad7418";
+                       reg = <0x28>;
+               };
+               rtc: ds1672@68 {
+                       compatible = "dallas,ds1672";
+                       reg = <0x68>;
+               };
+               eeprom@51 {
+                       compatible = "atmel,24c08";
+                       reg = <0x51>;
+                       pagesize = <16>;
+                       size = <1024>;
+                       read-only;
+               };
+               pld0: pld@56 {
+                       compatible = "gateworks,pld-gpio";
+                       reg = <0x56>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+               /* This PLD just handles the LED and user button */
+               pld1: pld@57 {
+                       compatible = "gateworks,pld-gpio";
+                       reg = <0x57>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+       };
+
+       flash@50000000 {
+               compatible = "intel,ixp4xx-flash", "cfi-flash";
+               bank-width = <2>;
+               /*
+                * 32 MB of Flash in 0x20000 byte blocks
+                * mapped in at 0x50000000
+                */
+               reg = <0x50000000 0x2000000>;
+
+               partitions {
+                       compatible = "redboot-fis";
+                       /* Eraseblock at 0x1fe0000 */
+                       fis-index-block = <0xff>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/intel-ixp43x.dtsi b/arch/arm/boot/dts/intel-ixp43x.dtsi
new file mode 100644 (file)
index 0000000..494fb2f
--- /dev/null
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for Intel XScale Network Processors
+ * in the IXP 43x series. This series has 64 interrupts and adds a few more
+ * peripherals over the 42x series.
+ */
+#include "intel-ixp4xx.dtsi"
+
+/ {
+       soc {
+               interrupt-controller@c8003000 {
+                       compatible = "intel,ixp43x-interrupt";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi b/arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi
new file mode 100644 (file)
index 0000000..f8cd506
--- /dev/null
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for Intel XScale Network Processors
+ * in the IXP45x and IXP46x series. This series has 64 interrupts and adds a
+ * few more peripherals over the 42x and 43x series so this extends the
+ * basic IXP4xx DTSI.
+ */
+#include "intel-ixp4xx.dtsi"
+
+/ {
+       soc {
+               interrupt-controller@c8003000 {
+                       compatible = "intel,ixp43x-interrupt";
+               };
+
+               /*
+                * This is the USB Device Mode (UDC) controller, which is used
+                * to present the IXP4xx as a device on a USB bus.
+                */
+               usb@c800b000 {
+                       compatible = "intel,ixp4xx-udc";
+                       reg = <0xc800b000 0x1000>;
+                       interrupts = <12 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
+               i2c@c8011000 {
+                       compatible = "intel,ixp4xx-i2c";
+                       reg = <0xc8011000 0x18>;
+                       interrupts = <33 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/intel-ixp4xx.dtsi b/arch/arm/boot/dts/intel-ixp4xx.dtsi
new file mode 100644 (file)
index 0000000..d4a0958
--- /dev/null
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Device Tree file for Intel XScale Network Processors
+ * in the IXP 4xx series.
+ */
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+               compatible = "simple-bus";
+               interrupt-parent = <&intcon>;
+
+               qmgr: queue-manager@60000000 {
+                       compatible = "intel,ixp4xx-ahb-queue-manager";
+                       reg = <0x60000000 0x4000>;
+                       interrupts = <3 IRQ_TYPE_LEVEL_HIGH>, <4 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               uart0: serial@c8000000 {
+                       compatible = "intel,xscale-uart";
+                       reg = <0xc8000000 0x1000>;
+                       /*
+                        * The reg-offset and reg-shift is a side effect
+                        * of running the platform in big endian mode.
+                        */
+                       reg-offset = <3>;
+                       reg-shift = <2>;
+                       interrupts = <15 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <14745600>;
+                       no-loopback-test;
+               };
+
+               gpio0: gpio@c8004000 {
+                       compatible = "intel,ixp4xx-gpio";
+                       reg = <0xc8004000 0x1000>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               intcon: interrupt-controller@c8003000 {
+                       /*
+                        * Note: no compatible string. The subvariant of the
+                        * chip needs to define what version it is. The
+                        * location of the interrupt controller is fixed in
+                        * memory across all variants.
+                        */
+                       reg = <0xc8003000 0x100>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               timer@c8005000 {
+                       compatible = "intel,ixp4xx-timer";
+                       reg = <0xc8005000 0x100>;
+                       interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               npe@c8006000 {
+                       compatible = "intel,ixp4xx-network-processing-engine";
+                       reg = <0xc8006000 0x1000>, <0xc8007000 0x1000>, <0xc8008000 0x1000>;
+               };
+       };
+};
index f46a118..4adf4c9 100644 (file)
 &mac {
        phy-mode = "rmii";
        use-iram;
+       status = "okay";
 };
 
 /* Here, choose exactly one from: ohci, usbd */
index ebd1925..1b15f79 100644 (file)
 &mac {
        phy-mode = "rmii";
        use-iram;
+       status = "okay";
 };
 
 /* Here, choose exactly one from: ohci, usbd */
 };
 
 &ssp0 {
-       #address-cells = <1>;
-       #size-cells = <0>;
        num-cs = <1>;
        cs-gpios = <&gpio 3 5 0>;
        status = "okay";
index 20b38f4..7b7ec7b 100644 (file)
@@ -1,14 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * NXP LPC32xx SoC
  *
+ * Copyright (C) 2015-2019 Vladimir Zapolskiy <vz@mleia.com>
  * Copyright 2012 Roland Stigge <stigge@antcom.de>
- *
- * 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/lpc32xx-clock.h>
                        reg = <0x31060000 0x1000>;
                        interrupts = <29 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clk LPC32XX_CLK_MAC>;
+                       status = "disabled";
                };
 
                emc: memory-controller@31080000 {
                                interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk LPC32XX_CLK_SSP0>;
                                clock-names = "apb_pclk";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                status = "disabled";
                        };
 
                                compatible = "nxp,lpc3220-spi";
                                reg = <0x20088000 0x1000>;
                                clocks = <&clk LPC32XX_CLK_SPI1>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                status = "disabled";
                        };
 
                                interrupts = <21 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk LPC32XX_CLK_SSP1>;
                                clock-names = "apb_pclk";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                status = "disabled";
                        };
 
                                compatible = "nxp,lpc3220-spi";
                                reg = <0x20090000 0x1000>;
                                clocks = <&clk LPC32XX_CLK_SPI2>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                status = "disabled";
                        };
 
                        i2s0: i2s@20094000 {
                                compatible = "nxp,lpc3220-i2s";
                                reg = <0x20094000 0x1000>;
+                               status = "disabled";
                        };
 
                        sd: sd@20098000 {
 
                        i2s1: i2s@2009c000 {
                                compatible = "nxp,lpc3220-i2s";
-                               reg = <0x2009C000 0x1000>;
+                               reg = <0x2009c000 0x1000>;
+                               status = "disabled";
                        };
 
                        /* UART5 first since it is the default console, ttyS0 */
 
                        i2c1: i2c@400a0000 {
                                compatible = "nxp,pnx-i2c";
-                               reg = <0x400A0000 0x100>;
+                               reg = <0x400a0000 0x100>;
                                interrupt-parent = <&sic1>;
                                interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
                                #address-cells = <1>;
 
                        i2c2: i2c@400a8000 {
                                compatible = "nxp,pnx-i2c";
-                               reg = <0x400A8000 0x100>;
+                               reg = <0x400a8000 0x100>;
                                interrupt-parent = <&sic1>;
                                interrupts = <18 IRQ_TYPE_LEVEL_LOW>;
                                #address-cells = <1>;
 
                        mpwm: mpwm@400e8000 {
                                compatible = "nxp,lpc3220-motor-pwm";
-                               reg = <0x400E8000 0x78>;
+                               reg = <0x400e8000 0x78>;
                                status = "disabled";
                                #pwm-cells = <2>;
                        };
 
                        timer4: timer@4002c000 {
                                compatible = "nxp,lpc3220-timer";
-                               reg = <0x4002C000 0x1000>;
+                               reg = <0x4002c000 0x1000>;
                                interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
                                clocks = <&clk LPC32XX_CLK_TIMER4>;
                                clock-names = "timerclk";
 
                        watchdog: watchdog@4003c000 {
                                compatible = "nxp,pnx4008-wdt";
-                               reg = <0x4003C000 0x1000>;
+                               reg = <0x4003c000 0x1000>;
                                clocks = <&clk LPC32XX_CLK_WDOG>;
                        };
 
 
                        timer1: timer@4004c000 {
                                compatible = "nxp,lpc3220-timer";
-                               reg = <0x4004C000 0x1000>;
+                               reg = <0x4004c000 0x1000>;
                                interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
                                clocks = <&clk LPC32XX_CLK_TIMER1>;
                                clock-names = "timerclk";
 
                        pwm1: pwm@4005c000 {
                                compatible = "nxp,lpc3220-pwm";
-                               reg = <0x4005C000 0x4>;
+                               reg = <0x4005c000 0x4>;
                                clocks = <&clk LPC32XX_CLK_PWM1>;
                                assigned-clocks = <&clk LPC32XX_CLK_PWM1>;
                                assigned-clock-parents = <&clk LPC32XX_CLK_PERIPH>;
 
                        pwm2: pwm@4005c004 {
                                compatible = "nxp,lpc3220-pwm";
-                               reg = <0x4005C004 0x4>;
+                               reg = <0x4005c004 0x4>;
                                clocks = <&clk LPC32XX_CLK_PWM2>;
                                assigned-clocks = <&clk LPC32XX_CLK_PWM2>;
                                assigned-clock-parents = <&clk LPC32XX_CLK_PERIPH>;
index ba1ddd9..dcb1d9b 100644 (file)
 };
 
 &qspi {
-       fsl,qspi-has-second-chip;
        status = "okay";
 
        flash: flash@0 {
index ca60730..74a6760 100644 (file)
        status = "okay";
 };
 
+&esdhc {
+       status = "okay";
+};
+
 &i2c0 {
        status = "okay";
 
index 97e1fb7..9b1fe99 100644 (file)
 };
 
 &enet0 {
-       tbi-handle = <&tbi1>;
+       tbi-handle = <&tbi0>;
        phy-handle = <&sgmii_phy2>;
        phy-connection-type = "sgmii";
        status = "okay";
        sgmii_phy2: ethernet-phy@2 {
                reg = <0x2>;
        };
+       tbi0: tbi-phy@1f {
+               reg = <0x1f>;
+               device_type = "tbi-phy";
+       };
+};
+
+&mdio1 {
        tbi1: tbi-phy@1f {
                reg = <0x1f>;
                device_type = "tbi-phy";
index b10ff58..464df42 100644 (file)
                        interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
                        clock-names = "qspi_en", "qspi";
                        clocks = <&clockgen 4 1>, <&clockgen 4 1>;
-                       big-endian;
                        status = "disabled";
                };
 
                };
 
                mdio0: mdio@2d24000 {
-                       compatible = "gianfar";
+                       compatible = "fsl,etsec2-mdio";
                        device_type = "mdio";
                        #address-cells = <1>;
                        #size-cells = <0>;
                              <0x0 0x2d10030 0x0 0x4>;
                };
 
+               mdio1: mdio@2d64000 {
+                       compatible = "fsl,etsec2-mdio";
+                       device_type = "mdio";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2d64000 0x0 0x4000>,
+                             <0x0 0x2d50030 0x0 0x4>;
+               };
+
                ptp_clock@2d10e00 {
                        compatible = "fsl,etsec-ptp";
                        reg = <0x0 0x2d10e00 0x0 0xb0>;
index 6f54a88..8841783 100644 (file)
                                #size-cells = <0>;
                                status = "disabled";
                        };
+
+                       rtc: rtc@740 {
+                               compatible = "amlogic,meson6-rtc";
+                               reg = <0x740 0x14>;
+                               interrupts = <GIC_SPI 72 IRQ_TYPE_EDGE_RISING>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               status = "disabled";
+                       };
                };
 
                usb0: usb@c9040000 {
index a978124..7ef4424 100644 (file)
                status = "disabled";
        };
 
+       clock-measure@8758 {
+               compatible = "amlogic,meson8-clk-measure";
+               reg = <0x8758 0x1c>;
+       };
+
        pinctrl_cbus: pinctrl@9880 {
                compatible = "amlogic,meson8-cbus-pinctrl";
                reg = <0x9880 0x10>;
        compatible = "amlogic,meson8-pwm", "amlogic,meson8b-pwm";
 };
 
+&rtc {
+       compatible = "amlogic,meson8-rtc";
+       resets = <&reset RESET_RTC>;
+};
+
 &saradc {
        compatible = "amlogic,meson8-saradc", "amlogic,meson-saradc";
        clocks = <&clkc CLKID_XTAL>,
index 3ca9638..9bf4249 100644 (file)
                };
        };
 
+       rtc32k_xtal: rtc32k-xtal-clk {
+               /* X2 in the schematics */
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+               clock-output-names = "RTC32K";
+               #clock-cells = <0>;
+       };
+
        usb_vbus: regulator-usb-vbus {
                /*
                 * Silergy SY6288CCAC-GP 2A Power Distribution Switch.
        clock-names = "clkin0";
 };
 
+&rtc {
+       status = "okay";
+       clocks = <&rtc32k_xtal>;
+       vdd-supply = <&vcc_rtc>;
+};
+
 /* exposed through the pin headers labeled "URDUG1" on the top of the PCB */
 &uart_AO {
        status = "okay";
index 3b0e0f8..f3ad939 100644 (file)
                io-channels = <&saradc 8>;
        };
 
+       rtc32k_xtal: rtc32k-xtal-clk {
+               /* X3 in the schematics */
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+               clock-output-names = "RTC32K";
+               #clock-cells = <0>;
+       };
+
        vcc_1v8: regulator-vcc-1v8 {
                /*
                 * RICHTEK RT9179 configured for a fixed output voltage of
        };
 };
 
+&gpio {
+       gpio-line-names = /* Bank GPIOX */
+                         "J2 Header Pin 35", "J2 Header Pin 36",
+                         "J2 Header Pin 32", "J2 Header Pin 31",
+                         "J2 Header Pin 29", "J2 Header Pin 18",
+                         "J2 Header Pin 22", "J2 Header Pin 16",
+                         "J2 Header Pin 23", "J2 Header Pin 21",
+                         "J2 Header Pin 19", "J2 Header Pin 33",
+                         "J2 Header Pin 8", "J2 Header Pin 10",
+                         "J2 Header Pin 15", "J2 Header Pin 13",
+                         "J2 Header Pin 24", "J2 Header Pin 26",
+                         /* Bank GPIOY */
+                         "Revision (upper)", "Revision (lower)",
+                         "J2 Header Pin 7", "", "J2 Header Pin 12",
+                         "J2 Header Pin 11", "", "", "",
+                         "TFLASH_VDD_EN", "", "",
+                         /* Bank GPIODV */
+                         "VCCK_PWM (PWM_C)", "I2CA_SDA", "I2CA_SCL",
+                         "I2CB_SDA", "I2CB_SCL", "VDDEE_PWM (PWM_D)",
+                         "",
+                         /* Bank GPIOH */
+                         "HDMI_HPD", "HDMI_I2C_SDA", "HDMI_I2C_SCL",
+                         "ETH_PHY_INTR", "ETH_PHY_NRST", "ETH_TXD1",
+                         "ETH_TXD0", "ETH_TXD3", "ETH_TXD2",
+                         "ETH_RGMII_TX_CLK",
+                         /* Bank CARD */
+                         "SD_DATA1 (SDB_D1)", "SD_DATA0 (SDB_D0)",
+                         "SD_CLK",  "SD_CMD", "SD_DATA3 (SDB_D3)",
+                         "SD_DATA2 (SDB_D2)", "SD_CDN (SD_DET_N)",
+                         /* Bank BOOT */
+                         "SDC_D0 (EMMC)", "SDC_D1 (EMMC)",
+                         "SDC_D2 (EMMC)", "SDC_D3 (EMMC)",
+                         "SDC_D4 (EMMC)", "SDC_D5 (EMMC)",
+                         "SDC_D6 (EMMC)", "SDC_D7 (EMMC)",
+                         "SDC_CLK (EMMC)", "SDC_RSTn (EMMC)",
+                         "SDC_CMD (EMMC)", "BOOT_SEL", "", "", "",
+                         "", "", "", "",
+                         /* Bank DIF */
+                         "ETH_RXD1", "ETH_RXD0", "ETH_RX_DV",
+                         "RGMII_RX_CLK", "ETH_RXD3", "ETH_RXD2",
+                         "ETH_TXEN", "ETH_PHY_REF_CLK_25MOUT",
+                         "ETH_MDC", "ETH_MDIO";
+};
+
 &gpio_ao {
+       gpio-line-names = "UART TX", "UART RX", "",
+                         "TF_3V3N_1V8_EN", "USB_HUB_RST_N",
+                         "USB_OTG_PWREN", "J7 Header Pin 2",
+                         "IR_IN", "J7 Header Pin 4",
+                         "J7 Header Pin 6", "J7 Header Pin 5",
+                         "J7 Header Pin 7", "HDMI_CEC",
+                         "SYS_LED", "", "";
+
        /*
         * WARNING: The USB Hub on the Odroid-C1/C1+ needs a reset signal
         * to be turned high in order to be detected by the USB Controller.
        clock-names = "clkin0";
 };
 
+&rtc {
+       /* needs to be enabled manually when a battery is connected */
+       clocks = <&rtc32k_xtal>;
+       vdd-supply = <&vdd_rtc>;
+};
+
 &uart_AO {
        status = "okay";
        pinctrl-0 = <&uart_ao_a_pins>;
index fe84a8c..800cd65 100644 (file)
                status = "disabled";
        };
 
+       clock-measure@8758 {
+               compatible = "amlogic,meson8b-clk-measure";
+               reg = <0x8758 0x1c>;
+       };
+
        pinctrl_cbus: pinctrl@9880 {
                compatible = "amlogic,meson8b-cbus-pinctrl";
                reg = <0x9880 0x10>;
        compatible = "amlogic,meson8b-pwm";
 };
 
+&rtc {
+       compatible = "amlogic,meson8b-rtc";
+       resets = <&reset RESET_RTC>;
+};
+
 &saradc {
        compatible = "amlogic,meson8b-saradc", "amlogic,meson-saradc";
        clocks = <&clkc CLKID_XTAL>,
index 96b9913..09c1dbc 100644 (file)
@@ -48,7 +48,7 @@
                pinctrl-names = "default";
                pinctrl-0 = <&aic33_pins>;
 
-               gpio-reset = <&gpio4 22 GPIO_ACTIVE_LOW>; /* gpio118 */
+               reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>; /* gpio118 */
 
                ai3x-gpio-func = <
                        10 /* AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK */
index 5e81691..a1dacb8 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include "omap443x.dtsi"
+#include "omap4-mcpdm.dtsi"
 
 / {
        model = "Gumstix Duovero";
                >;
        };
 
-       mcpdm_pins: pinmux_mcpdm_pins {
-               pinctrl-single,pins = <
-                       OMAP4_IOPAD(0x106, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_pdm_ul_data.abe_pdm_ul_data */
-                       OMAP4_IOPAD(0x108, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_pdm_dl_data.abe_pdm_dl_data */
-                       OMAP4_IOPAD(0x10a, PIN_INPUT_PULLUP   | MUX_MODE0)      /* abe_pdm_frame.abe_pdm_frame */
-                       OMAP4_IOPAD(0x10c, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_pdm_lb_clk.abe_pdm_lb_clk */
-                       OMAP4_IOPAD(0x10e, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_clks.abe_clks */
-               >;
-       };
-
        mcbsp1_pins: pinmux_mcbsp1_pins {
                pinctrl-single,pins = <
                        OMAP4_IOPAD(0x0fe, PIN_INPUT | MUX_MODE0)               /* abe_mcbsp1_clkx.abe_mcbsp1_clkx */
        status = "okay";
 };
 
-&mcpdm {
-       pinctrl-names = "default";
-       pinctrl-0 = <&mcpdm_pins>;
-
-       clocks = <&twl6040>;
-       clock-names = "pdmclk";
-
-       status = "okay";
-};
-
 &mmc1 {
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pins>;
diff --git a/arch/arm/boot/dts/omap4-l4-abe.dtsi b/arch/arm/boot/dts/omap4-l4-abe.dtsi
new file mode 100644 (file)
index 0000000..67072df
--- /dev/null
@@ -0,0 +1,501 @@
+&l4_abe {                                              /* 0x40100000 */
+       compatible = "ti,omap4-l4-abe", "simple-bus";
+       reg = <0x40100000 0x400>,
+             <0x40100400 0x400>;
+       reg-names = "la", "ap";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges = <0x00000000 0x40100000 0x100000>,      /* segment 0 */
+                <0x49000000 0x49000000 0x100000>;
+       segment@0 {                                     /* 0x40100000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges =
+                        /* CPU to L4 ABE mapping */
+                        <0x00000000 0x00000000 0x000400>,      /* ap 0 */
+                        <0x00000400 0x00000400 0x000400>,      /* ap 1 */
+                        <0x00022000 0x00022000 0x001000>,      /* ap 2 */
+                        <0x00023000 0x00023000 0x001000>,      /* ap 3 */
+                        <0x00024000 0x00024000 0x001000>,      /* ap 4 */
+                        <0x00025000 0x00025000 0x001000>,      /* ap 5 */
+                        <0x00026000 0x00026000 0x001000>,      /* ap 6 */
+                        <0x00027000 0x00027000 0x001000>,      /* ap 7 */
+                        <0x00028000 0x00028000 0x001000>,      /* ap 8 */
+                        <0x00029000 0x00029000 0x001000>,      /* ap 9 */
+                        <0x0002a000 0x0002a000 0x001000>,      /* ap 10 */
+                        <0x0002b000 0x0002b000 0x001000>,      /* ap 11 */
+                        <0x0002e000 0x0002e000 0x001000>,      /* ap 12 */
+                        <0x0002f000 0x0002f000 0x001000>,      /* ap 13 */
+                        <0x00030000 0x00030000 0x001000>,      /* ap 14 */
+                        <0x00031000 0x00031000 0x001000>,      /* ap 15 */
+                        <0x00032000 0x00032000 0x001000>,      /* ap 16 */
+                        <0x00033000 0x00033000 0x001000>,      /* ap 17 */
+                        <0x00038000 0x00038000 0x001000>,      /* ap 18 */
+                        <0x00039000 0x00039000 0x001000>,      /* ap 19 */
+                        <0x0003a000 0x0003a000 0x001000>,      /* ap 20 */
+                        <0x0003b000 0x0003b000 0x001000>,      /* ap 21 */
+                        <0x0003c000 0x0003c000 0x001000>,      /* ap 22 */
+                        <0x0003d000 0x0003d000 0x001000>,      /* ap 23 */
+                        <0x0003e000 0x0003e000 0x001000>,      /* ap 24 */
+                        <0x0003f000 0x0003f000 0x001000>,      /* ap 25 */
+                        <0x00080000 0x00080000 0x010000>,      /* ap 26 */
+                        <0x00080000 0x00080000 0x001000>,      /* ap 27 */
+                        <0x000a0000 0x000a0000 0x010000>,      /* ap 28 */
+                        <0x000a0000 0x000a0000 0x001000>,      /* ap 29 */
+                        <0x000c0000 0x000c0000 0x010000>,      /* ap 30 */
+                        <0x000c0000 0x000c0000 0x001000>,      /* ap 31 */
+                        <0x000f1000 0x000f1000 0x001000>,      /* ap 32 */
+                        <0x000f2000 0x000f2000 0x001000>,      /* ap 33 */
+
+                        /* L3 to L4 ABE mapping */
+                        <0x49000000 0x49000000 0x000400>,      /* ap 0 */
+                        <0x49000400 0x49000400 0x000400>,      /* ap 1 */
+                        <0x49022000 0x49022000 0x001000>,      /* ap 2 */
+                        <0x49023000 0x49023000 0x001000>,      /* ap 3 */
+                        <0x49024000 0x49024000 0x001000>,      /* ap 4 */
+                        <0x49025000 0x49025000 0x001000>,      /* ap 5 */
+                        <0x49026000 0x49026000 0x001000>,      /* ap 6 */
+                        <0x49027000 0x49027000 0x001000>,      /* ap 7 */
+                        <0x49028000 0x49028000 0x001000>,      /* ap 8 */
+                        <0x49029000 0x49029000 0x001000>,      /* ap 9 */
+                        <0x4902a000 0x4902a000 0x001000>,      /* ap 10 */
+                        <0x4902b000 0x4902b000 0x001000>,      /* ap 11 */
+                        <0x4902e000 0x4902e000 0x001000>,      /* ap 12 */
+                        <0x4902f000 0x4902f000 0x001000>,      /* ap 13 */
+                        <0x49030000 0x49030000 0x001000>,      /* ap 14 */
+                        <0x49031000 0x49031000 0x001000>,      /* ap 15 */
+                        <0x49032000 0x49032000 0x001000>,      /* ap 16 */
+                        <0x49033000 0x49033000 0x001000>,      /* ap 17 */
+                        <0x49038000 0x49038000 0x001000>,      /* ap 18 */
+                        <0x49039000 0x49039000 0x001000>,      /* ap 19 */
+                        <0x4903a000 0x4903a000 0x001000>,      /* ap 20 */
+                        <0x4903b000 0x4903b000 0x001000>,      /* ap 21 */
+                        <0x4903c000 0x4903c000 0x001000>,      /* ap 22 */
+                        <0x4903d000 0x4903d000 0x001000>,      /* ap 23 */
+                        <0x4903e000 0x4903e000 0x001000>,      /* ap 24 */
+                        <0x4903f000 0x4903f000 0x001000>,      /* ap 25 */
+                        <0x49080000 0x49080000 0x010000>,      /* ap 26 */
+                        <0x49080000 0x49080000 0x001000>,      /* ap 27 */
+                        <0x490a0000 0x490a0000 0x010000>,      /* ap 28 */
+                        <0x490a0000 0x490a0000 0x001000>,      /* ap 29 */
+                        <0x490c0000 0x490c0000 0x010000>,      /* ap 30 */
+                        <0x490c0000 0x490c0000 0x001000>,      /* ap 31 */
+                        <0x490f1000 0x490f1000 0x001000>,      /* ap 32 */
+                        <0x490f2000 0x490f2000 0x001000>;      /* ap 33 */
+
+               target-module@22000 {                   /* 0x40122000, ap 2 02.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "mcbsp1";
+                       reg = <0x2208c 0x4>;
+                       reg-names = "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       /* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP4_MCBSP1_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x22000 0x1000>,
+                                <0x49022000 0x49022000 0x1000>;
+
+                       mcbsp1: mcbsp@0 {
+                               compatible = "ti,omap4-mcbsp";
+                               reg = <0x0 0xff>, /* MPU private access */
+                                     <0x49022000 0xff>; /* L3 Interconnect */
+                               reg-names = "mpu", "dma";
+                               interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "common";
+                               ti,buffer-size = <128>;
+                               dmas = <&sdma 33>,
+                                      <&sdma 34>;
+                               dma-names = "tx", "rx";
+                               status = "disabled";
+                       };
+               };
+
+               target-module@24000 {                   /* 0x40124000, ap 4 04.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "mcbsp2";
+                       reg = <0x2408c 0x4>;
+                       reg-names = "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       /* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP4_MCBSP2_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x24000 0x1000>,
+                                <0x49024000 0x49024000 0x1000>;
+
+                       mcbsp2: mcbsp@0 {
+                               compatible = "ti,omap4-mcbsp";
+                               reg = <0x0 0xff>, /* MPU private access */
+                                     <0x49024000 0xff>; /* L3 Interconnect */
+                               reg-names = "mpu", "dma";
+                               interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "common";
+                               ti,buffer-size = <128>;
+                               dmas = <&sdma 17>,
+                                      <&sdma 18>;
+                               dma-names = "tx", "rx";
+                               status = "disabled";
+                       };
+               };
+
+               target-module@26000 {                   /* 0x40126000, ap 6 06.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "mcbsp3";
+                       reg = <0x2608c 0x4>;
+                       reg-names = "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       /* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP4_MCBSP3_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x26000 0x1000>,
+                                <0x49026000 0x49026000 0x1000>;
+
+                       mcbsp3: mcbsp@0 {
+                               compatible = "ti,omap4-mcbsp";
+                               reg = <0x0 0xff>, /* MPU private access */
+                                     <0x49026000 0xff>; /* L3 Interconnect */
+                               reg-names = "mpu", "dma";
+                               interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "common";
+                               ti,buffer-size = <128>;
+                               dmas = <&sdma 19>,
+                                      <&sdma 20>;
+                               dma-names = "tx", "rx";
+                               status = "disabled";
+                       };
+               };
+
+               target-module@28000 {                   /* 0x40128000, ap 8 08.0 */
+                       compatible = "ti,sysc-mcasp", "ti,sysc";
+                       ti,hwmods = "mcasp";
+                       reg = <0x28000 0x4>,
+                             <0x28004 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP4_MCASP_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x28000 0x1000>,
+                                <0x49028000 0x49028000 0x1000>;
+
+                       /*
+                        * Child device unsupported by davinci-mcasp. At least
+                        * RX path is disabled for omap4, and only DIT mode
+                        * works with no I2S. See also old Android kernel
+                        * omap-mcasp driver for more information.
+                        */
+               };
+
+               target-module@2a000 {                   /* 0x4012a000, ap 10 0a.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x2a000 0x1000>,
+                                <0x4902a000 0x4902a000 0x1000>;
+               };
+
+               target-module@2e000 {                   /* 0x4012e000, ap 12 0c.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "dmic";
+                       reg = <0x2e000 0x4>,
+                             <0x2e010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP4_DMIC_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x2e000 0x1000>,
+                                <0x4902e000 0x4902e000 0x1000>;
+
+                       dmic: dmic@0 {
+                               compatible = "ti,omap4-dmic";
+                               reg = <0x0 0x7f>, /* MPU private access */
+                                     <0x4902e000 0x7f>; /* L3 Interconnect */
+                               reg-names = "mpu", "dma";
+                               interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&sdma 67>;
+                               dma-names = "up_link";
+                               status = "disabled";
+                       };
+               };
+
+               target-module@30000 {                   /* 0x40130000, ap 14 0e.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "wd_timer3";
+                       reg = <0x30000 0x4>,
+                             <0x30010 0x4>,
+                             <0x30014 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_EMUFREE |
+                                        SYSC_OMAP2_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP4_WD_TIMER3_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x30000 0x1000>,
+                                <0x49030000 0x49030000 0x1000>;
+
+                       wdt3: wdt@0 {
+                               compatible = "ti,omap4-wdt", "ti,omap3-wdt";
+                               reg = <0x0 0x80>;
+                               interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               mcpdm_module: target-module@32000 {     /* 0x40132000, ap 16 10.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "mcpdm";
+                       reg = <0x32000 0x4>,
+                             <0x32010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP4_MCPDM_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x32000 0x1000>,
+                                <0x49032000 0x49032000 0x1000>;
+
+                       /* Must be only enabled for boards with pdmclk wired */
+                       status = "disabled";
+
+                       mcpdm: mcpdm@0 {
+                               compatible = "ti,omap4-mcpdm";
+                               reg = <0x0 0x7f>, /* MPU private access */
+                                     <0x49032000 0x7f>; /* L3 Interconnect */
+                               reg-names = "mpu", "dma";
+                               interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&sdma 65>,
+                                      <&sdma 66>;
+                               dma-names = "up_link", "dn_link";
+                       };
+               };
+
+               target-module@38000 {                   /* 0x40138000, ap 18 12.0 */
+                       compatible = "ti,sysc-omap4-timer", "ti,sysc";
+                       ti,hwmods = "timer5";
+                       reg = <0x38000 0x4>,
+                             <0x38010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP4_TIMER5_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x38000 0x1000>,
+                                <0x49038000 0x49038000 0x1000>;
+
+                       timer5: timer@0 {
+                               compatible = "ti,omap4430-timer";
+                               reg = <0x00000000 0x80>,
+                                     <0x49038000 0x80>;
+                               clocks = <&abe_clkctrl OMAP4_TIMER5_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-dsp;
+                       };
+               };
+
+               target-module@3a000 {                   /* 0x4013a000, ap 20 14.0 */
+                       compatible = "ti,sysc-omap4-timer", "ti,sysc";
+                       ti,hwmods = "timer6";
+                       reg = <0x3a000 0x4>,
+                             <0x3a010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP4_TIMER6_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x3a000 0x1000>,
+                                <0x4903a000 0x4903a000 0x1000>;
+
+                       timer6: timer@0 {
+                               compatible = "ti,omap4430-timer";
+                               reg = <0x00000000 0x80>,
+                                     <0x4903a000 0x80>;
+                               clocks = <&abe_clkctrl OMAP4_TIMER6_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-dsp;
+                       };
+               };
+
+               target-module@3c000 {                   /* 0x4013c000, ap 22 16.0 */
+                       compatible = "ti,sysc-omap4-timer", "ti,sysc";
+                       ti,hwmods = "timer7";
+                       reg = <0x3c000 0x4>,
+                             <0x3c010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP4_TIMER7_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x3c000 0x1000>,
+                                <0x4903c000 0x4903c000 0x1000>;
+
+                       timer7: timer@0 {
+                               compatible = "ti,omap4430-timer";
+                               reg = <0x00000000 0x80>,
+                                     <0x4903c000 0x80>;
+                               clocks = <&abe_clkctrl OMAP4_TIMER7_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-dsp;
+                       };
+               };
+
+               target-module@3e000 {                   /* 0x4013e000, ap 24 18.0 */
+                       compatible = "ti,sysc-omap4-timer", "ti,sysc";
+                       ti,hwmods = "timer8";
+                       reg = <0x3e000 0x4>,
+                             <0x3e010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP4_TIMER8_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x3e000 0x1000>,
+                                <0x4903e000 0x4903e000 0x1000>;
+
+                       timer8: timer@0 {
+                               compatible = "ti,omap4430-timer";
+                               reg = <0x00000000 0x80>,
+                                     <0x4903e000 0x80>;
+                               clocks = <&abe_clkctrl OMAP4_TIMER8_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-pwm;
+                               ti,timer-dsp;
+                       };
+               };
+
+               target-module@80000 {                   /* 0x40180000, ap 26 1a.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x80000 0x10000>,
+                                <0x49080000 0x49080000 0x10000>;
+               };
+
+               target-module@a0000 {                   /* 0x401a0000, ap 28 1c.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xa0000 0x10000>,
+                                <0x490a0000 0x490a0000 0x10000>;
+               };
+
+               target-module@c0000 {                   /* 0x401c0000, ap 30 1e.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xc0000 0x10000>,
+                                <0x490c0000 0x490c0000 0x10000>;
+               };
+
+               target-module@f1000 {                   /* 0x401f1000, ap 32 20.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "aess";
+                       reg = <0xf1000 0x4>,
+                             <0xf1010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-midle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       /* Domains (V, P, C): iva, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP4_AESS_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xf1000 0x1000>,
+                                <0x490f1000 0x490f1000 0x1000>;
+
+                       /*
+                        * No child device binding or driver in mainline.
+                        * See Android tree and related upstreaming efforts
+                        * for the old driver.
+                        */
+               };
+       };
+};
+
diff --git a/arch/arm/boot/dts/omap4-mcpdm.dtsi b/arch/arm/boot/dts/omap4-mcpdm.dtsi
new file mode 100644 (file)
index 0000000..915a9b3
--- /dev/null
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Common omap4 mcpdm configuration
+ *
+ * Only include this file if your board has pdmclk wired from the
+ * pmic to ABE as mcpdm uses an external clock for the module.
+ */
+
+&omap4_pmx_core {
+       mcpdm_pins: pinmux_mcpdm_pins {
+               pinctrl-single,pins = <
+               /* 0x4a100106 abe_pdm_ul_data.abe_pdm_ul_data ag25 */
+               OMAP4_IOPAD(0x106, PIN_INPUT_PULLDOWN | MUX_MODE0)
+
+               /* 0x4a100108 abe_pdm_dl_data.abe_pdm_dl_data af25 */
+               OMAP4_IOPAD(0x108, PIN_INPUT_PULLDOWN | MUX_MODE0)
+
+               /* 0x4a10010a abe_pdm_frame.abe_pdm_frame ae25 */
+               OMAP4_IOPAD(0x10a, PIN_INPUT_PULLUP   | MUX_MODE0)
+
+               /* 0x4a10010c abe_pdm_lb_clk.abe_pdm_lb_clk af26 */
+               OMAP4_IOPAD(0x10c, PIN_INPUT_PULLDOWN | MUX_MODE0)
+
+               /* 0x4a10010e abe_clks.abe_clks ah26 */
+               OMAP4_IOPAD(0x10e, PIN_INPUT_PULLDOWN | MUX_MODE0)
+               >;
+       };
+};
+
+&mcpdm_module {
+       /*
+        * McPDM pads must be muxed at the interconnect target module
+        * level as the module on the SoC needs external clock from
+        * the PMIC
+        */
+       pinctrl-names = "default";
+       pinctrl-0 = <&mcpdm_pins>;
+       status = "okay";
+};
+
+&mcpdm {
+       clocks = <&twl6040>;
+       clock-names = "pdmclk";
+};
index 926f018..68e1894 100644 (file)
@@ -7,6 +7,7 @@
  */
 #include <dt-bindings/input/input.h>
 #include "elpida_ecb240abacn.dtsi"
+#include "omap4-mcpdm.dtsi"
 
 / {
        memory@80000000 {
                >;
        };
 
-       mcpdm_pins: pinmux_mcpdm_pins {
-               pinctrl-single,pins = <
-                       OMAP4_IOPAD(0x106, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_pdm_ul_data.abe_pdm_ul_data */
-                       OMAP4_IOPAD(0x108, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_pdm_dl_data.abe_pdm_dl_data */
-                       OMAP4_IOPAD(0x10a, PIN_INPUT_PULLUP   | MUX_MODE0)      /* abe_pdm_frame.abe_pdm_frame */
-                       OMAP4_IOPAD(0x10c, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_pdm_lb_clk.abe_pdm_lb_clk */
-                       OMAP4_IOPAD(0x10e, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_clks.abe_clks */
-               >;
-       };
-
        mcbsp1_pins: pinmux_mcbsp1_pins {
                pinctrl-single,pins = <
                        OMAP4_IOPAD(0x0fe, PIN_INPUT | MUX_MODE0)               /* abe_mcbsp1_clkx.abe_mcbsp1_clkx */
        status = "okay";
 };
 
-&mcpdm {
-       pinctrl-names = "default";
-       pinctrl-0 = <&mcpdm_pins>;
-
-       clocks = <&twl6040>;
-       clock-names = "pdmclk";
-
-       status = "okay";
-};
-
 &twl_usb_comparator {
        usb-supply = <&vusb>;
 };
index c88817b..fb51a4b 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "omap443x.dtsi"
 #include "elpida_ecb240abacn.dtsi"
+#include "omap4-mcpdm.dtsi"
 
 / {
        model = "TI OMAP4 SDP board";
                >;
        };
 
-       mcpdm_pins: pinmux_mcpdm_pins {
-               pinctrl-single,pins = <
-                       OMAP4_IOPAD(0x106, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_pdm_ul_data.abe_pdm_ul_data */
-                       OMAP4_IOPAD(0x108, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_pdm_dl_data.abe_pdm_dl_data */
-                       OMAP4_IOPAD(0x10a, PIN_INPUT_PULLUP | MUX_MODE0)        /* abe_pdm_frame.abe_pdm_frame */
-                       OMAP4_IOPAD(0x10c, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_pdm_lb_clk.abe_pdm_lb_clk */
-                       OMAP4_IOPAD(0x10e, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_clks.abe_clks */
-               >;
-       };
-
        dmic_pins: pinmux_dmic_pins {
                pinctrl-single,pins = <
                        OMAP4_IOPAD(0x110, PIN_OUTPUT | MUX_MODE0)              /* abe_dmic_clk1.abe_dmic_clk1 */
        status = "okay";
 };
 
-&mcpdm {
-       pinctrl-names = "default";
-       pinctrl-0 = <&mcpdm_pins>;
-
-       clocks = <&twl6040>;
-       clock-names = "pdmclk";
-
-       status = "okay";
-};
-
 &twl_usb_comparator {
        usb-supply = <&vusb>;
 };
index 10fce28..9562d37 100644 (file)
@@ -7,6 +7,7 @@
  * published by the Free Software Foundation.
  */
 #include "omap4460.dtsi"
+#include "omap4-mcpdm.dtsi"
 
 / {
        model = "Variscite VAR-SOM-OM44";
                >;
        };
 
-       mcpdm_pins: pinmux_mcpdm_pins {
-               pinctrl-single,pins = <
-                       OMAP4_IOPAD(0x106, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_pdm_ul_data.abe_pdm_ul_data */
-                       OMAP4_IOPAD(0x108, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_pdm_dl_data.abe_pdm_dl_data */
-                       OMAP4_IOPAD(0x10a, PIN_INPUT_PULLUP | MUX_MODE0)        /* abe_pdm_frame.abe_pdm_frame */
-                       OMAP4_IOPAD(0x10c, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_pdm_lb_clk.abe_pdm_lb_clk */
-                       OMAP4_IOPAD(0x10e, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* abe_clks.abe_clks */
-               >;
-       };
-
        tsc2004_pins: pinmux_tsc2004_pins {
                pinctrl-single,pins = <
                        OMAP4_IOPAD(0x090, PIN_INPUT | MUX_MODE3)               /* gpmc_ncs4.gpio_101 (irq) */
        status = "disabled";
 };
 
-&mcpdm {
-       pinctrl-names = "default";
-       pinctrl-0 = <&mcpdm_pins>;
-
-       clocks = <&twl6040>;
-       clock-names = "pdmclk";
-
-       status = "okay";
-};
-
 &gpmc {
        status = "disabled";
 };
index 1a96d43..442a737 100644 (file)
                l4_per: interconnect@48000000 {
                };
 
+               l4_abe: interconnect@40100000 {
+               };
+
                ocmcram: ocmcram@40304000 {
                        compatible = "mmio-sram";
                        reg = <0x40304000 0xa000>; /* 40k */
                        #iommu-cells = <0>;
                        ti,iommu-bus-err-back;
                };
-               target-module@40130000 {
-                       compatible = "ti,sysc-omap2", "ti,sysc";
-                       ti,hwmods = "wd_timer3";
-                       reg = <0x40130000 0x4>,
-                             <0x40130010 0x4>,
-                             <0x40130014 0x4>;
-                       reg-names = "rev", "sysc", "syss";
-                       ti,sysc-mask = <(SYSC_OMAP2_EMUFREE |
-                                        SYSC_OMAP2_SOFTRESET)>;
-                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
-                                       <SYSC_IDLE_NO>,
-                                       <SYSC_IDLE_SMART>,
-                                       <SYSC_IDLE_SMART_WKUP>;
-                       ti,syss-mask = <1>;
-                       /* Domains (V, P, C): abe, abe_pwrdm, abe_clkdm */
-                       clocks = <&abe_clkctrl OMAP4_WD_TIMER3_CLKCTRL 0>;
-                       clock-names = "fck";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges = <0x00000000 0x40130000 0x1000>, /* MPU private access */
-                                <0x49030000 0x49030000 0x0080>; /* L3 Interconnect */
-
-                       wdt3: wdt@0 {
-                               compatible = "ti,omap4-wdt", "ti,omap3-wdt";
-                               reg = <0x0 0x80>;
-                               interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
-                       };
-               };
-
-               mcpdm: mcpdm@40132000 {
-                       compatible = "ti,omap4-mcpdm";
-                       reg = <0x40132000 0x7f>, /* MPU private access */
-                             <0x49032000 0x7f>; /* L3 Interconnect */
-                       reg-names = "mpu", "dma";
-                       interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "mcpdm";
-                       dmas = <&sdma 65>,
-                              <&sdma 66>;
-                       dma-names = "up_link", "dn_link";
-                       status = "disabled";
-               };
-
-               dmic: dmic@4012e000 {
-                       compatible = "ti,omap4-dmic";
-                       reg = <0x4012e000 0x7f>, /* MPU private access */
-                             <0x4902e000 0x7f>; /* L3 Interconnect */
-                       reg-names = "mpu", "dma";
-                       interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "dmic";
-                       dmas = <&sdma 67>;
-                       dma-names = "up_link";
-                       status = "disabled";
-               };
-
-               mcbsp1: mcbsp@40122000 {
-                       compatible = "ti,omap4-mcbsp";
-                       reg = <0x40122000 0xff>, /* MPU private access */
-                             <0x49022000 0xff>; /* L3 Interconnect */
-                       reg-names = "mpu", "dma";
-                       interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-names = "common";
-                       ti,buffer-size = <128>;
-                       ti,hwmods = "mcbsp1";
-                       dmas = <&sdma 33>,
-                              <&sdma 34>;
-                       dma-names = "tx", "rx";
-                       status = "disabled";
-               };
-
-               mcbsp2: mcbsp@40124000 {
-                       compatible = "ti,omap4-mcbsp";
-                       reg = <0x40124000 0xff>, /* MPU private access */
-                             <0x49024000 0xff>; /* L3 Interconnect */
-                       reg-names = "mpu", "dma";
-                       interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-names = "common";
-                       ti,buffer-size = <128>;
-                       ti,hwmods = "mcbsp2";
-                       dmas = <&sdma 17>,
-                              <&sdma 18>;
-                       dma-names = "tx", "rx";
-                       status = "disabled";
-               };
-
-               mcbsp3: mcbsp@40126000 {
-                       compatible = "ti,omap4-mcbsp";
-                       reg = <0x40126000 0xff>, /* MPU private access */
-                             <0x49026000 0xff>; /* L3 Interconnect */
-                       reg-names = "mpu", "dma";
-                       interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-names = "common";
-                       ti,buffer-size = <128>;
-                       ti,hwmods = "mcbsp3";
-                       dmas = <&sdma 19>,
-                              <&sdma 20>;
-                       dma-names = "tx", "rx";
-                       status = "disabled";
-               };
-
-               target-module@40128000 {
-                       compatible = "ti,sysc-mcasp", "ti,sysc";
-                       ti,hwmods = "mcasp";
-                       reg = <0x40128000 0x4>,
-                             <0x40128004 0x4>;
-                       reg-names = "rev", "sysc";
-                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
-                                       <SYSC_IDLE_NO>,
-                                       <SYSC_IDLE_SMART>,
-                                       <SYSC_IDLE_SMART_WKUP>;
-                       clocks = <&abe_clkctrl OMAP4_MCASP_CLKCTRL 0>;
-                       clock-names = "fck";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges = <0x00000000 0x40128000 0x1000>, /* MPU */
-                                <0x49028000 0x49028000 0x1000>; /* L3 */
-
-                       /*
-                        * Child device unsupported by davinci-mcasp. At least
-                        * RX path is disabled for omap4, and only DIT mode
-                        * works with no I2S. See also old Android kernel
-                        * omap-mcasp driver for more information.
-                        */
-               };
-
                target-module@4012c000 {
                        compatible = "ti,sysc-omap4", "ti,sysc";
                        ti,hwmods = "slimbus1";
                        /* No child device binding or driver in mainline */
                };
 
-               target-module@401f1000 {
-                       compatible = "ti,sysc-omap4", "ti,sysc";
-                       ti,hwmods = "aess";
-                       reg = <0x401f1000 0x4>,
-                             <0x401f1010 0x4>;
-                       reg-names = "rev", "sysc";
-                       ti,sysc-midle = <SYSC_IDLE_FORCE>,
-                                       <SYSC_IDLE_NO>,
-                                       <SYSC_IDLE_SMART>,
-                                       <SYSC_IDLE_SMART_WKUP>;
-                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
-                                       <SYSC_IDLE_NO>,
-                                       <SYSC_IDLE_SMART>;
-                       clocks = <&abe_clkctrl OMAP4_AESS_CLKCTRL 0>;
-                       clock-names = "fck";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges = <0x00000000 0x401f1000 0x1000>, /* MPU */
-                                <0x490f1000 0x490f1000 0x1000>; /* L3 */
-
-                       /*
-                        * No child device binding or driver in mainline.
-                        * See Android tree and related upstreaming efforts
-                        * for the old driver.
-                        */
-               };
-
                dmm@4e000000 {
                        compatible = "ti,omap4-dmm";
                        reg = <0x4e000000 0x800>;
                        hw-caps-temp-alert;
                };
 
-               timer5: timer@40138000 {
-                       compatible = "ti,omap4430-timer";
-                       reg = <0x40138000 0x80>,
-                             <0x49038000 0x80>;
-                       interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer5";
-                       ti,timer-dsp;
-               };
-
-               timer6: timer@4013a000 {
-                       compatible = "ti,omap4430-timer";
-                       reg = <0x4013a000 0x80>,
-                             <0x4903a000 0x80>;
-                       interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer6";
-                       ti,timer-dsp;
-               };
-
-               timer7: timer@4013c000 {
-                       compatible = "ti,omap4430-timer";
-                       reg = <0x4013c000 0x80>,
-                             <0x4903c000 0x80>;
-                       interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer7";
-                       ti,timer-dsp;
-               };
-
-               timer8: timer@4013e000 {
-                       compatible = "ti,omap4430-timer";
-                       reg = <0x4013e000 0x80>,
-                             <0x4903e000 0x80>;
-                       interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer8";
-                       ti,timer-pwm;
-                       ti,timer-dsp;
-               };
-
                aes1: aes@4b501000 {
                        compatible = "ti,omap4-aes";
                        ti,hwmods = "aes1";
 };
 
 #include "omap4-l4.dtsi"
+#include "omap4-l4-abe.dtsi"
 #include "omap44xx-clocks.dtsi"
index 61a06f6..2dc3e19 100644 (file)
        };
 };
 
-&mcpdm {
+&mcpdm_module {
+       /* Module on the SoC needs external clock from the PMIC */
        pinctrl-names = "default";
        pinctrl-0 = <&mcpdm_pins>;
+       status = "okay";
+};
 
+&mcpdm {
        clocks = <&twl6040>;
        clock-names = "pdmclk";
-
-       status = "okay";
 };
 
 &mcbsp1 {
diff --git a/arch/arm/boot/dts/omap5-l4-abe.dtsi b/arch/arm/boot/dts/omap5-l4-abe.dtsi
new file mode 100644 (file)
index 0000000..dc9d053
--- /dev/null
@@ -0,0 +1,447 @@
+&l4_abe {                                              /* 0x40100000 */
+       compatible = "ti,omap5-l4-abe", "simple-bus";
+       reg = <0x40100000 0x400>,
+             <0x40100400 0x400>;
+       reg-names = "la", "ap";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges = <0x00000000 0x40100000 0x100000>,      /* segment 0 */
+                <0x49000000 0x49000000 0x100000>;
+       segment@0 {                                     /* 0x40100000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges =
+                        /* CPU to L4 ABE mapping */
+                        <0x00000000 0x00000000 0x000400>,      /* ap 0 */
+                        <0x00000400 0x00000400 0x000400>,      /* ap 1 */
+                        <0x00022000 0x00022000 0x001000>,      /* ap 2 */
+                        <0x00023000 0x00023000 0x001000>,      /* ap 3 */
+                        <0x00024000 0x00024000 0x001000>,      /* ap 4 */
+                        <0x00025000 0x00025000 0x001000>,      /* ap 5 */
+                        <0x00026000 0x00026000 0x001000>,      /* ap 6 */
+                        <0x00027000 0x00027000 0x001000>,      /* ap 7 */
+                        <0x00028000 0x00028000 0x001000>,      /* ap 8 */
+                        <0x00029000 0x00029000 0x001000>,      /* ap 9 */
+                        <0x0002a000 0x0002a000 0x001000>,      /* ap 10 */
+                        <0x0002b000 0x0002b000 0x001000>,      /* ap 11 */
+                        <0x0002e000 0x0002e000 0x001000>,      /* ap 12 */
+                        <0x0002f000 0x0002f000 0x001000>,      /* ap 13 */
+                        <0x00030000 0x00030000 0x001000>,      /* ap 14 */
+                        <0x00031000 0x00031000 0x001000>,      /* ap 15 */
+                        <0x00032000 0x00032000 0x001000>,      /* ap 16 */
+                        <0x00033000 0x00033000 0x001000>,      /* ap 17 */
+                        <0x00038000 0x00038000 0x001000>,      /* ap 18 */
+                        <0x00039000 0x00039000 0x001000>,      /* ap 19 */
+                        <0x0003a000 0x0003a000 0x001000>,      /* ap 20 */
+                        <0x0003b000 0x0003b000 0x001000>,      /* ap 21 */
+                        <0x0003c000 0x0003c000 0x001000>,      /* ap 22 */
+                        <0x0003d000 0x0003d000 0x001000>,      /* ap 23 */
+                        <0x0003e000 0x0003e000 0x001000>,      /* ap 24 */
+                        <0x0003f000 0x0003f000 0x001000>,      /* ap 25 */
+                        <0x00080000 0x00080000 0x010000>,      /* ap 26 */
+                        <0x00080000 0x00080000 0x001000>,      /* ap 27 */
+                        <0x000a0000 0x000a0000 0x010000>,      /* ap 28 */
+                        <0x000a0000 0x000a0000 0x001000>,      /* ap 29 */
+                        <0x000c0000 0x000c0000 0x010000>,      /* ap 30 */
+                        <0x000c0000 0x000c0000 0x001000>,      /* ap 31 */
+                        <0x000f1000 0x000f1000 0x001000>,      /* ap 32 */
+                        <0x000f2000 0x000f2000 0x001000>,      /* ap 33 */
+
+                        /* L3 to L4 ABE mapping */
+                        <0x49000000 0x49000000 0x000400>,      /* ap 0 */
+                        <0x49000400 0x49000400 0x000400>,      /* ap 1 */
+                        <0x49022000 0x49022000 0x001000>,      /* ap 2 */
+                        <0x49023000 0x49023000 0x001000>,      /* ap 3 */
+                        <0x49024000 0x49024000 0x001000>,      /* ap 4 */
+                        <0x49025000 0x49025000 0x001000>,      /* ap 5 */
+                        <0x49026000 0x49026000 0x001000>,      /* ap 6 */
+                        <0x49027000 0x49027000 0x001000>,      /* ap 7 */
+                        <0x49028000 0x49028000 0x001000>,      /* ap 8 */
+                        <0x49029000 0x49029000 0x001000>,      /* ap 9 */
+                        <0x4902a000 0x4902a000 0x001000>,      /* ap 10 */
+                        <0x4902b000 0x4902b000 0x001000>,      /* ap 11 */
+                        <0x4902e000 0x4902e000 0x001000>,      /* ap 12 */
+                        <0x4902f000 0x4902f000 0x001000>,      /* ap 13 */
+                        <0x49030000 0x49030000 0x001000>,      /* ap 14 */
+                        <0x49031000 0x49031000 0x001000>,      /* ap 15 */
+                        <0x49032000 0x49032000 0x001000>,      /* ap 16 */
+                        <0x49033000 0x49033000 0x001000>,      /* ap 17 */
+                        <0x49038000 0x49038000 0x001000>,      /* ap 18 */
+                        <0x49039000 0x49039000 0x001000>,      /* ap 19 */
+                        <0x4903a000 0x4903a000 0x001000>,      /* ap 20 */
+                        <0x4903b000 0x4903b000 0x001000>,      /* ap 21 */
+                        <0x4903c000 0x4903c000 0x001000>,      /* ap 22 */
+                        <0x4903d000 0x4903d000 0x001000>,      /* ap 23 */
+                        <0x4903e000 0x4903e000 0x001000>,      /* ap 24 */
+                        <0x4903f000 0x4903f000 0x001000>,      /* ap 25 */
+                        <0x49080000 0x49080000 0x010000>,      /* ap 26 */
+                        <0x49080000 0x49080000 0x001000>,      /* ap 27 */
+                        <0x490a0000 0x490a0000 0x010000>,      /* ap 28 */
+                        <0x490a0000 0x490a0000 0x001000>,      /* ap 29 */
+                        <0x490c0000 0x490c0000 0x010000>,      /* ap 30 */
+                        <0x490c0000 0x490c0000 0x001000>,      /* ap 31 */
+                        <0x490f1000 0x490f1000 0x001000>,      /* ap 32 */
+                        <0x490f2000 0x490f2000 0x001000>;      /* ap 33 */
+
+               target-module@22000 {                   /* 0x40122000, ap 2 02.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "mcbsp1";
+                       reg = <0x2208c 0x4>;
+                       reg-names = "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       /* Domains (V, P, C): core, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP5_MCBSP1_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x22000 0x1000>,
+                                <0x49022000 0x49022000 0x1000>;
+
+                       mcbsp1: mcbsp@0 {
+                               compatible = "ti,omap4-mcbsp";
+                               reg = <0x0 0xff>, /* MPU private access */
+                                     <0x49022000 0xff>; /* L3 Interconnect */
+                               reg-names = "mpu", "dma";
+                               interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "common";
+                               ti,buffer-size = <128>;
+                               dmas = <&sdma 33>,
+                                      <&sdma 34>;
+                               dma-names = "tx", "rx";
+                               status = "disabled";
+                       };
+               };
+
+               target-module@24000 {                   /* 0x40124000, ap 4 04.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "mcbsp2";
+                       reg = <0x2408c 0x4>;
+                       reg-names = "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       /* Domains (V, P, C): core, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP5_MCBSP2_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x24000 0x1000>,
+                                <0x49024000 0x49024000 0x1000>;
+
+                       mcbsp2: mcbsp@0 {
+                               compatible = "ti,omap4-mcbsp";
+                               reg = <0x0 0xff>, /* MPU private access */
+                                     <0x49024000 0xff>; /* L3 Interconnect */
+                               reg-names = "mpu", "dma";
+                               interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "common";
+                               ti,buffer-size = <128>;
+                               dmas = <&sdma 17>,
+                                      <&sdma 18>;
+                               dma-names = "tx", "rx";
+                               status = "disabled";
+                       };
+               };
+
+               target-module@26000 {                   /* 0x40126000, ap 6 06.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "mcbsp3";
+                       reg = <0x2608c 0x4>;
+                       reg-names = "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       /* Domains (V, P, C): core, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP5_MCBSP3_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x26000 0x1000>,
+                                <0x49026000 0x49026000 0x1000>;
+
+                       mcbsp3: mcbsp@0 {
+                               compatible = "ti,omap4-mcbsp";
+                               reg = <0x0 0xff>, /* MPU private access */
+                                     <0x49026000 0xff>; /* L3 Interconnect */
+                               reg-names = "mpu", "dma";
+                               interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "common";
+                               ti,buffer-size = <128>;
+                               dmas = <&sdma 19>,
+                                      <&sdma 20>;
+                               dma-names = "tx", "rx";
+                               status = "disabled";
+                       };
+               };
+
+               target-module@28000 {                   /* 0x40128000, ap 8 08.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x28000 0x1000>,
+                                <0x49028000 0x49028000 0x1000>;
+               };
+
+               target-module@2a000 {                   /* 0x4012a000, ap 10 0a.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x2a000 0x1000>,
+                                <0x4902a000 0x4902a000 0x1000>;
+               };
+
+               target-module@2e000 {                   /* 0x4012e000, ap 12 0c.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "dmic";
+                       reg = <0x2e000 0x4>,
+                             <0x2e010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP5_DMIC_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x2e000 0x1000>,
+                                <0x4902e000 0x4902e000 0x1000>;
+
+                       dmic: dmic@0 {
+                               compatible = "ti,omap4-dmic";
+                               reg = <0x0 0x7f>, /* MPU private access */
+                                     <0x4902e000 0x7f>; /* L3 Interconnect */
+                               reg-names = "mpu", "dma";
+                               interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&sdma 67>;
+                               dma-names = "up_link";
+                               status = "disabled";
+                       };
+               };
+
+               target-module@30000 {                   /* 0x40130000, ap 14 0e.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x30000 0x1000>,
+                                <0x49030000 0x49030000 0x1000>;
+               };
+
+               mcpdm_module: target-module@32000 {     /* 0x40132000, ap 16 10.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "mcpdm";
+                       reg = <0x32000 0x4>,
+                             <0x32010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP5_MCPDM_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x32000 0x1000>,
+                                <0x49032000 0x49032000 0x1000>;
+
+                       /* Must be only enabled for boards with pdmclk wired */
+                       status = "disabled";
+
+                       mcpdm: mcpdm@0 {
+                               compatible = "ti,omap4-mcpdm";
+                               reg = <0x0 0x7f>, /* MPU private access */
+                                     <0x49032000 0x7f>; /* L3 Interconnect */
+                               reg-names = "mpu", "dma";
+                               interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&sdma 65>,
+                                      <&sdma 66>;
+                               dma-names = "up_link", "dn_link";
+                       };
+               };
+
+               target-module@38000 {                   /* 0x40138000, ap 18 12.0 */
+                       compatible = "ti,sysc-omap4-timer", "ti,sysc";
+                       ti,hwmods = "timer5";
+                       reg = <0x38000 0x4>,
+                             <0x38010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP5_TIMER5_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x38000 0x1000>,
+                                <0x49038000 0x49038000 0x1000>;
+
+                       timer5: timer@0 {
+                               compatible = "ti,omap5430-timer";
+                               reg = <0x0 0x80>,
+                                     <0x49038000 0x80>;
+                               clocks = <&abe_clkctrl OMAP5_TIMER5_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-dsp;
+                               ti,timer-pwm;
+                       };
+               };
+
+               target-module@3a000 {                   /* 0x4013a000, ap 20 14.0 */
+                       compatible = "ti,sysc-omap4-timer", "ti,sysc";
+                       ti,hwmods = "timer6";
+                       reg = <0x3a000 0x4>,
+                             <0x3a010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP5_TIMER6_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x3a000 0x1000>,
+                                <0x4903a000 0x4903a000 0x1000>;
+
+                       timer6: timer@0 {
+                               compatible = "ti,omap5430-timer";
+                               reg = <0x0 0x80>,
+                                     <0x4903a000 0x80>;
+                               clocks = <&abe_clkctrl OMAP5_TIMER6_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-dsp;
+                               ti,timer-pwm;
+                       };
+               };
+
+               target-module@3c000 {                   /* 0x4013c000, ap 22 16.0 */
+                       compatible = "ti,sysc-omap4-timer", "ti,sysc";
+                       ti,hwmods = "timer7";
+                       reg = <0x3c000 0x4>,
+                             <0x3c010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP5_TIMER7_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x3c000 0x1000>,
+                                <0x4903c000 0x4903c000 0x1000>;
+
+                       timer7: timer@0 {
+                               compatible = "ti,omap5430-timer";
+                               reg = <0x0 0x80>,
+                                     <0x4903c000 0x80>;
+                               clocks = <&abe_clkctrl OMAP5_TIMER7_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-dsp;
+                       };
+               };
+
+               target-module@3e000 {                   /* 0x4013e000, ap 24 18.0 */
+                       compatible = "ti,sysc-omap4-timer", "ti,sysc";
+                       ti,hwmods = "timer8";
+                       reg = <0x3e000 0x4>,
+                             <0x3e010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, abe_pwrdm, abe_clkdm */
+                       clocks = <&abe_clkctrl OMAP5_TIMER8_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x3e000 0x1000>,
+                                <0x4903e000 0x4903e000 0x1000>;
+
+                       timer8: timer@0 {
+                               compatible = "ti,omap5430-timer";
+                               reg = <0x0 0x80>,
+                                     <0x4903e000 0x80>;
+                               clocks = <&abe_clkctrl OMAP5_TIMER8_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-dsp;
+                               ti,timer-pwm;
+                       };
+               };
+
+               target-module@80000 {                   /* 0x40180000, ap 26 1a.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x80000 0x10000>,
+                                <0x49080000 0x49080000 0x10000>;
+               };
+
+               target-module@a0000 {                   /* 0x401a0000, ap 28 1c.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xa0000 0x10000>,
+                                <0x490a0000 0x490a0000 0x10000>;
+               };
+
+               target-module@c0000 {                   /* 0x401c0000, ap 30 1e.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xc0000 0x10000>,
+                                <0x490c0000 0x490c0000 0x10000>;
+               };
+
+               target-module@f1000 {                   /* 0x401f1000, ap 32 20.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xf1000 0x1000>,
+                                <0x490f1000 0x490f1000 0x1000>;
+               };
+       };
+};
+
index 2fefaaf..4b40e47 100644 (file)
                l4_per: interconnect@48000000 {
                };
 
+               l4_abe: interconnect@40100000 {
+               };
+
                ocmcram: ocmcram@40300000 {
                        compatible = "mmio-sram";
                        reg = <0x40300000 0x20000>; /* 128k */
                        ti,iommu-bus-err-back;
                };
 
-               mcpdm: mcpdm@40132000 {
-                       compatible = "ti,omap4-mcpdm";
-                       reg = <0x40132000 0x7f>, /* MPU private access */
-                             <0x49032000 0x7f>; /* L3 Interconnect */
-                       reg-names = "mpu", "dma";
-                       interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "mcpdm";
-                       dmas = <&sdma 65>,
-                              <&sdma 66>;
-                       dma-names = "up_link", "dn_link";
-                       status = "disabled";
-               };
-
-               dmic: dmic@4012e000 {
-                       compatible = "ti,omap4-dmic";
-                       reg = <0x4012e000 0x7f>, /* MPU private access */
-                             <0x4902e000 0x7f>; /* L3 Interconnect */
-                       reg-names = "mpu", "dma";
-                       interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "dmic";
-                       dmas = <&sdma 67>;
-                       dma-names = "up_link";
-                       status = "disabled";
-               };
-
-               mcbsp1: mcbsp@40122000 {
-                       compatible = "ti,omap4-mcbsp";
-                       reg = <0x40122000 0xff>, /* MPU private access */
-                             <0x49022000 0xff>; /* L3 Interconnect */
-                       reg-names = "mpu", "dma";
-                       interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-names = "common";
-                       ti,buffer-size = <128>;
-                       ti,hwmods = "mcbsp1";
-                       dmas = <&sdma 33>,
-                              <&sdma 34>;
-                       dma-names = "tx", "rx";
-                       status = "disabled";
-               };
-
-               mcbsp2: mcbsp@40124000 {
-                       compatible = "ti,omap4-mcbsp";
-                       reg = <0x40124000 0xff>, /* MPU private access */
-                             <0x49024000 0xff>; /* L3 Interconnect */
-                       reg-names = "mpu", "dma";
-                       interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-names = "common";
-                       ti,buffer-size = <128>;
-                       ti,hwmods = "mcbsp2";
-                       dmas = <&sdma 17>,
-                              <&sdma 18>;
-                       dma-names = "tx", "rx";
-                       status = "disabled";
-               };
-
-               mcbsp3: mcbsp@40126000 {
-                       compatible = "ti,omap4-mcbsp";
-                       reg = <0x40126000 0xff>, /* MPU private access */
-                             <0x49026000 0xff>; /* L3 Interconnect */
-                       reg-names = "mpu", "dma";
-                       interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-names = "common";
-                       ti,buffer-size = <128>;
-                       ti,hwmods = "mcbsp3";
-                       dmas = <&sdma 19>,
-                              <&sdma 20>;
-                       dma-names = "tx", "rx";
-                       status = "disabled";
-               };
-
-               timer5: timer@40138000 {
-                       compatible = "ti,omap5430-timer";
-                       reg = <0x40138000 0x80>,
-                             <0x49038000 0x80>;
-                       interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer5";
-                       ti,timer-dsp;
-                       ti,timer-pwm;
-               };
-
-               timer6: timer@4013a000 {
-                       compatible = "ti,omap5430-timer";
-                       reg = <0x4013a000 0x80>,
-                             <0x4903a000 0x80>;
-                       interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer6";
-                       ti,timer-dsp;
-                       ti,timer-pwm;
-               };
-
-               timer7: timer@4013c000 {
-                       compatible = "ti,omap5430-timer";
-                       reg = <0x4013c000 0x80>,
-                             <0x4903c000 0x80>;
-                       interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer7";
-                       ti,timer-dsp;
-               };
-
-               timer8: timer@4013e000 {
-                       compatible = "ti,omap5430-timer";
-                       reg = <0x4013e000 0x80>,
-                             <0x4903e000 0x80>;
-                       interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer8";
-                       ti,timer-dsp;
-                       ti,timer-pwm;
-               };
-
                dmm@4e000000 {
                        compatible = "ti,omap5-dmm";
                        reg = <0x4e000000 0x800>;
 &core_thermal {
        coefficients = <0 2000>;
 };
+
+#include "omap5-l4-abe.dtsi"
+#include "omap54xx-clocks.dtsi"
index bd6907d..65975df 100644 (file)
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
                                        gpio-controller;
+                                       gpio-ranges = <&pm8921_gpio 0 0 44>;
                                        #gpio-cells = <2>;
 
                                };
                                <0x04700300 0x200>,
                                <0x04700500 0x5c>;
                        reg-names = "dsi_pll", "dsi_phy", "dsi_phy_regulator";
-                       clock-names = "iface_clk";
-                       clocks = <&mmcc DSI_M_AHB_CLK>;
+                       clock-names = "iface_clk", "ref";
+                       clocks = <&mmcc DSI_M_AHB_CLK>,
+                                <&cxo_board>;
                };
 
 
index 9e75f97..1008dfb 100644 (file)
                        #address-cells = <3>;
                        #size-cells = <2>;
 
-                       ranges = <0x81000000 0 0x40200000 0x40200000 0 0x00100000
-                                 0x82000000 0 0x40300000 0x40300000 0 0x400000>;
+                       ranges = <0x81000000 0 0x40200000 0x40200000 0 0x00100000>,
+                                <0x82000000 0 0x40300000 0x40300000 0 0x00d00000>;
 
                        interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
                        interrupt-names = "msi";
index 02afc6a..356e953 100644 (file)
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
                                        gpio-controller;
+                                       gpio-ranges = <&pmicgpio 0 0 6>;
                                        #gpio-cells = <2>;
                                };
                        };
index 65a994f..ec5cbc4 100644 (file)
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
                                        gpio-controller;
+                                       gpio-ranges = <&pm8058_gpio 0 0 44>;
                                        #gpio-cells = <2>;
 
                                };
index 8f5ea7a..ea1ca16 100644 (file)
@@ -31,6 +31,7 @@
                        compatible = "qcom,pma8084-gpio", "qcom,spmi-gpio";
                        reg = <0xc000>;
                        gpio-controller;
+                       gpio-ranges = <&pma8084_gpios 0 0 22>;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
index 8ee44a1..ff24301 100644 (file)
        };
 
        leds {
-               status = "okay";
                compatible = "gpio-leds";
 
                led0 {
                        gpios = <&port7 1 GPIO_ACTIVE_LOW>;
                };
+
+               led1 {
+                       gpios = <&io_expander1 0 GPIO_ACTIVE_LOW>;
+               };
+
+               led2 {
+                       gpios = <&io_expander1 1 GPIO_ACTIVE_LOW>;
+               };
+
+               led3 {
+                       gpios = <&io_expander1 2 GPIO_ACTIVE_LOW>;
+               };
        };
 };
 
        clock-frequency = <13330000>;
 };
 
+&i2c3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c3_pins>;
+       status = "okay";
+
+       clock-frequency = <400000>;
+
+       io_expander1: gpio@20 {
+               compatible = "onnn,cat9554";
+               reg = <0x20>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       io_expander2: gpio@21 {
+               compatible = "onnn,cat9554";
+               reg = <0x21>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       eeprom@50 {
+               compatible = "renesas,r1ex24016", "atmel,24c16";
+               reg = <0x50>;
+               pagesize = <16>;
+       };
+};
+
 &usb_x1_clk {
        clock-frequency = <48000000>;
 };
 };
 
 &pinctrl {
+       /* RIIC ch3 (Port Expander, EEPROM (MAC Addr), Audio Codec) */
+       i2c3_pins: i2c3 {
+               pinmux = <RZA1_PINMUX(1, 6, 1)>,        /* RIIC3SCL */
+                        <RZA1_PINMUX(1, 7, 1)>;        /* RIIC3SDA */
+       };
 
        /* Serial Console */
        scif2_pins: serial2 {
index d530f45..f70f4a3 100644 (file)
@@ -19,7 +19,7 @@
        };
 
        chosen {
-               bootargs = "ignore_loglevel root=/dev/nfs ip=dhcp rw";
+               bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
                stdout-path = "serial0:115200n8";
        };
 
 };
 
 &bsc {
+       flash@0 {
+               compatible = "cfi-flash", "mtd-rom";
+               reg = <0x0 0x08000000>;
+               bank-width = <2>;
+
+               partitions {
+                       compatible = "fixed-partitions";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       partition@0 {
+                               label = "uboot";
+                               reg = <0x00000000 0x00040000>;
+                               read-only;
+                       };
+                       partition@40000 {
+                               label = "uboot-env";
+                               reg = <0x00040000 0x00040000>;
+                               read-only;
+                       };
+                       partition@80000 {
+                               label = "flash";
+                               reg = <0x00080000 0x07f80000>;
+                       };
+               };
+       };
+
        ethernet@8000000 {
                compatible = "smsc,lan9220", "smsc,lan9115";
                reg = <0x08000000 0x1000>;
index 77d1824..2840eb0 100644 (file)
                stdout-path = "serial1:115200n8";
        };
 
+       hdmi-out {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_con: endpoint {
+                               remote-endpoint = <&bridge_out>;
+                       };
+               };
+       };
+
        memory@40000000 {
                device_type = "memory";
                reg = <0 0x40000000 0 0x20000000>;
        status = "okay";
 };
 
+&du {
+       pinctrl-0 = <&du0_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
+
+       ports {
+               port@0 {
+                       endpoint {
+                               remote-endpoint = <&bridge_in>;
+                       };
+               };
+       };
+};
+
+&ehci1 {
+       status = "okay";
+};
+
 &extal_clk {
        clock-frequency = <20000000>;
 };
 
+&gpio2 {
+       interrupt-fixup {
+               gpio-hog;
+               gpios = <29 GPIO_ACTIVE_HIGH>;
+               line-name = "hdmi-hpd-int";
+               input;
+       };
+};
+
+&hsusb0 {
+       status = "okay";
+};
+
 &i2c3 {
        pinctrl-0 = <&i2c3_pins>;
        pinctrl-names = "default";
        };
 };
 
+&i2c4 {
+       pinctrl-0 = <&i2c4_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
+       clock-frequency = <100000>;
+
+       hdmi@39 {
+               compatible = "sil,sii9022";
+               reg = <0x39>;
+               interrupt-parent = <&gpio2>;
+               interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               bridge_in: endpoint {
+                                       remote-endpoint = <&du_out_rgb0>;
+                               };
+                       };
+
+                       port@1 {
+                               reg = <1>;
+                               bridge_out: endpoint {
+                                       remote-endpoint = <&hdmi_con>;
+                               };
+                       };
+               };
+       };
+};
+
+&ohci1 {
+       status = "okay";
+};
+
 &pfc {
        avb_pins: avb {
                groups = "avb_mdio", "avb_gmii_tx_rx";
                function = "avb";
        };
 
+       du0_pins: du0 {
+               groups = "du0_rgb888", "du0_sync", "du0_disp", "du0_clk0_out";
+               function = "du0";
+       };
+
+       i2c4_pins: i2c4 {
+               groups = "i2c4_e";
+               function = "i2c4";
+       };
+
        i2c3_pins: i2c3 {
                groups = "i2c3_c";
                function = "i2c3";
                function = "sdhi2";
                power-source = <1800>;
        };
+
+       usb0_pins: usb0 {
+               groups = "usb0";
+               function = "usb0";
+       };
+
+       usb1_pins: usb1 {
+               groups = "usb1";
+               function = "usb1";
+       };
 };
 
 &qspi0 {
        sd-uhs-sdr50;
        status = "okay";
 };
+
+&usb2_phy0 {
+       status = "okay";
+};
+
+&usb2_phy1 {
+       status = "okay";
+};
+
+&usbphy0 {
+       pinctrl-0 = <&usb0_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
+};
+
+&usbphy1 {
+       pinctrl-0 = <&usb1_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
+};
index f4e232b..56cb10b 100644 (file)
                        status = "disabled";
                };
 
+               hsusb0: hsusb@e6590000 {
+                       compatible = "renesas,usbhs-r8a77470",
+                                    "renesas,rcar-gen2-usbhs";
+                       reg = <0 0xe6590000 0 0x100>;
+                       interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 704>;
+                       dmas = <&usb_dmac00 0>, <&usb_dmac00 1>,
+                              <&usb_dmac10 0>, <&usb_dmac10 1>;
+                       dma-names = "ch0", "ch1", "ch2", "ch3";
+                       renesas,buswait = <4>;
+                       phys = <&usb0 1>;
+                       phy-names = "usb";
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 704>;
+                       status = "disabled";
+               };
+
+               usbphy0: usb-phy@e6590100 {
+                       compatible = "renesas,usb-phy-r8a77470",
+                                    "renesas,rcar-gen2-usb-phy";
+                       reg = <0 0xe6590100 0 0x100>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       clocks = <&cpg CPG_MOD 704>;
+                       clock-names = "usbhs";
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 704>;
+                       status = "disabled";
+
+                       usb0: usb-channel@0 {
+                               reg = <0>;
+                               #phy-cells = <1>;
+                       };
+               };
+
+               hsusb1: hsusb@e6598000 {
+                       compatible = "renesas,usbhs-r8a77470",
+                                    "renesas,rcar-gen2-usbhs";
+                       reg = <0 0xe6598000 0 0x100>;
+                       interrupts = <GIC_SPI 291 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 706>;
+                       dmas = <&usb_dmac01 0>, <&usb_dmac01 1>,
+                              <&usb_dmac11 0>, <&usb_dmac11 1>;
+                       dma-names = "ch0", "ch1", "ch2", "ch3";
+                       renesas,buswait = <4>;
+                       /* We need to turn on usbphy0 to make usbphy1 to work */
+                       phys = <&usb1 1>;
+                       phy-names = "usb";
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 706>;
+                       status = "disabled";
+               };
+
+               usbphy1: usb-phy@e6598100 {
+                       compatible = "renesas,usb-phy-r8a77470",
+                                    "renesas,rcar-gen2-usb-phy";
+                       reg = <0 0xe6598100 0 0x100>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       clocks = <&cpg CPG_MOD 706>;
+                       clock-names = "usbhs";
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 706>;
+                       status = "disabled";
+
+                       usb1: usb-channel@0 {
+                               reg = <0>;
+                               #phy-cells = <1>;
+                       };
+               };
+
                usb_dmac00: dma-controller@e65a0000 {
                        compatible = "renesas,r8a77470-usb-dmac",
                                     "renesas,usb-dmac";
                        status = "disabled";
                };
 
+               hscif0: serial@e62c0000 {
+                       compatible = "renesas,hscif-r8a77470",
+                                    "renesas,rcar-gen2-hscif", "renesas,hscif";
+                       reg = <0 0xe62c0000 0 0x60>;
+                       interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 717>,
+                                <&cpg CPG_CORE R8A77470_CLK_ZS>, <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
+                              <&dmac1 0x39>, <&dmac1 0x3a>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 717>;
+                       status = "disabled";
+               };
+
+               hscif1: serial@e62c8000 {
+                       compatible = "renesas,hscif-r8a77470",
+                                    "renesas,rcar-gen2-hscif", "renesas,hscif";
+                       reg = <0 0xe62c8000 0 0x60>;
+                       interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 716>,
+                                <&cpg CPG_CORE R8A77470_CLK_ZS>, <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
+                              <&dmac1 0x4d>, <&dmac1 0x4e>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 716>;
+                       status = "disabled";
+               };
+
+               hscif2: serial@e62d0000 {
+                       compatible = "renesas,hscif-r8a77470",
+                                    "renesas,rcar-gen2-hscif", "renesas,hscif";
+                       reg = <0 0xe62d0000 0 0x60>;
+                       interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 713>,
+                                <&cpg CPG_CORE R8A77470_CLK_ZS>, <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac0 0x3b>, <&dmac0 0x3c>,
+                              <&dmac1 0x3b>, <&dmac1 0x3c>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 713>;
+                       status = "disabled";
+               };
+
+               pwm0: pwm@e6e30000 {
+                       compatible = "renesas,pwm-r8a77470", "renesas,pwm-rcar";
+                       reg = <0 0xe6e30000 0 0x8>;
+                       clocks = <&cpg CPG_MOD 523>;
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
+                       #pwm-cells = <2>;
+                       status = "disabled";
+               };
+
+               pwm1: pwm@e6e31000 {
+                       compatible = "renesas,pwm-r8a77470", "renesas,pwm-rcar";
+                       reg = <0 0xe6e31000 0 0x8>;
+                       clocks = <&cpg CPG_MOD 523>;
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
+                       #pwm-cells = <2>;
+                       status = "disabled";
+               };
+
+               pwm2: pwm@e6e32000 {
+                       compatible = "renesas,pwm-r8a77470", "renesas,pwm-rcar";
+                       reg = <0 0xe6e32000 0 0x8>;
+                       clocks = <&cpg CPG_MOD 523>;
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
+                       #pwm-cells = <2>;
+                       status = "disabled";
+               };
+
+               pwm3: pwm@e6e33000 {
+                       compatible = "renesas,pwm-r8a77470", "renesas,pwm-rcar";
+                       reg = <0 0xe6e33000 0 0x8>;
+                       clocks = <&cpg CPG_MOD 523>;
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
+                       #pwm-cells = <2>;
+                       status = "disabled";
+               };
+
+               pwm4: pwm@e6e34000 {
+                       compatible = "renesas,pwm-r8a77470", "renesas,pwm-rcar";
+                       reg = <0 0xe6e34000 0 0x8>;
+                       clocks = <&cpg CPG_MOD 523>;
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
+                       #pwm-cells = <2>;
+                       status = "disabled";
+               };
+
+               pwm5: pwm@e6e35000 {
+                       compatible = "renesas,pwm-r8a77470", "renesas,pwm-rcar";
+                       reg = <0 0xe6e35000 0 0x8>;
+                       clocks = <&cpg CPG_MOD 523>;
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
+                       #pwm-cells = <2>;
+                       status = "disabled";
+               };
+
+               pwm6: pwm@e6e36000 {
+                       compatible = "renesas,pwm-r8a77470", "renesas,pwm-rcar";
+                       reg = <0 0xe6e36000 0 0x8>;
+                       clocks = <&cpg CPG_MOD 523>;
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
+                       #pwm-cells = <2>;
+                       status = "disabled";
+               };
+
+               vin0: video@e6ef0000 {
+                       compatible = "renesas,vin-r8a77470",
+                                    "renesas,rcar-gen2-vin";
+                       reg = <0 0xe6ef0000 0 0x1000>;
+                       interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 811>;
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 811>;
+                       status = "disabled";
+               };
+
+               vin1: video@e6ef1000 {
+                       compatible = "renesas,vin-r8a77470",
+                                    "renesas,rcar-gen2-vin";
+                       reg = <0 0xe6ef1000 0 0x1000>;
+                       interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 810>;
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 810>;
+                       status = "disabled";
+               };
+
+               ohci0: usb@ee080000 {
+                       compatible = "generic-ohci";
+                       reg = <0 0xee080000 0 0x100>;
+                       interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 703>;
+                       phys = <&usb0 0>, <&usb2_phy0>;
+                       phy-names = "usb";
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 703>;
+                       status = "disabled";
+               };
+
+               ehci0: usb@ee080100 {
+                       compatible = "generic-ehci";
+                       reg = <0 0xee080100 0 0x100>;
+                       interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 703>;
+                       phys = <&usb0 0>, <&usb2_phy0>;
+                       phy-names = "usb";
+                       companion = <&ohci0>;
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 703>;
+                       status = "disabled";
+               };
+
+               usb2_phy0: usb-phy@ee080200 {
+                       compatible = "renesas,usb2-phy-r8a77470";
+                       reg = <0 0xee080200 0 0x700>;
+                       clocks = <&cpg CPG_MOD 703>;
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 703>;
+                       #phy-cells = <0>;
+                       status = "disabled";
+               };
+
+               ohci1: usb@ee0c0000 {
+                       compatible = "generic-ohci";
+                       reg = <0 0xee0c0000 0 0x100>;
+                       interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 705>;
+                       phys = <&usb0 1>, <&usb2_phy1>, <&usb1 0>;
+                       phy-names = "usb";
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 705>;
+                       status = "disabled";
+               };
+
+               ehci1: usb@ee0c0100 {
+                       compatible = "generic-ehci";
+                       reg = <0 0xee0c0100 0 0x100>;
+                       interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 705>;
+                       phys = <&usb0 1>, <&usb2_phy1>, <&usb1 0>;
+                       phy-names = "usb";
+                       companion = <&ohci1>;
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 705>;
+                       status = "disabled";
+               };
+
+               usb2_phy1: usb-phy@ee0c0200 {
+                       compatible = "renesas,usb2-phy-r8a77470";
+                       reg = <0 0xee0c0200 0 0x700>;
+                       clocks = <&cpg CPG_MOD 705>;
+                       power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+                       resets = <&cpg 705>;
+                       #phy-cells = <0>;
+                       status = "disabled";
+               };
+
                sdhi0: sd@ee100000 {
                        compatible = "renesas,sdhi-r8a77470",
                                     "renesas,rcar-gen2-sdhi";
                        resets = <&cpg 408>;
                };
 
+               du: display@feb00000 {
+                       compatible = "renesas,du-r8a77470";
+                       reg = <0 0xfeb00000 0 0x40000>;
+                       interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 724>,
+                                <&cpg CPG_MOD 723>;
+                       clock-names = "du.0", "du.1";
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       du_out_rgb0: endpoint {
+                                       };
+                               };
+                               port@1 {
+                                       reg = <1>;
+                                       du_out_rgb1: endpoint {
+                                       };
+                               };
+                               port@2 {
+                                       reg = <2>;
+                                       du_out_lvds0: endpoint {
+                                       };
+                               };
+                       };
+               };
+
                prr: chipid@ff000044 {
                        compatible = "renesas,prr";
                        reg = <0 0xff000044 0 4>;
index cecb229..0b49956 100644 (file)
@@ -25,7 +25,7 @@
        };
 
        chosen {
-               bootargs = "ignore_loglevel ip=dhcp root=/dev/nfs rw";
+               bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
                stdout-path = "serial0:115200n8";
        };
 
index abc14e7..d4bee1e 100644 (file)
@@ -21,7 +21,7 @@
        };
 
        chosen {
-               bootargs = "ignore_loglevel root=/dev/nfs ip=on";
+               bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
                stdout-path = "serial0:115200n8";
        };
 
index f923012..b6fa80c 100644 (file)
        };
 };
 
+&iic3 {
+       status = "okay";
+
+       pmic@58 {
+               compatible = "dlg,da9063";
+               reg = <0x58>;
+               interrupt-parent = <&irqc>;
+               interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+
+               rtc {
+                       compatible = "dlg,da9063-rtc";
+               };
+
+               wdt {
+                       compatible = "dlg,da9063-watchdog";
+               };
+       };
+};
+
 &du {
        pinctrl-0 = <&du0_pins &du1_pins>;
        pinctrl-names = "default";
index 8e9eb4b..38fb43d 100644 (file)
@@ -22,6 +22,7 @@
                i2c3 = &i2c3;
                i2c4 = &i2c4;
                i2c5 = &i2c5;
+               i2c6 = &iic3;
                spi0 = &qspi;
                spi1 = &msiof0;
                spi2 = &msiof1;
                        status = "disabled";
                };
 
+               iic3: i2c@e60b0000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "renesas,iic-r8a7792",
+                                    "renesas,rcar-gen2-iic",
+                                    "renesas,rmobile-iic";
+                       reg = <0 0xe60b0000 0 0x425>;
+                       interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 926>;
+                       dmas = <&dmac0 0x77>, <&dmac0 0x78>,
+                              <&dmac1 0x77>, <&dmac1 0x78>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
+                       resets = <&cpg 926>;
+                       status = "disabled";
+               };
+
                dmac0: dma-controller@e6700000 {
                        compatible = "renesas,dmac-r8a7792",
                                     "renesas,rcar-dmac";
index ef7e2a8..0ab3d8d 100644 (file)
        };
 };
 
+&pci0 {
+       status = "okay";
+       pinctrl-0 = <&usb0_pins>;
+       pinctrl-names = "default";
+};
+
+&pci1 {
+       status = "okay";
+       pinctrl-0 = <&usb1_pins>;
+       pinctrl-names = "default";
+};
+
+&usbphy {
+       status = "okay";
+};
+
 &du {
        pinctrl-0 = <&du_pins>;
        pinctrl-names = "default";
                function = "sdhi1";
                power-source = <1800>;
        };
+
+       usb0_pins: usb0 {
+               groups = "usb0";
+               function = "usb0";
+       };
+
+       usb1_pins: usb1 {
+               groups = "usb1";
+               function = "usb1";
+       };
 };
 
 &cmt0 {
        pinctrl-names = "i2c-exio4";
 };
 
+&i2c7 {
+       status = "okay";
+       clock-frequency = <100000>;
+
+       pmic@58 {
+               compatible = "dlg,da9063";
+               reg = <0x58>;
+               interrupt-parent = <&gpio3>;
+               interrupts = <31 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+
+               rtc {
+                       compatible = "dlg,da9063-rtc";
+               };
+
+               wdt {
+                       compatible = "dlg,da9063-watchdog";
+               };
+       };
+};
+
 &vin0 {
        status = "okay";
        pinctrl-0 = <&vin0_pins>;
index 0173eb1..fb3cf00 100644 (file)
 &pinctrl {
        leds {
                led_ctl: led-ctl {
-                       rockchip,pins = <2 30 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pmic {
                pmic_int: pmic-int {
-                       rockchip,pins = <2 2 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_default>;
                };
        };
 
        sdio {
                bt_wake_h: bt-wake-h {
-                       rockchip,pins = <2 8 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_default>;
                };
        };
 
        sdmmc {
                sdmmc_pwr: sdmmc-pwr {
-                       rockchip,pins = <2 28 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        sleep {
                global_pwroff: global-pwroff {
-                       rockchip,pins = <2 7 RK_FUNC_1 &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PA7 1 &pcfg_pull_none>;
                };
        };
 };
index 59c9086..0290ea4 100644 (file)
 
                pwm0 {
                        pwm0_pin: pwm0-pin {
-                               rockchip,pins = <0 0 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA0 2 &pcfg_pull_none>;
                        };
                };
 
                pwm1 {
                        pwm1_pin: pwm1-pin {
-                               rockchip,pins = <0 1 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA1 2 &pcfg_pull_none>;
                        };
                };
 
                pwm2 {
                        pwm2_pin: pwm2-pin {
-                               rockchip,pins = <0 1 2 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA1 2 &pcfg_pull_none>;
                        };
                };
 
                pwm3 {
                        pwm3_pin: pwm3-pin {
-                               rockchip,pins = <0 27 1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PD3 1 &pcfg_pull_none>;
                        };
                };
 
                sdmmc {
                        sdmmc_clk: sdmmc-clk {
-                               rockchip,pins = <1 16 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PC0 1 &pcfg_pull_none>;
                        };
 
                        sdmmc_cmd: sdmmc-cmd {
-                               rockchip,pins = <1 15 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PB7 1 &pcfg_pull_default>;
                        };
 
                        sdmmc_cd: sdmmc-cd {
-                               rockchip,pins = <1 17 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PC1 1 &pcfg_pull_default>;
                        };
 
                        sdmmc_bus1: sdmmc-bus1 {
-                               rockchip,pins = <1 18 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PC2 1 &pcfg_pull_default>;
                        };
 
                        sdmmc_bus4: sdmmc-bus4 {
-                               rockchip,pins = <1 18 RK_FUNC_1 &pcfg_pull_default>,
-                                               <1 19 RK_FUNC_1 &pcfg_pull_default>,
-                                               <1 20 RK_FUNC_1 &pcfg_pull_default>,
-                                               <1 21 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PC2 1 &pcfg_pull_default>,
+                                               <1 RK_PC3 1 &pcfg_pull_default>,
+                                               <1 RK_PC4 1 &pcfg_pull_default>,
+                                               <1 RK_PC5 1 &pcfg_pull_default>;
                        };
                };
 
                sdio {
                        sdio_bus1: sdio-bus1 {
-                               rockchip,pins = <0 11 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <0 RK_PB3 1 &pcfg_pull_default>;
                        };
 
                        sdio_bus4: sdio-bus4 {
-                               rockchip,pins = <0 11 RK_FUNC_1 &pcfg_pull_default>,
-                                               <0 12 RK_FUNC_1 &pcfg_pull_default>,
-                                               <0 13 RK_FUNC_1 &pcfg_pull_default>,
-                                               <0 14 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <0 RK_PB3 1 &pcfg_pull_default>,
+                                               <0 RK_PB4 1 &pcfg_pull_default>,
+                                               <0 RK_PB5 1 &pcfg_pull_default>,
+                                               <0 RK_PB6 1 &pcfg_pull_default>;
                        };
 
                        sdio_cmd: sdio-cmd {
-                               rockchip,pins = <0 8 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <0 RK_PB0 1 &pcfg_pull_default>;
                        };
 
                        sdio_clk: sdio-clk {
-                               rockchip,pins = <0 9 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PB1 1 &pcfg_pull_none>;
                        };
                };
 
                         * We also have external pulls, so disable the internal ones.
                         */
                        emmc_clk: emmc-clk {
-                               rockchip,pins = <2 4 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PA4 2 &pcfg_pull_none>;
                        };
 
                        emmc_cmd: emmc-cmd {
-                               rockchip,pins = <2 1 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <2 RK_PA1 2 &pcfg_pull_default>;
                        };
 
                        emmc_bus8: emmc-bus8 {
-                               rockchip,pins = <1 24 RK_FUNC_2 &pcfg_pull_default>,
-                                               <1 25 RK_FUNC_2 &pcfg_pull_default>,
-                                               <1 26 RK_FUNC_2 &pcfg_pull_default>,
-                                               <1 27 RK_FUNC_2 &pcfg_pull_default>,
-                                               <1 28 RK_FUNC_2 &pcfg_pull_default>,
-                                               <1 29 RK_FUNC_2 &pcfg_pull_default>,
-                                               <1 30 RK_FUNC_2 &pcfg_pull_default>,
-                                               <1 31 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PD0 2 &pcfg_pull_default>,
+                                               <1 RK_PD1 2 &pcfg_pull_default>,
+                                               <1 RK_PD2 2 &pcfg_pull_default>,
+                                               <1 RK_PD3 2 &pcfg_pull_default>,
+                                               <1 RK_PD4 2 &pcfg_pull_default>,
+                                               <1 RK_PD5 2 &pcfg_pull_default>,
+                                               <1 RK_PD6 2 &pcfg_pull_default>,
+                                               <1 RK_PD7 2 &pcfg_pull_default>;
                        };
                };
 
                emac {
                        emac_xfer: emac-xfer {
-                               rockchip,pins = <2 10 RK_FUNC_1 &pcfg_pull_default>, /* crs_dvalid */
-                                               <2 13 RK_FUNC_1 &pcfg_pull_default>, /* tx_en */
-                                               <2 14 RK_FUNC_1 &pcfg_pull_default>, /* mac_clk */
-                                               <2 15 RK_FUNC_1 &pcfg_pull_default>, /* rx_err */
-                                               <2 16 RK_FUNC_1 &pcfg_pull_default>, /* rxd1 */
-                                               <2 17 RK_FUNC_1 &pcfg_pull_default>, /* rxd0 */
-                                               <2 18 RK_FUNC_1 &pcfg_pull_default>, /* txd1 */
-                                               <2 19 RK_FUNC_1 &pcfg_pull_default>; /* txd0 */
+                               rockchip,pins = <2 RK_PB2 1 &pcfg_pull_default>, /* crs_dvalid */
+                                               <2 RK_PB5 1 &pcfg_pull_default>, /* tx_en */
+                                               <2 RK_PB6 1 &pcfg_pull_default>, /* mac_clk */
+                                               <2 RK_PB7 1 &pcfg_pull_default>, /* rx_err */
+                                               <2 RK_PC0 1 &pcfg_pull_default>, /* rxd1 */
+                                               <2 RK_PC1 1 &pcfg_pull_default>, /* rxd0 */
+                                               <2 RK_PC2 1 &pcfg_pull_default>, /* txd1 */
+                                               <2 RK_PC3 1 &pcfg_pull_default>; /* txd0 */
                        };
 
                        emac_mdio: emac-mdio {
-                               rockchip,pins = <2 12 RK_FUNC_1 &pcfg_pull_default>, /* mac_md */
-                                               <2 25 RK_FUNC_1 &pcfg_pull_default>; /* mac_mdclk */
+                               rockchip,pins = <2 RK_PB4 1 &pcfg_pull_default>, /* mac_md */
+                                               <2 RK_PD1 1 &pcfg_pull_default>; /* mac_mdclk */
                        };
                };
 
                i2c0 {
                        i2c0_xfer: i2c0-xfer {
-                               rockchip,pins = <0 0 RK_FUNC_1 &pcfg_pull_none>,
-                                               <0 1 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA0 1 &pcfg_pull_none>,
+                                               <0 RK_PA1 1 &pcfg_pull_none>;
                        };
                };
 
                i2c1 {
                        i2c1_xfer: i2c1-xfer {
-                               rockchip,pins = <0 2 RK_FUNC_1 &pcfg_pull_none>,
-                                               <0 3 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA2 1 &pcfg_pull_none>,
+                                               <0 RK_PA3 1 &pcfg_pull_none>;
                        };
                };
 
                i2c2 {
                        i2c2_xfer: i2c2-xfer {
-                               rockchip,pins = <2 20 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 21 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PC4 1 &pcfg_pull_none>,
+                                               <2 RK_PC5 1 &pcfg_pull_none>;
                        };
                };
 
                i2s {
                        i2s_bus: i2s-bus {
-                               rockchip,pins = <1 0 RK_FUNC_1 &pcfg_pull_default>,
-                                               <1 1 RK_FUNC_1 &pcfg_pull_default>,
-                                               <1 2 RK_FUNC_1 &pcfg_pull_default>,
-                                               <1 3 RK_FUNC_1 &pcfg_pull_default>,
-                                               <1 4 RK_FUNC_1 &pcfg_pull_default>,
-                                               <1 5 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PA0 1 &pcfg_pull_default>,
+                                               <1 RK_PA1 1 &pcfg_pull_default>,
+                                               <1 RK_PA2 1 &pcfg_pull_default>,
+                                               <1 RK_PA3 1 &pcfg_pull_default>,
+                                               <1 RK_PA4 1 &pcfg_pull_default>,
+                                               <1 RK_PA5 1 &pcfg_pull_default>;
                        };
                };
 
                hdmi {
                        hdmi_ctl: hdmi-ctl {
-                               rockchip,pins = <1 8  RK_FUNC_1 &pcfg_pull_none>,
-                                               <1 9  RK_FUNC_1 &pcfg_pull_none>,
-                                               <1 10 RK_FUNC_1 &pcfg_pull_none>,
-                                               <1 11 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB0  1 &pcfg_pull_none>,
+                                               <1 RK_PB1  1 &pcfg_pull_none>,
+                                               <1 RK_PB2 1 &pcfg_pull_none>,
+                                               <1 RK_PB3 1 &pcfg_pull_none>;
                        };
                };
 
                uart0 {
                        uart0_xfer: uart0-xfer {
-                               rockchip,pins = <0 16 RK_FUNC_1 &pcfg_pull_default>,
-                                               <0 17 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PC0 1 &pcfg_pull_default>,
+                                               <0 RK_PC1 1 &pcfg_pull_none>;
                        };
 
                        uart0_cts: uart0-cts {
-                               rockchip,pins = <0 18 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <0 RK_PC2 1 &pcfg_pull_default>;
                        };
 
                        uart0_rts: uart0-rts {
-                               rockchip,pins = <0 19 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PC3 1 &pcfg_pull_none>;
                        };
                };
 
                uart1 {
                        uart1_xfer: uart1-xfer {
-                               rockchip,pins = <2 22 RK_FUNC_1 &pcfg_pull_default>,
-                                               <2 23 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PC6 1 &pcfg_pull_default>,
+                                               <2 RK_PC7 1 &pcfg_pull_none>;
                        };
                        /* no rts / cts for uart1 */
                };
 
                uart2 {
                        uart2_xfer: uart2-xfer {
-                               rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_default>,
-                                               <1 19 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PC2 2 &pcfg_pull_default>,
+                                               <1 RK_PC3 2 &pcfg_pull_none>;
                        };
                        /* no rts / cts for uart2 */
                };
 
                spi-pins {
                        spi_txd:spi-txd {
-                               rockchip,pins = <1 29 RK_FUNC_3 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PD5 3 &pcfg_pull_default>;
                        };
 
                        spi_rxd:spi-rxd {
-                               rockchip,pins = <1 28 RK_FUNC_3 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PD4 3 &pcfg_pull_default>;
                        };
 
                        spi_clk:spi-clk {
-                               rockchip,pins = <2 0 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <2 RK_PA0 2 &pcfg_pull_default>;
                        };
 
                        spi_cs0:spi-cs0 {
-                               rockchip,pins = <1 30 RK_FUNC_3 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PD6 3 &pcfg_pull_default>;
 
                        };
 
                        spi_cs1:spi-cs1 {
-                               rockchip,pins = <1 31 RK_FUNC_3 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PD7 3 &pcfg_pull_default>;
 
                        };
                };
index ce525b9..7e01f64 100644 (file)
 &pinctrl {
        lan8720a {
                phy_int: phy-int {
-                       rockchip,pins = <RK_GPIO1 26 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 9d2216d..365eff6 100644 (file)
                };
        };
 
+       hdmi_con {
+               compatible = "hdmi-connector";
+               type = "c";
+
+               port {
+                       hdmi_con_in: endpoint {
+                               remote-endpoint = <&hdmi_out_con>;
+                       };
+               };
+       };
+
        vcc_io: vcc-io {
                compatible = "regulator-fixed";
                regulator-name = "vcc_io";
        };
 };
 
+&hdmi {
+       status = "okay";
+};
+
+&hdmi_in_vop1 {
+       status = "disabled";
+};
+
+&hdmi_out {
+       hdmi_out_con: endpoint {
+               remote-endpoint = <&hdmi_con_in>;
+       };
+};
+
 &mmc0 {
        bus-width = <4>;
        cap-mmc-highspeed;
 &pinctrl {
        usb-host {
                host_drv: host-drv {
-                       rockchip,pins = <RK_GPIO0 6 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_default>;
                };
        };
 
        usb-otg {
                otg_drv: otg-drv {
-                       rockchip,pins = <RK_GPIO0 5 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_default>;
                };
        };
 
        sdmmc {
                sdmmc_pwr: sdmmc-pwr {
-                       rockchip,pins = <RK_GPIO3 7 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_default>;
                };
        };
 
        sdio {
                wifi_pwr: wifi-pwr {
-                       rockchip,pins = <RK_GPIO3 24 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <3 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
        status = "okay";
 };
 
+&vop0 {
+       status = "okay";
+};
+
 &wdt {
        status = "okay";
 };
index 949fa80..f9db6bb 100644 (file)
 
        ak8963 {
                comp_int: comp-int {
-                       rockchip,pins = <4 17 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <4 RK_PC1 RK_FUNC_GPIO &pcfg_pull_default>;
                };
        };
 
        emac {
                rmii_rst: rmii-rst {
-                       rockchip,pins = <1 30 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <1 RK_PD6 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 
        ir {
                ir_int: ir-int {
-                       rockchip,pins = <6 1 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <6 RK_PA1 RK_FUNC_GPIO &pcfg_pull_default>;
                };
        };
 
        keys {
                pwr_key: pwr-key {
-                       rockchip,pins = <6 2 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <6 RK_PA2 RK_FUNC_GPIO &pcfg_pull_default>;
                };
        };
 
        mma8452 {
                gsensor_int: gsensor-int {
-                       rockchip,pins = <4 16 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <4 RK_PC0 RK_FUNC_GPIO &pcfg_pull_default>;
                };
        };
 
        mmc {
                sdmmc_pwr: sdmmc-pwr {
-                       rockchip,pins = <3 7 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_default>;
                };
        };
 
        usb_host {
                host_drv: host-drv {
-                       rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_default>;
                };
 
                hub_rst: hub-rst {
-                       rockchip,pins = <1 31 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <1 RK_PD7 RK_FUNC_GPIO &pcfg_output_high>;
                };
 
                sata_pwr: sata-pwr {
-                       rockchip,pins = <4 22 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <4 RK_PC6 RK_FUNC_GPIO &pcfg_pull_default>;
                };
 
                sata_reset: sata-reset {
-                       rockchip,pins = <0 13 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 
        usb_otg {
                otg_drv: otg-drv {
-                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_default>;
                };
        };
 
        tps {
                pmic_int: pmic-int {
-                       rockchip,pins = <6 4 RK_FUNC_GPIO &pcfg_pull_default>;
+                       rockchip,pins = <6 RK_PA4 RK_FUNC_GPIO &pcfg_pull_default>;
                };
 
                pwr_hold: pwr-hold {
-                       rockchip,pins = <6 8 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <6 RK_PB0 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 };
index 653127a..3d1b02f 100644 (file)
                vop0_out: port {
                        #address-cells = <1>;
                        #size-cells = <0>;
+
+                       vop0_out_hdmi: endpoint@0 {
+                               reg = <0>;
+                               remote-endpoint = <&hdmi_in_vop0>;
+                       };
                };
        };
 
                vop1_out: port {
                        #address-cells = <1>;
                        #size-cells = <0>;
+
+                       vop1_out_hdmi: endpoint@0 {
+                               reg = <0>;
+                               remote-endpoint = <&hdmi_in_vop1>;
+                       };
+               };
+       };
+
+       hdmi: hdmi@10116000 {
+               compatible = "rockchip,rk3066-hdmi";
+               reg = <0x10116000 0x2000>;
+               interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru HCLK_HDMI>;
+               clock-names = "hclk";
+               pinctrl-names = "default";
+               pinctrl-0 = <&hdmii2c_xfer>, <&hdmi_hpd>;
+               power-domains = <&power RK3066_PD_VIO>;
+               rockchip,grf = <&grf>;
+               status = "disabled";
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       hdmi_in: port@0 {
+                               reg = <0>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               hdmi_in_vop0: endpoint@0 {
+                                       reg = <0>;
+                                       remote-endpoint = <&vop0_out_hdmi>;
+                               };
+
+                               hdmi_in_vop1: endpoint@1 {
+                                       reg = <1>;
+                                       remote-endpoint = <&vop1_out_hdmi>;
+                               };
+                       };
+
+                       hdmi_out: port@1 {
+                               reg = <1>;
+                       };
                };
        };
 
 
                emac {
                        emac_xfer: emac-xfer {
-                               rockchip,pins = <RK_GPIO1 16 RK_FUNC_2 &pcfg_pull_none>, /* mac_clk */
-                                               <RK_GPIO1 17 RK_FUNC_2 &pcfg_pull_none>, /* tx_en */
-                                               <RK_GPIO1 18 RK_FUNC_2 &pcfg_pull_none>, /* txd1 */
-                                               <RK_GPIO1 19 RK_FUNC_2 &pcfg_pull_none>, /* txd0 */
-                                               <RK_GPIO1 20 RK_FUNC_2 &pcfg_pull_none>, /* rx_err */
-                                               <RK_GPIO1 21 RK_FUNC_2 &pcfg_pull_none>, /* crs_dvalid */
-                                               <RK_GPIO1 22 RK_FUNC_2 &pcfg_pull_none>, /* rxd1 */
-                                               <RK_GPIO1 23 RK_FUNC_2 &pcfg_pull_none>; /* rxd0 */
+                               rockchip,pins = <1 RK_PC0 2 &pcfg_pull_none>, /* mac_clk */
+                                               <1 RK_PC1 2 &pcfg_pull_none>, /* tx_en */
+                                               <1 RK_PC2 2 &pcfg_pull_none>, /* txd1 */
+                                               <1 RK_PC3 2 &pcfg_pull_none>, /* txd0 */
+                                               <1 RK_PC4 2 &pcfg_pull_none>, /* rx_err */
+                                               <1 RK_PC5 2 &pcfg_pull_none>, /* crs_dvalid */
+                                               <1 RK_PC6 2 &pcfg_pull_none>, /* rxd1 */
+                                               <1 RK_PC7 2 &pcfg_pull_none>; /* rxd0 */
                        };
 
                        emac_mdio: emac-mdio {
-                               rockchip,pins = <RK_GPIO1 24 RK_FUNC_2 &pcfg_pull_none>, /* mac_md */
-                                               <RK_GPIO1 25 RK_FUNC_2 &pcfg_pull_none>; /* mac_mdclk */
+                               rockchip,pins = <1 RK_PD0 2 &pcfg_pull_none>, /* mac_md */
+                                               <1 RK_PD1 2 &pcfg_pull_none>; /* mac_mdclk */
                        };
                };
 
                emmc {
                        emmc_clk: emmc-clk {
-                               rockchip,pins = <RK_GPIO3 31 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PD7 2 &pcfg_pull_default>;
                        };
 
                        emmc_cmd: emmc-cmd {
-                               rockchip,pins = <RK_GPIO4 9 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <4 RK_PB1 2 &pcfg_pull_default>;
                        };
 
                        emmc_rst: emmc-rst {
-                               rockchip,pins = <RK_GPIO4 10 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <4 RK_PB2 2 &pcfg_pull_default>;
                        };
 
                        /*
                         */
                };
 
+               hdmi {
+                       hdmi_hpd: hdmi-hpd {
+                               rockchip,pins = <0 RK_PA0 1 &pcfg_pull_default>;
+                       };
+
+                       hdmii2c_xfer: hdmii2c-xfer {
+                               rockchip,pins = <0 RK_PA1 1 &pcfg_pull_none>,
+                                               <0 RK_PA2 1 &pcfg_pull_none>;
+                       };
+               };
+
                i2c0 {
                        i2c0_xfer: i2c0-xfer {
-                               rockchip,pins = <RK_GPIO2 28 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO2 29 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PD4 1 &pcfg_pull_none>,
+                                               <2 RK_PD5 1 &pcfg_pull_none>;
                        };
                };
 
                i2c1 {
                        i2c1_xfer: i2c1-xfer {
-                               rockchip,pins = <RK_GPIO2 30 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO2 31 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PD6 1 &pcfg_pull_none>,
+                                               <2 RK_PD7 1 &pcfg_pull_none>;
                        };
                };
 
                i2c2 {
                        i2c2_xfer: i2c2-xfer {
-                               rockchip,pins = <RK_GPIO3 0 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO3 1 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PA0 1 &pcfg_pull_none>,
+                                               <3 RK_PA1 1 &pcfg_pull_none>;
                        };
                };
 
                i2c3 {
                        i2c3_xfer: i2c3-xfer {
-                               rockchip,pins = <RK_GPIO3 2 RK_FUNC_2 &pcfg_pull_none>,
-                                               <RK_GPIO3 3 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PA2 2 &pcfg_pull_none>,
+                                               <3 RK_PA3 2 &pcfg_pull_none>;
                        };
                };
 
                i2c4 {
                        i2c4_xfer: i2c4-xfer {
-                               rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO3 5 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PA4 1 &pcfg_pull_none>,
+                                               <3 RK_PA5 1 &pcfg_pull_none>;
                        };
                };
 
                pwm0 {
                        pwm0_out: pwm0-out {
-                               rockchip,pins = <RK_GPIO0 3 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA3 1 &pcfg_pull_none>;
                        };
                };
 
                pwm1 {
                        pwm1_out: pwm1-out {
-                               rockchip,pins = <RK_GPIO0 4 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>;
                        };
                };
 
                pwm2 {
                        pwm2_out: pwm2-out {
-                               rockchip,pins = <RK_GPIO0 30 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PD6 1 &pcfg_pull_none>;
                        };
                };
 
                pwm3 {
                        pwm3_out: pwm3-out {
-                               rockchip,pins = <RK_GPIO0 31 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PD7 1 &pcfg_pull_none>;
                        };
                };
 
                spi0 {
                        spi0_clk: spi0-clk {
-                               rockchip,pins = <RK_GPIO1 5 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PA5 2 &pcfg_pull_default>;
                        };
                        spi0_cs0: spi0-cs0 {
-                               rockchip,pins = <RK_GPIO1 4 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PA4 2 &pcfg_pull_default>;
                        };
                        spi0_tx: spi0-tx {
-                               rockchip,pins = <RK_GPIO1 7 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PA7 2 &pcfg_pull_default>;
                        };
                        spi0_rx: spi0-rx {
-                               rockchip,pins = <RK_GPIO1 6 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PA6 2 &pcfg_pull_default>;
                        };
                        spi0_cs1: spi0-cs1 {
-                               rockchip,pins = <RK_GPIO4 15 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <4 RK_PB7 1 &pcfg_pull_default>;
                        };
                };
 
                spi1 {
                        spi1_clk: spi1-clk {
-                               rockchip,pins = <RK_GPIO2 19 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <2 RK_PC3 2 &pcfg_pull_default>;
                        };
                        spi1_cs0: spi1-cs0 {
-                               rockchip,pins = <RK_GPIO2 20 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <2 RK_PC4 2 &pcfg_pull_default>;
                        };
                        spi1_rx: spi1-rx {
-                               rockchip,pins = <RK_GPIO2 22 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <2 RK_PC6 2 &pcfg_pull_default>;
                        };
                        spi1_tx: spi1-tx {
-                               rockchip,pins = <RK_GPIO2 21 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <2 RK_PC5 2 &pcfg_pull_default>;
                        };
                        spi1_cs1: spi1-cs1 {
-                               rockchip,pins = <RK_GPIO2 23 RK_FUNC_2 &pcfg_pull_default>;
+                               rockchip,pins = <2 RK_PC7 2 &pcfg_pull_default>;
                        };
                };
 
                uart0 {
                        uart0_xfer: uart0-xfer {
-                               rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PA0 1 &pcfg_pull_default>,
+                                               <1 RK_PA1 1 &pcfg_pull_default>;
                        };
 
                        uart0_cts: uart0-cts {
-                               rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PA2 1 &pcfg_pull_default>;
                        };
 
                        uart0_rts: uart0-rts {
-                               rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PA3 1 &pcfg_pull_default>;
                        };
                };
 
                uart1 {
                        uart1_xfer: uart1-xfer {
-                               rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PA4 1 &pcfg_pull_default>,
+                                               <1 RK_PA5 1 &pcfg_pull_default>;
                        };
 
                        uart1_cts: uart1-cts {
-                               rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PA6 1 &pcfg_pull_default>;
                        };
 
                        uart1_rts: uart1-rts {
-                               rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PA7 1 &pcfg_pull_default>;
                        };
                };
 
                uart2 {
                        uart2_xfer: uart2-xfer {
-                               rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <1 RK_PB0 1 &pcfg_pull_default>,
+                                               <1 RK_PB1 1 &pcfg_pull_default>;
                        };
                        /* no rts / cts for uart2 */
                };
 
                uart3 {
                        uart3_xfer: uart3-xfer {
-                               rockchip,pins = <RK_GPIO3 27 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO3 28 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PD3 1 &pcfg_pull_default>,
+                                               <3 RK_PD4 1 &pcfg_pull_default>;
                        };
 
                        uart3_cts: uart3-cts {
-                               rockchip,pins = <RK_GPIO3 29 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PD5 1 &pcfg_pull_default>;
                        };
 
                        uart3_rts: uart3-rts {
-                               rockchip,pins = <RK_GPIO3 30 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PD6 1 &pcfg_pull_default>;
                        };
                };
 
                sd0 {
                        sd0_clk: sd0-clk {
-                               rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PB0 1 &pcfg_pull_default>;
                        };
 
                        sd0_cmd: sd0-cmd {
-                               rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PB1 1 &pcfg_pull_default>;
                        };
 
                        sd0_cd: sd0-cd {
-                               rockchip,pins = <RK_GPIO3 14 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PB6 1 &pcfg_pull_default>;
                        };
 
                        sd0_wp: sd0-wp {
-                               rockchip,pins = <RK_GPIO3 15 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PB7 1 &pcfg_pull_default>;
                        };
 
                        sd0_bus1: sd0-bus-width1 {
-                               rockchip,pins = <RK_GPIO3 10 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PB2 1 &pcfg_pull_default>;
                        };
 
                        sd0_bus4: sd0-bus-width4 {
-                               rockchip,pins = <RK_GPIO3 10 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO3 11 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO3 12 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO3 13 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PB2 1 &pcfg_pull_default>,
+                                               <3 RK_PB3 1 &pcfg_pull_default>,
+                                               <3 RK_PB4 1 &pcfg_pull_default>,
+                                               <3 RK_PB5 1 &pcfg_pull_default>;
                        };
                };
 
                sd1 {
                        sd1_clk: sd1-clk {
-                               rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PC5 1 &pcfg_pull_default>;
                        };
 
                        sd1_cmd: sd1-cmd {
-                               rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PC0 1 &pcfg_pull_default>;
                        };
 
                        sd1_cd: sd1-cd {
-                               rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PC6 1 &pcfg_pull_default>;
                        };
 
                        sd1_wp: sd1-wp {
-                               rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PC7 1 &pcfg_pull_default>;
                        };
 
                        sd1_bus1: sd1-bus-width1 {
-                               rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PC1 1 &pcfg_pull_default>;
                        };
 
                        sd1_bus4: sd1-bus-width4 {
-                               rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <3 RK_PC1 1 &pcfg_pull_default>,
+                                               <3 RK_PC2 1 &pcfg_pull_default>,
+                                               <3 RK_PC3 1 &pcfg_pull_default>,
+                                               <3 RK_PC4 1 &pcfg_pull_default>;
                        };
                };
 
                i2s0 {
                        i2s0_bus: i2s0-bus {
-                               rockchip,pins = <RK_GPIO0 7 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 8 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 9 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 10 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 11 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 12 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 13 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 14 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 15 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <0 RK_PA7 1 &pcfg_pull_default>,
+                                               <0 RK_PB0 1 &pcfg_pull_default>,
+                                               <0 RK_PB1 1 &pcfg_pull_default>,
+                                               <0 RK_PB2 1 &pcfg_pull_default>,
+                                               <0 RK_PB3 1 &pcfg_pull_default>,
+                                               <0 RK_PB4 1 &pcfg_pull_default>,
+                                               <0 RK_PB5 1 &pcfg_pull_default>,
+                                               <0 RK_PB6 1 &pcfg_pull_default>,
+                                               <0 RK_PB7 1 &pcfg_pull_default>;
                        };
                };
 
                i2s1 {
                        i2s1_bus: i2s1-bus {
-                               rockchip,pins = <RK_GPIO0 16 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 17 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 18 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 19 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 20 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 21 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <0 RK_PC0 1 &pcfg_pull_default>,
+                                               <0 RK_PC1 1 &pcfg_pull_default>,
+                                               <0 RK_PC2 1 &pcfg_pull_default>,
+                                               <0 RK_PC3 1 &pcfg_pull_default>,
+                                               <0 RK_PC4 1 &pcfg_pull_default>,
+                                               <0 RK_PC5 1 &pcfg_pull_default>;
                        };
                };
 
                i2s2 {
                        i2s2_bus: i2s2-bus {
-                               rockchip,pins = <RK_GPIO0 24 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 25 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 26 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 27 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 28 RK_FUNC_1 &pcfg_pull_default>,
-                                               <RK_GPIO0 29 RK_FUNC_1 &pcfg_pull_default>;
+                               rockchip,pins = <0 RK_PD0 1 &pcfg_pull_default>,
+                                               <0 RK_PD1 1 &pcfg_pull_default>,
+                                               <0 RK_PD2 1 &pcfg_pull_default>,
+                                               <0 RK_PD3 1 &pcfg_pull_default>,
+                                               <0 RK_PD4 1 &pcfg_pull_default>,
+                                               <0 RK_PD5 1 &pcfg_pull_default>;
                        };
                };
        };
index c0eaa9c..c32e1d4 100644 (file)
 
        usb {
                host_vbus_drv: host-vbus-drv {
-                       rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
                otg_vbus_drv: otg-vbus-drv {
-                       rockchip,pins = <2 31 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PD7 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 94bc81c..c9a7f54 100644 (file)
 
        act8846 {
                act8846_dvs0_ctl: act8846-dvs0-ctl {
-                       rockchip,pins = <RK_GPIO3 27 RK_FUNC_GPIO &pcfg_output_low>;
+                       rockchip,pins = <3 RK_PD3 RK_FUNC_GPIO &pcfg_output_low>;
                };
        };
 
        hym8563 {
                rtc_int: rtc-int {
-                       rockchip,pins = <RK_GPIO0 0 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        lan8720a  {
                phy_int: phy-int {
-                       rockchip,pins = <RK_GPIO3 26 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <3 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        ir-receiver {
                ir_recv_pin: ir-recv-pin {
-                       rockchip,pins = <RK_GPIO0 10 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        sd0 {
                sdmmc_pwr: sdmmc-pwr {
-                       rockchip,pins = <RK_GPIO3 1 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <3 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        usb {
                host_vbus_drv: host-vbus-drv {
-                       rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
                otg_vbus_drv: otg-vbus-drv {
-                       rockchip,pins = <2 31 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PD7 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 3ed4989..10ede65 100644 (file)
 
                emmc {
                        emmc_clk: emmc-clk {
-                               rockchip,pins = <RK_GPIO0 24 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PD0 2 &pcfg_pull_none>;
                        };
 
                        emmc_cmd: emmc-cmd {
-                               rockchip,pins = <RK_GPIO0 26 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PD2 2 &pcfg_pull_up>;
                        };
 
                        emmc_rst: emmc-rst {
-                               rockchip,pins = <RK_GPIO0 27 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PD3 2 &pcfg_pull_none>;
                        };
 
                        /*
 
                emac {
                        emac_xfer: emac-xfer {
-                               rockchip,pins = <RK_GPIO3 16 RK_FUNC_2 &pcfg_pull_none>, /* tx_en */
-                                               <RK_GPIO3 17 RK_FUNC_2 &pcfg_pull_none>, /* txd1 */
-                                               <RK_GPIO3 18 RK_FUNC_2 &pcfg_pull_none>, /* txd0 */
-                                               <RK_GPIO3 19 RK_FUNC_2 &pcfg_pull_none>, /* rxd0 */
-                                               <RK_GPIO3 20 RK_FUNC_2 &pcfg_pull_none>, /* rxd1 */
-                                               <RK_GPIO3 21 RK_FUNC_2 &pcfg_pull_none>, /* mac_clk */
-                                               <RK_GPIO3 22 RK_FUNC_2 &pcfg_pull_none>, /* rx_err */
-                                               <RK_GPIO3 23 RK_FUNC_2 &pcfg_pull_none>; /* crs_dvalid */
+                               rockchip,pins = <3 RK_PC0 2 &pcfg_pull_none>, /* tx_en */
+                                               <3 RK_PC1 2 &pcfg_pull_none>, /* txd1 */
+                                               <3 RK_PC2 2 &pcfg_pull_none>, /* txd0 */
+                                               <3 RK_PC3 2 &pcfg_pull_none>, /* rxd0 */
+                                               <3 RK_PC4 2 &pcfg_pull_none>, /* rxd1 */
+                                               <3 RK_PC5 2 &pcfg_pull_none>, /* mac_clk */
+                                               <3 RK_PC6 2 &pcfg_pull_none>, /* rx_err */
+                                               <3 RK_PC7 2 &pcfg_pull_none>; /* crs_dvalid */
                        };
 
                        emac_mdio: emac-mdio {
-                               rockchip,pins = <RK_GPIO3 24 RK_FUNC_2 &pcfg_pull_none>,
-                                               <RK_GPIO3 25 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PD0 2 &pcfg_pull_none>,
+                                               <3 RK_PD1 2 &pcfg_pull_none>;
                        };
                };
 
                i2c0 {
                        i2c0_xfer: i2c0-xfer {
-                               rockchip,pins = <RK_GPIO1 24 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO1 25 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PD0 1 &pcfg_pull_none>,
+                                               <1 RK_PD1 1 &pcfg_pull_none>;
                        };
                };
 
                i2c1 {
                        i2c1_xfer: i2c1-xfer {
-                               rockchip,pins = <RK_GPIO1 26 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO1 27 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PD2 1 &pcfg_pull_none>,
+                                               <1 RK_PD3 1 &pcfg_pull_none>;
                        };
                };
 
                i2c2 {
                        i2c2_xfer: i2c2-xfer {
-                               rockchip,pins = <RK_GPIO1 28 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO1 29 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PD4 1 &pcfg_pull_none>,
+                                               <1 RK_PD5 1 &pcfg_pull_none>;
                        };
                };
 
                i2c3 {
                        i2c3_xfer: i2c3-xfer {
-                               rockchip,pins = <RK_GPIO3 14 RK_FUNC_2 &pcfg_pull_none>,
-                                               <RK_GPIO3 15 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PB6 2 &pcfg_pull_none>,
+                                               <3 RK_PB7 2 &pcfg_pull_none>;
                        };
                };
 
                i2c4 {
                        i2c4_xfer: i2c4-xfer {
-                               rockchip,pins = <RK_GPIO1 30 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO1 31 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PD6 1 &pcfg_pull_none>,
+                                               <1 RK_PD7 1 &pcfg_pull_none>;
                        };
                };
 
                lcdc1 {
                        lcdc1_dclk: lcdc1-dclk {
-                               rockchip,pins = <2 RK_PD0 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PD0 1 &pcfg_pull_none>;
                        };
 
                        lcdc1_den: lcdc1-den {
-                               rockchip,pins = <2 RK_PD1 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PD1 1 &pcfg_pull_none>;
                        };
 
                        lcdc1_hsync: lcdc1-hsync {
-                               rockchip,pins = <2 RK_PD2 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PD2 1 &pcfg_pull_none>;
                        };
 
                        lcdc1_vsync: lcdc1-vsync {
-                               rockchip,pins = <2 RK_PD3 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PD3 1 &pcfg_pull_none>;
                        };
 
                        lcdc1_rgb24: ldcd1-rgb24 {
-                               rockchip,pins = <2 RK_PA0 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PA1 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PA2 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PA3 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PA4 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PA5 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PA6 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PA7 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PB0 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PB1 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PB2 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PB3 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PB4 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PB5 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PB6 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PB7 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PC0 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PC1 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PC2 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PC3 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PC4 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PC5 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PC6 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 RK_PC7 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PA0 1 &pcfg_pull_none>,
+                                               <2 RK_PA1 1 &pcfg_pull_none>,
+                                               <2 RK_PA2 1 &pcfg_pull_none>,
+                                               <2 RK_PA3 1 &pcfg_pull_none>,
+                                               <2 RK_PA4 1 &pcfg_pull_none>,
+                                               <2 RK_PA5 1 &pcfg_pull_none>,
+                                               <2 RK_PA6 1 &pcfg_pull_none>,
+                                               <2 RK_PA7 1 &pcfg_pull_none>,
+                                               <2 RK_PB0 1 &pcfg_pull_none>,
+                                               <2 RK_PB1 1 &pcfg_pull_none>,
+                                               <2 RK_PB2 1 &pcfg_pull_none>,
+                                               <2 RK_PB3 1 &pcfg_pull_none>,
+                                               <2 RK_PB4 1 &pcfg_pull_none>,
+                                               <2 RK_PB5 1 &pcfg_pull_none>,
+                                               <2 RK_PB6 1 &pcfg_pull_none>,
+                                               <2 RK_PB7 1 &pcfg_pull_none>,
+                                               <2 RK_PC0 1 &pcfg_pull_none>,
+                                               <2 RK_PC1 1 &pcfg_pull_none>,
+                                               <2 RK_PC2 1 &pcfg_pull_none>,
+                                               <2 RK_PC3 1 &pcfg_pull_none>,
+                                               <2 RK_PC4 1 &pcfg_pull_none>,
+                                               <2 RK_PC5 1 &pcfg_pull_none>,
+                                               <2 RK_PC6 1 &pcfg_pull_none>,
+                                               <2 RK_PC7 1 &pcfg_pull_none>;
                        };
                };
 
                pwm0 {
                        pwm0_out: pwm0-out {
-                               rockchip,pins = <RK_GPIO3 27 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PD3 1 &pcfg_pull_none>;
                        };
                };
 
                pwm1 {
                        pwm1_out: pwm1-out {
-                               rockchip,pins = <RK_GPIO3 28 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PD4 1 &pcfg_pull_none>;
                        };
                };
 
                pwm2 {
                        pwm2_out: pwm2-out {
-                               rockchip,pins = <RK_GPIO3 29 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PD5 1 &pcfg_pull_none>;
                        };
                };
 
                pwm3 {
                        pwm3_out: pwm3-out {
-                               rockchip,pins = <RK_GPIO3 30 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PD6 1 &pcfg_pull_none>;
                        };
                };
 
                spi0 {
                        spi0_clk: spi0-clk {
-                               rockchip,pins = <RK_GPIO1 6 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PA6 2 &pcfg_pull_up>;
                        };
                        spi0_cs0: spi0-cs0 {
-                               rockchip,pins = <RK_GPIO1 7 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PA7 2 &pcfg_pull_up>;
                        };
                        spi0_tx: spi0-tx {
-                               rockchip,pins = <RK_GPIO1 5 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PA5 2 &pcfg_pull_up>;
                        };
                        spi0_rx: spi0-rx {
-                               rockchip,pins = <RK_GPIO1 4 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PA4 2 &pcfg_pull_up>;
                        };
                        spi0_cs1: spi0-cs1 {
-                               rockchip,pins = <RK_GPIO1 15 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PB7 1 &pcfg_pull_up>;
                        };
                };
 
                spi1 {
                        spi1_clk: spi1-clk {
-                               rockchip,pins = <RK_GPIO0 30 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PD6 1 &pcfg_pull_up>;
                        };
                        spi1_cs0: spi1-cs0 {
-                               rockchip,pins = <RK_GPIO0 31 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PD7 1 &pcfg_pull_up>;
                        };
                        spi1_rx: spi1-rx {
-                               rockchip,pins = <RK_GPIO0 28 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PD4 1 &pcfg_pull_up>;
                        };
                        spi1_tx: spi1-tx {
-                               rockchip,pins = <RK_GPIO0 29 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PD5 1 &pcfg_pull_up>;
                        };
                        spi1_cs1: spi1-cs1 {
-                               rockchip,pins = <RK_GPIO1 14 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PB6 2 &pcfg_pull_up>;
                        };
                };
 
                uart0 {
                        uart0_xfer: uart0-xfer {
-                               rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_up>,
-                                               <RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PA0 1 &pcfg_pull_up>,
+                                               <1 RK_PA1 1 &pcfg_pull_none>;
                        };
 
                        uart0_cts: uart0-cts {
-                               rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PA2 1 &pcfg_pull_none>;
                        };
 
                        uart0_rts: uart0-rts {
-                               rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PA3 1 &pcfg_pull_none>;
                        };
                };
 
                uart1 {
                        uart1_xfer: uart1-xfer {
-                               rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_up>,
-                                               <RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PA4 1 &pcfg_pull_up>,
+                                               <1 RK_PA5 1 &pcfg_pull_none>;
                        };
 
                        uart1_cts: uart1-cts {
-                               rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PA6 1 &pcfg_pull_none>;
                        };
 
                        uart1_rts: uart1-rts {
-                               rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PA7 1 &pcfg_pull_none>;
                        };
                };
 
                uart2 {
                        uart2_xfer: uart2-xfer {
-                               rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_up>,
-                                               <RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB0 1 &pcfg_pull_up>,
+                                               <1 RK_PB1 1 &pcfg_pull_none>;
                        };
                        /* no rts / cts for uart2 */
                };
 
                uart3 {
                        uart3_xfer: uart3-xfer {
-                               rockchip,pins = <RK_GPIO1 10 RK_FUNC_1 &pcfg_pull_up>,
-                                               <RK_GPIO1 11 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB2 1 &pcfg_pull_up>,
+                                               <1 RK_PB3 1 &pcfg_pull_none>;
                        };
 
                        uart3_cts: uart3-cts {
-                               rockchip,pins = <RK_GPIO1 12 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB4 1 &pcfg_pull_none>;
                        };
 
                        uart3_rts: uart3-rts {
-                               rockchip,pins = <RK_GPIO1 13 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB5 1 &pcfg_pull_none>;
                        };
                };
 
                sd0 {
                        sd0_clk: sd0-clk {
-                               rockchip,pins = <RK_GPIO3 2 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PA2 1 &pcfg_pull_none>;
                        };
 
                        sd0_cmd: sd0-cmd {
-                               rockchip,pins = <RK_GPIO3 3 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PA3 1 &pcfg_pull_none>;
                        };
 
                        sd0_cd: sd0-cd {
-                               rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PB0 1 &pcfg_pull_none>;
                        };
 
                        sd0_wp: sd0-wp {
-                               rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PB1 1 &pcfg_pull_none>;
                        };
 
                        sd0_pwr: sd0-pwr {
-                               rockchip,pins = <RK_GPIO3 1 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PA1 1 &pcfg_pull_none>;
                        };
 
                        sd0_bus1: sd0-bus-width1 {
-                               rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PA4 1 &pcfg_pull_none>;
                        };
 
                        sd0_bus4: sd0-bus-width4 {
-                               rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO3 5 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO3 6 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO3 7 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PA4 1 &pcfg_pull_none>,
+                                               <3 RK_PA5 1 &pcfg_pull_none>,
+                                               <3 RK_PA6 1 &pcfg_pull_none>,
+                                               <3 RK_PA7 1 &pcfg_pull_none>;
                        };
                };
 
                sd1 {
                        sd1_clk: sd1-clk {
-                               rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PC5 1 &pcfg_pull_none>;
                        };
 
                        sd1_cmd: sd1-cmd {
-                               rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PC0 1 &pcfg_pull_none>;
                        };
 
                        sd1_cd: sd1-cd {
-                               rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PC6 1 &pcfg_pull_none>;
                        };
 
                        sd1_wp: sd1-wp {
-                               rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PC7 1 &pcfg_pull_none>;
                        };
 
                        sd1_bus1: sd1-bus-width1 {
-                               rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PC1 1 &pcfg_pull_none>;
                        };
 
                        sd1_bus4: sd1-bus-width4 {
-                               rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PC1 1 &pcfg_pull_none>,
+                                               <3 RK_PC2 1 &pcfg_pull_none>,
+                                               <3 RK_PC3 1 &pcfg_pull_none>,
+                                               <3 RK_PC4 1 &pcfg_pull_none>;
                        };
                };
 
                i2s0 {
                        i2s0_bus: i2s0-bus {
-                               rockchip,pins = <RK_GPIO1 16 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO1 17 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO1 18 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO1 19 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO1 20 RK_FUNC_1 &pcfg_pull_none>,
-                                               <RK_GPIO1 21 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PC0 1 &pcfg_pull_none>,
+                                               <1 RK_PC1 1 &pcfg_pull_none>,
+                                               <1 RK_PC2 1 &pcfg_pull_none>,
+                                               <1 RK_PC3 1 &pcfg_pull_none>,
+                                               <1 RK_PC4 1 &pcfg_pull_none>,
+                                               <1 RK_PC5 1 &pcfg_pull_none>;
                        };
                };
 
                spdif {
                        spdif_tx: spdif-tx {
-                               rockchip,pins = <RK_GPIO1 14 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB6 1 &pcfg_pull_none>;
                        };
                };
        };
index 29f1907..da102ff 100644 (file)
 
                emmc {
                        emmc_clk: emmc-clk {
-                               rockchip,pins = <2 7 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PA7 2 &pcfg_pull_none>;
                        };
 
                        emmc_cmd: emmc-cmd {
-                               rockchip,pins = <1 22 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PC6 2 &pcfg_pull_none>;
                        };
 
                        emmc_bus8: emmc-bus8 {
-                               rockchip,pins = <1 24 RK_FUNC_2 &pcfg_pull_none>,
-                                               <1 25 RK_FUNC_2 &pcfg_pull_none>,
-                                               <1 26 RK_FUNC_2 &pcfg_pull_none>,
-                                               <1 27 RK_FUNC_2 &pcfg_pull_none>,
-                                               <1 28 RK_FUNC_2 &pcfg_pull_none>,
-                                               <1 29 RK_FUNC_2 &pcfg_pull_none>,
-                                               <1 30 RK_FUNC_2 &pcfg_pull_none>,
-                                               <1 31 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PD0 2 &pcfg_pull_none>,
+                                               <1 RK_PD1 2 &pcfg_pull_none>,
+                                               <1 RK_PD2 2 &pcfg_pull_none>,
+                                               <1 RK_PD3 2 &pcfg_pull_none>,
+                                               <1 RK_PD4 2 &pcfg_pull_none>,
+                                               <1 RK_PD5 2 &pcfg_pull_none>,
+                                               <1 RK_PD6 2 &pcfg_pull_none>,
+                                               <1 RK_PD7 2 &pcfg_pull_none>;
                        };
                };
 
                gmac {
                        rgmii_pins: rgmii-pins {
-                               rockchip,pins = <2 14 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 12 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 25 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 19 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
-                                               <2 18 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
-                                               <2 22 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
-                                               <2 23 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
-                                               <2 9 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
-                                               <2 13 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
-                                               <2 17 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 16 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 21 RK_FUNC_2 &pcfg_pull_none>,
-                                               <2 20 RK_FUNC_2 &pcfg_pull_none>,
-                                               <2 11 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 8 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PB6 1 &pcfg_pull_none>,
+                                               <2 RK_PB4 1 &pcfg_pull_none>,
+                                               <2 RK_PD1 1 &pcfg_pull_none>,
+                                               <2 RK_PC3 1 &pcfg_pull_none_drv_12ma>,
+                                               <2 RK_PC2 1 &pcfg_pull_none_drv_12ma>,
+                                               <2 RK_PC6 1 &pcfg_pull_none_drv_12ma>,
+                                               <2 RK_PC7 1 &pcfg_pull_none_drv_12ma>,
+                                               <2 RK_PB1 1 &pcfg_pull_none_drv_12ma>,
+                                               <2 RK_PB5 1 &pcfg_pull_none_drv_12ma>,
+                                               <2 RK_PC1 1 &pcfg_pull_none>,
+                                               <2 RK_PC0 1 &pcfg_pull_none>,
+                                               <2 RK_PC5 2 &pcfg_pull_none>,
+                                               <2 RK_PC4 2 &pcfg_pull_none>,
+                                               <2 RK_PB3 1 &pcfg_pull_none>,
+                                               <2 RK_PB0 1 &pcfg_pull_none>;
                        };
 
                        rmii_pins: rmii-pins {
-                               rockchip,pins = <2 14 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 12 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 25 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 19 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
-                                               <2 18 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
-                                               <2 13 RK_FUNC_1 &pcfg_pull_none_drv_12ma>,
-                                               <2 17 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 16 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 8 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 15 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PB6 1 &pcfg_pull_none>,
+                                               <2 RK_PB4 1 &pcfg_pull_none>,
+                                               <2 RK_PD1 1 &pcfg_pull_none>,
+                                               <2 RK_PC3 1 &pcfg_pull_none_drv_12ma>,
+                                               <2 RK_PC2 1 &pcfg_pull_none_drv_12ma>,
+                                               <2 RK_PB5 1 &pcfg_pull_none_drv_12ma>,
+                                               <2 RK_PC1 1 &pcfg_pull_none>,
+                                               <2 RK_PC0 1 &pcfg_pull_none>,
+                                               <2 RK_PB0 1 &pcfg_pull_none>,
+                                               <2 RK_PB7 1 &pcfg_pull_none>;
                        };
 
                        phy_pins: phy-pins {
-                               rockchip,pins = <2 14 RK_FUNC_2 &pcfg_pull_none>,
-                                               <2 8 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PB6 2 &pcfg_pull_none>,
+                                               <2 RK_PB0 2 &pcfg_pull_none>;
                        };
                };
 
                i2c0 {
                        i2c0_xfer: i2c0-xfer {
-                               rockchip,pins = <0 0 RK_FUNC_1 &pcfg_pull_none>,
-                                               <0 1 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA0 1 &pcfg_pull_none>,
+                                               <0 RK_PA1 1 &pcfg_pull_none>;
                        };
                };
 
                i2c1 {
                        i2c1_xfer: i2c1-xfer {
-                               rockchip,pins = <0 2 RK_FUNC_1 &pcfg_pull_none>,
-                                               <0 3 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA2 1 &pcfg_pull_none>,
+                                               <0 RK_PA3 1 &pcfg_pull_none>;
                        };
                };
 
                i2c2 {
                        i2c2_xfer: i2c2-xfer {
-                               rockchip,pins = <2 20 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 21 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PC4 1 &pcfg_pull_none>,
+                                               <2 RK_PC5 1 &pcfg_pull_none>;
                        };
                };
 
                i2c3 {
                        i2c3_xfer: i2c3-xfer {
-                               rockchip,pins = <0 6 RK_FUNC_1 &pcfg_pull_none>,
-                                               <0 7 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA6 1 &pcfg_pull_none>,
+                                               <0 RK_PA7 1 &pcfg_pull_none>;
                        };
                };
 
                spi-0 {
                        spi0_clk: spi0-clk {
-                               rockchip,pins = <0 9 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PB1 2 &pcfg_pull_up>;
                        };
                        spi0_cs0: spi0-cs0 {
-                               rockchip,pins = <0 14 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PB6 2 &pcfg_pull_up>;
                        };
                        spi0_tx: spi0-tx {
-                               rockchip,pins = <0 11 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PB3 2 &pcfg_pull_up>;
                        };
                        spi0_rx: spi0-rx {
-                               rockchip,pins = <0 13 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PB5 2 &pcfg_pull_up>;
                        };
                        spi0_cs1: spi0-cs1 {
-                               rockchip,pins = <1 12 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PB4 1 &pcfg_pull_up>;
                        };
                };
 
                spi-1 {
                        spi1_clk: spi1-clk {
-                               rockchip,pins = <0 23 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PC7 2 &pcfg_pull_up>;
                        };
                        spi1_cs0: spi1-cs0 {
-                               rockchip,pins = <2 2 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <2 RK_PA2 2 &pcfg_pull_up>;
                        };
                        spi1_rx: spi1-rx {
-                               rockchip,pins = <2 0 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <2 RK_PA0 2 &pcfg_pull_up>;
                        };
                        spi1_tx: spi1-tx {
-                               rockchip,pins = <2 1 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <2 RK_PA1 2 &pcfg_pull_up>;
                        };
                        spi1_cs1: spi1-cs1 {
-                               rockchip,pins = <2 3 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <2 RK_PA3 2 &pcfg_pull_up>;
                        };
                };
 
                i2s1 {
                        i2s1_bus: i2s1-bus {
-                               rockchip,pins = <0 8 RK_FUNC_1 &pcfg_pull_none>,
-                                               <0 9 RK_FUNC_1 &pcfg_pull_none>,
-                                               <0 11 RK_FUNC_1 &pcfg_pull_none>,
-                                               <0 12 RK_FUNC_1 &pcfg_pull_none>,
-                                               <0 13 RK_FUNC_1 &pcfg_pull_none>,
-                                               <0 14 RK_FUNC_1 &pcfg_pull_none>,
-                                               <1 2 RK_FUNC_2 &pcfg_pull_none>,
-                                               <1 4 RK_FUNC_2 &pcfg_pull_none>,
-                                               <1 5 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PB0 1 &pcfg_pull_none>,
+                                               <0 RK_PB1 1 &pcfg_pull_none>,
+                                               <0 RK_PB3 1 &pcfg_pull_none>,
+                                               <0 RK_PB4 1 &pcfg_pull_none>,
+                                               <0 RK_PB5 1 &pcfg_pull_none>,
+                                               <0 RK_PB6 1 &pcfg_pull_none>,
+                                               <1 RK_PA2 2 &pcfg_pull_none>,
+                                               <1 RK_PA4 2 &pcfg_pull_none>,
+                                               <1 RK_PA5 2 &pcfg_pull_none>;
                        };
                };
 
                pwm0 {
                        pwm0_pin: pwm0-pin {
-                               rockchip,pins = <3 21 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PC5 1 &pcfg_pull_none>;
                        };
                };
 
                pwm1 {
                        pwm1_pin: pwm1-pin {
-                               rockchip,pins = <0 30 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PD6 2 &pcfg_pull_none>;
                        };
                };
 
                pwm2 {
                        pwm2_pin: pwm2-pin {
-                               rockchip,pins = <1 12 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB4 2 &pcfg_pull_none>;
                        };
                };
 
                pwm3 {
                        pwm3_pin: pwm3-pin {
-                               rockchip,pins = <1 11 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB3 2 &pcfg_pull_none>;
                        };
                };
 
                spdif {
                        spdif_tx: spdif-tx {
-                               rockchip,pins = <3 31 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PD7 2 &pcfg_pull_none>;
                        };
                };
 
                tsadc {
                        otp_gpio: otp-gpio {
-                               rockchip,pins = <0 24 RK_FUNC_GPIO &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
                        };
 
                        otp_out: otp-out {
-                               rockchip,pins = <0 24 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PD0 2 &pcfg_pull_none>;
                        };
                };
 
                uart0 {
                        uart0_xfer: uart0-xfer {
-                               rockchip,pins = <2 26 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 27 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PD2 1 &pcfg_pull_none>,
+                                               <2 RK_PD3 1 &pcfg_pull_none>;
                        };
 
                        uart0_cts: uart0-cts {
-                               rockchip,pins = <2 29 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PD5 1 &pcfg_pull_none>;
                        };
 
                        uart0_rts: uart0-rts {
-                               rockchip,pins = <0 17 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PC1 1 &pcfg_pull_none>;
                        };
                };
 
                uart1 {
                        uart1_xfer: uart1-xfer {
-                               rockchip,pins = <1 9 RK_FUNC_1 &pcfg_pull_none>,
-                                               <1 10 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB1 1 &pcfg_pull_none>,
+                                               <1 RK_PB2 1 &pcfg_pull_none>;
                        };
 
                        uart1_cts: uart1-cts {
-                               rockchip,pins = <1 8 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB0 1 &pcfg_pull_none>;
                        };
 
                        uart1_rts: uart1-rts {
-                               rockchip,pins = <1 11 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB3 1 &pcfg_pull_none>;
                        };
                };
 
                uart2 {
                        uart2_xfer: uart2-xfer {
-                               rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up>,
-                                               <1 19 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>,
+                                               <1 RK_PC3 2 &pcfg_pull_none>;
                        };
 
                        uart21_xfer: uart21-xfer {
-                               rockchip,pins = <1 10 RK_FUNC_2 &pcfg_pull_up>,
-                                               <1 9 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB2 2 &pcfg_pull_up>,
+                                               <1 RK_PB1 2 &pcfg_pull_none>;
                        };
 
                        uart2_cts: uart2-cts {
-                               rockchip,pins = <0 25 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PD1 1 &pcfg_pull_none>;
                        };
 
                        uart2_rts: uart2-rts {
-                               rockchip,pins = <0 24 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PD0 1 &pcfg_pull_none>;
                        };
                };
        };
index 6592c80..8008076 100644 (file)
 &pinctrl {
        lcd {
                lcd_en: lcd-en  {
-                       rockchip,pins = <7 3 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        wifi {
                wifi_pwr: wifi-pwr {
-                       rockchip,pins = <7 9 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 97e4d55..8204407 100644 (file)
 
        backlight {
                bl_en: bl-en {
-                       rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        buttons {
                pwrbtn: pwrbtn {
-                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        lcd {
                lcd_cs: lcd-cs {
-                       rockchip,pins = <7 4 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pmic {
                pmic_int: pmic-int {
-                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
                 * high-speed mode on EVB board so bump up to 8ma.
                 */
                sdmmc_bus4: sdmmc-bus4 {
-                       rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
-                                       <6 17 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
-                                       <6 18 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
-                                       <6 19 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <6 RK_PC0 1 &pcfg_pull_up_drv_8ma>,
+                                       <6 RK_PC1 1 &pcfg_pull_up_drv_8ma>,
+                                       <6 RK_PC2 1 &pcfg_pull_up_drv_8ma>,
+                                       <6 RK_PC3 1 &pcfg_pull_up_drv_8ma>;
                };
 
                sdmmc_clk: sdmmc-clk {
-                       rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <6 RK_PC4 1 &pcfg_pull_none_drv_8ma>;
                };
 
                sdmmc_cmd: sdmmc-cmd {
-                       rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <6 RK_PC5 1 &pcfg_pull_up_drv_8ma>;
                };
 
                sdmmc_pwr: sdmmc-pwr {
-                       rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        usb {
                host_vbus_drv: host-vbus-drv {
-                       rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        eth_phy {
                eth_phy_pwr: eth-phy-pwr {
-                       rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 29af26e..4847cf9 100644 (file)
 
        gmac {
                phy_int: phy-int {
-                       rockchip,pins = <0 9 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                phy_pmeb: phy-pmeb {
-                       rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                phy_rst: phy-rst {
-                       rockchip,pins = <4 8 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 
        pmic {
                pmic_int: pmic-int {
-                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        usbphy {
                host_drv: host-drv {
-                       rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 0f3c29d..135e883 100644 (file)
 &pinctrl {
        act8846 {
                pmic_vsel: pmic-vsel {
-                       rockchip,pins = <7 1 RK_FUNC_GPIO &pcfg_output_low>;
+                       rockchip,pins = <7 RK_PA1 RK_FUNC_GPIO &pcfg_output_low>;
                };
        };
 
        ir {
                ir_int: ir-int {
-                       rockchip,pins = <7 5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <7 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 };
index f57f286..61435d8 100644 (file)
 
        act8846 {
                pwr_hold: pwr-hold {
-                       rockchip,pins = <0 1 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_output_high>;
                };
 
                pmic_vsel: pmic-vsel {
-                       rockchip,pins = <7 14 RK_FUNC_GPIO &pcfg_output_low>;
+                       rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_output_low>;
                };
        };
 
        gmac {
                phy_int: phy-int {
-                       rockchip,pins = <0 9 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                phy_pmeb: phy-pmeb {
-                       rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                phy_rst: phy-rst {
-                       rockchip,pins = <4 8 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 };
index 3a646c5..1574383 100644 (file)
 &pinctrl {
        ir {
                ir_int: ir-int {
-                       rockchip,pins = <7 0 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <7 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        dvp {
                dvp_pwr: dvp-pwr {
-                       rockchip,pins = <0 11 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                cif_pwr: cif-pwr {
-                       rockchip,pins = <7 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        hym8563 {
                rtc_int: rtc-int {
-                       rockchip,pins = <7 4 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <7 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        keys {
                pwr_key: pwr-key {
-                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        leds {
                power_led: power-led {
-                       rockchip,pins = <8 2 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <8 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                work_led: work-led {
-                       rockchip,pins = <8 1 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <8 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
                 * high-speed mode on firefly board so bump up to 12ma.
                 */
                sdmmc_bus4: sdmmc-bus4 {
-                       rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
-                                       <6 17 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
-                                       <6 18 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
-                                       <6 19 RK_FUNC_1 &pcfg_pull_up_drv_12ma>;
+                       rockchip,pins = <6 RK_PC0 1 &pcfg_pull_up_drv_12ma>,
+                                       <6 RK_PC1 1 &pcfg_pull_up_drv_12ma>,
+                                       <6 RK_PC2 1 &pcfg_pull_up_drv_12ma>,
+                                       <6 RK_PC3 1 &pcfg_pull_up_drv_12ma>;
                };
 
                sdmmc_clk: sdmmc-clk {
-                       rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none_12ma>;
+                       rockchip,pins = <6 RK_PC4 1 &pcfg_pull_none_12ma>;
                };
 
                sdmmc_cmd: sdmmc-cmd {
-                       rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_12ma>;
+                       rockchip,pins = <6 RK_PC5 1 &pcfg_pull_up_drv_12ma>;
                };
 
                sdmmc_pwr: sdmmc-pwr {
-                       rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        sdio {
                wifi_enable: wifi-enable {
-                       rockchip,pins = <4 28 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <4 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        usb_host {
                host_vbus_drv: host-vbus-drv {
-                       rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                usbhub_rst: usbhub-rst {
-                       rockchip,pins = <8 3 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <8 RK_PA3 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 
        usb_otg {
                otg_vbus_drv: otg-vbus-drv {
-                       rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 556ab42..313459d 100644 (file)
 &pinctrl {
        act8846 {
                pmic_vsel: pmic-vsel {
-                       rockchip,pins = <7 14 RK_FUNC_GPIO &pcfg_output_low>;
+                       rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_output_low>;
                };
        };
 
        ir {
                ir_int: ir-int {
-                       rockchip,pins = <7 0 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <7 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 };
index a6ff7ea..5e0a190 100644 (file)
 
        act8846 {
                pwr_hold: pwr-hold {
-                       rockchip,pins = <0 1 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 
        dvp {
                dvp_pwr: dvp-pwr {
-                       rockchip,pins = <0 11 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        gmac {
                phy_int: phy-int {
-                       rockchip,pins = <0 9 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                phy_pmeb: phy-pmeb {
-                       rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                phy_rst: phy-rst {
-                       rockchip,pins = <4 8 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 
        hym8563 {
                rtc_int: rtc-int {
-                       rockchip,pins = <7 4 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <7 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        keys {
                pwr_key: pwr-key {
-                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        leds {
                power_led: power-led {
-                       rockchip,pins = <8 2 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <8 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                work_led: work-led {
-                       rockchip,pins = <8 1 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <8 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
                 * high-speed mode on firefly board so bump up to 12ma.
                 */
                sdmmc_bus4: sdmmc-bus4 {
-                       rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
-                                       <6 17 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
-                                       <6 18 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
-                                       <6 19 RK_FUNC_1 &pcfg_pull_up_drv_12ma>;
+                       rockchip,pins = <6 RK_PC0 1 &pcfg_pull_up_drv_12ma>,
+                                       <6 RK_PC1 1 &pcfg_pull_up_drv_12ma>,
+                                       <6 RK_PC2 1 &pcfg_pull_up_drv_12ma>,
+                                       <6 RK_PC3 1 &pcfg_pull_up_drv_12ma>;
                };
 
                sdmmc_clk: sdmmc-clk {
-                       rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none_12ma>;
+                       rockchip,pins = <6 RK_PC4 1 &pcfg_pull_none_12ma>;
                };
 
                sdmmc_cmd: sdmmc-cmd {
-                       rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_12ma>;
+                       rockchip,pins = <6 RK_PC5 1 &pcfg_pull_up_drv_12ma>;
                };
 
                sdmmc_pwr: sdmmc-pwr {
-                       rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        usb_host {
                host_vbus_drv: host-vbus-drv {
-                       rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                usbhub_rst: usbhub-rst {
-                       rockchip,pins = <8 3 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <8 RK_PA3 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 
        usb_otg {
                otg_vbus_drv: otg-vbus-drv {
-                       rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index fb7365b..c41d012 100644 (file)
 
        act8846 {
                pmic_int: pmic-int {
-                       rockchip,pins = <0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                pmic_sleep: pmic-sleep {
-                       rockchip,pins = <0 0 RK_FUNC_GPIO &pcfg_output_low>;
+                       rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_output_low>;
                };
 
                pmic_vsel: pmic-vsel {
-                       rockchip,pins = <7 1 RK_FUNC_GPIO &pcfg_output_low>;
+                       rockchip,pins = <7 RK_PA1 RK_FUNC_GPIO &pcfg_output_low>;
                };
        };
 
        gmac {
                phy_int: phy-int {
-                       rockchip,pins = <0 9 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                phy_pmeb: phy-pmeb {
-                       rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                phy_rst: phy-rst {
-                       rockchip,pins = <4 8 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 
                 * high-speed mode on firefly board so bump up to 12ma.
                 */
                sdmmc_bus4: sdmmc-bus4 {
-                       rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
-                                       <6 17 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
-                                       <6 18 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
-                                       <6 19 RK_FUNC_1 &pcfg_pull_up_drv_12ma>;
+                       rockchip,pins = <6 RK_PC0 1 &pcfg_pull_up_drv_12ma>,
+                                       <6 RK_PC1 1 &pcfg_pull_up_drv_12ma>,
+                                       <6 RK_PC2 1 &pcfg_pull_up_drv_12ma>,
+                                       <6 RK_PC3 1 &pcfg_pull_up_drv_12ma>;
                };
 
                sdmmc_clk: sdmmc-clk {
-                       rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none_12ma>;
+                       rockchip,pins = <6 RK_PC4 1 &pcfg_pull_none_12ma>;
                };
 
                sdmmc_cmd: sdmmc-cmd {
-                       rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_12ma>;
+                       rockchip,pins = <6 RK_PC5 1 &pcfg_pull_up_drv_12ma>;
                };
 
                sdmmc_pwr: sdmmc-pwr {
-                       rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        usb_host {
                host_vbus_drv: host-vbus-drv {
-                       rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 7077c34..1e33859 100644 (file)
        buttons {
                user_button_pins: user-button-pins {
                        /* button 1 */
-                       rockchip,pins = <8 3 RK_FUNC_GPIO &pcfg_pull_up>,
+                       rockchip,pins = <8 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>,
                        /* button 2 */
-                                       <8 0 RK_FUNC_GPIO &pcfg_pull_up>;
+                                       <8 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        rv4162 {
                i2c_rtc_int: i2c-rtc-int {
-                       rockchip,pins = <5 10 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <5 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
                 * high-speed mode on pcm-947 board so bump up to 12 mA.
                 */
                sdmmc_bus4: sdmmc-bus4 {
-                       rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
-                                       <6 17 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
-                                       <6 18 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
-                                       <6 19 RK_FUNC_1 &pcfg_pull_up_drv_12ma>;
+                       rockchip,pins = <6 RK_PC0 1 &pcfg_pull_up_drv_12ma>,
+                                       <6 RK_PC1 1 &pcfg_pull_up_drv_12ma>,
+                                       <6 RK_PC2 1 &pcfg_pull_up_drv_12ma>,
+                                       <6 RK_PC3 1 &pcfg_pull_up_drv_12ma>;
                };
 
                sdmmc_clk: sdmmc-clk {
-                       rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none_12ma>;
+                       rockchip,pins = <6 RK_PC4 1 &pcfg_pull_none_12ma>;
                };
 
                sdmmc_cmd: sdmmc-cmd {
-                       rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_12ma>;
+                       rockchip,pins = <6 RK_PC5 1 &pcfg_pull_up_drv_12ma>;
                };
 
                sdmmc_pwr: sdmmc-pwr {
-                       rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        touchscreen {
                ts_irq_pin: ts-irq-pin {
-                       rockchip,pins = <5 15 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <5 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        usb_host {
                host0_vbus_drv: host0-vbus-drv {
-                       rockchip,pins = <2 13 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                host1_vbus_drv: host1-vbus-drv {
-                       rockchip,pins = <2 0 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        usb_otg {
                otg_vbus_drv: otg-vbus-drv {
-                       rockchip,pins = <2 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index c218dd5..77a47b9 100644 (file)
                 * We also have external pulls, so disable the internal ones.
                 */
                emmc_clk: emmc-clk {
-                       rockchip,pins = <3 18 RK_FUNC_2 &pcfg_pull_none_12ma>;
+                       rockchip,pins = <3 RK_PC2 2 &pcfg_pull_none_12ma>;
                };
 
                emmc_cmd: emmc-cmd {
-                       rockchip,pins = <3 16 RK_FUNC_2 &pcfg_pull_none_12ma>;
+                       rockchip,pins = <3 RK_PC0 2 &pcfg_pull_none_12ma>;
                };
 
                emmc_bus8: emmc-bus8 {
-                       rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_none_12ma>,
-                                       <3 1 RK_FUNC_2 &pcfg_pull_none_12ma>,
-                                       <3 2 RK_FUNC_2 &pcfg_pull_none_12ma>,
-                                       <3 3 RK_FUNC_2 &pcfg_pull_none_12ma>,
-                                       <3 4 RK_FUNC_2 &pcfg_pull_none_12ma>,
-                                       <3 5 RK_FUNC_2 &pcfg_pull_none_12ma>,
-                                       <3 6 RK_FUNC_2 &pcfg_pull_none_12ma>,
-                                       <3 7 RK_FUNC_2 &pcfg_pull_none_12ma>;
+                       rockchip,pins = <3 RK_PA0 2 &pcfg_pull_none_12ma>,
+                                       <3 RK_PA1 2 &pcfg_pull_none_12ma>,
+                                       <3 RK_PA2 2 &pcfg_pull_none_12ma>,
+                                       <3 RK_PA3 2 &pcfg_pull_none_12ma>,
+                                       <3 RK_PA4 2 &pcfg_pull_none_12ma>,
+                                       <3 RK_PA5 2 &pcfg_pull_none_12ma>,
+                                       <3 RK_PA6 2 &pcfg_pull_none_12ma>,
+                                       <3 RK_PA7 2 &pcfg_pull_none_12ma>;
                };
        };
 
        gmac {
                phy_int: phy-int {
-                       rockchip,pins = <4 2 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                phy_rst: phy-rst {
-                       rockchip,pins = <4 8 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 
        leds {
                user_led: user-led {
-                       rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <7 RK_PA2 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 
        pmic {
                pmic_int: pmic-int {
-                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                /* Pin for switching state between sleep and non-sleep state */
                pmic_sleep: pmic-sleep {
-                       rockchip,pins = <RK_GPIO0 0 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 };
index 28972fb..a6ffc38 100644 (file)
 
        act8846 {
                pmic_vsel: pmic-vsel {
-                       rockchip,pins = <7 1 RK_FUNC_GPIO &pcfg_output_low>;
+                       rockchip,pins = <7 RK_PA1 RK_FUNC_GPIO &pcfg_output_low>;
                };
 
                pwr_hold: pwr-hold {
-                       rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 
        buttons {
                pwrbtn: pwrbtn {
-                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        ir {
                ir_int: ir-int {
-                       rockchip,pins = <7 0 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <7 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        pmic {
                pmic_int: pmic-int {
-                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        usb {
                host_vbus_drv: host-vbus-drv {
-                       rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                otg_vbus_drv: otg-vbus-drv {
-                       rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 32e1ab3..9f9e2bf 100644 (file)
 
        emmc {
                        emmc_reset: emmc-reset {
-                               rockchip,pins = <3 9 RK_FUNC_GPIO &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
                        };
        };
 
        gmac {
                phy_rst: phy-rst {
-                       rockchip,pins = <4 8 RK_FUNC_GPIO  &pcfg_output_high>;
+                       rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO  &pcfg_output_high>;
                };
        };
 };
index 5b7e1c9..cdcdc92 100644 (file)
 &pinctrl {
        ir {
                ir_int: ir-int {
-                       rockchip,pins = <8 1 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <8 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        keys {
                pwr_key: pwr-key {
-                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        pmic {
                pmic_int: pmic-int {
-                       rockchip,pins = <0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        headphone {
                hp_det: hp-det {
-                       rockchip,pins = <7 7 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                phone_ctl: phone-ctl {
-                       rockchip,pins = <8 0 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <8 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        usb {
                host_vbus_drv: host-vbus-drv {
-                       rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        sata {
                sata_pwr_en: sata-pwr-en {
-                       rockchip,pins = <0 13 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        sdmmc {
                sdmmc_pwr: sdmmc-pwr {
-                       rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        sdio {
                wifi_enable: wifi-enable {
-                       rockchip,pins = <4 28 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <4 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index d97da89..970e138 100644 (file)
@@ -23,3 +23,8 @@
        mmc-ddr-1_8v;
        status = "okay";
 };
+
+&hdmi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&hdmi_cec_c0>;
+};
index ef653c3..2935768 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "rk3288.dtsi"
 #include <dt-bindings/input/input.h>
+#include <dt-bindings/clock/rockchip,rk808.h>
 
 / {
        chosen {
                };
        };
 
+       sdio_pwrseq: sdio-pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               clocks = <&rk808 RK808_CLKOUT1>;
+               clock-names = "ext_clock";
+               pinctrl-names = "default";
+               pinctrl-0 = <&wifi_enable>;
+               reset-gpios = <&gpio4 RK_PD3 GPIO_ACTIVE_LOW>,
+                       <&gpio4 RK_PD4 GPIO_ACTIVE_LOW>;
+       };
+
        sound {
                compatible = "simple-audio-card";
                simple-audio-card,format = "i2s";
        status = "okay";
 
        sdcard-supply = <&vccio_sd>;
+       wifi-supply = <&vcc_18>;
 };
 
 &pinctrl {
 
        backlight {
                bl_en: bl-en {
-                       rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        buttons {
                pwrbtn: pwrbtn {
-                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        eth_phy {
                eth_phy_pwr: eth-phy-pwr {
-                       rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pmic {
                pmic_int: pmic-int {
-                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO \
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO \
                                        &pcfg_pull_up>;
                };
 
                dvs_1: dvs-1 {
-                       rockchip,pins = <RK_GPIO0 11 RK_FUNC_GPIO \
+                       rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO \
                                        &pcfg_pull_down>;
                };
 
                dvs_2: dvs-2 {
-                       rockchip,pins = <RK_GPIO0 12 RK_FUNC_GPIO \
+                       rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO \
                                        &pcfg_pull_down>;
                };
        };
 
        sdmmc {
                sdmmc_bus4: sdmmc-bus4 {
-                       rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
-                                       <6 17 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
-                                       <6 18 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
-                                       <6 19 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <6 RK_PC0 1 &pcfg_pull_up_drv_8ma>,
+                                       <6 RK_PC1 1 &pcfg_pull_up_drv_8ma>,
+                                       <6 RK_PC2 1 &pcfg_pull_up_drv_8ma>,
+                                       <6 RK_PC3 1 &pcfg_pull_up_drv_8ma>;
                };
 
                sdmmc_clk: sdmmc-clk {
-                       rockchip,pins = <6 20 RK_FUNC_1 \
+                       rockchip,pins = <6 RK_PC4 1 \
                                        &pcfg_pull_none_drv_8ma>;
                };
 
                sdmmc_cmd: sdmmc-cmd {
-                       rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <6 RK_PC5 1 &pcfg_pull_up_drv_8ma>;
                };
 
                sdmmc_pwr: sdmmc-pwr {
-                       rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        usb {
                host_vbus_drv: host-vbus-drv {
-                       rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                pwr_3g: pwr-3g {
-                       rockchip,pins = <7 8 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       sdio {
+               wifi_enable: wifi-enable {
+                       rockchip,pins = <4 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>,
+                               <4 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
        vqmmc-supply = <&vccio_sd>;
 };
 
+&sdio0 {
+       bus-width = <4>;
+       cap-sd-highspeed;
+       cap-sdio-irq;
+       keep-power-in-suspend;
+       max-frequency = <50000000>;
+       mmc-pwrseq = <&sdio_pwrseq>;
+       non-removable;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdio0_bus4>, <&sdio0_cmd>, <&sdio0_clk>, <&sdio0_int>;
+       sd-uhs-sdr12;
+       sd-uhs-sdr25;
+       sd-uhs-sdr50;
+       vmmc-supply = <&vcc_io>;
+       vqmmc-supply = <&vcc_18>;
+       status = "okay";
+};
+
 &tsadc {
        rockchip,hw-tshut-mode = <1>; /* tshut mode 0:CRU 1:GPIO */
        rockchip,hw-tshut-polarity = <1>; /* tshut polarity 0:LOW 1:HIGH */
index eaf9216..445270a 100644 (file)
@@ -73,7 +73,7 @@
 &pinctrl {
        codec {
                hp_det: hp-det {
-                       rockchip,pins = <6 5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <6 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                /*
                 * we've got a ts3a227e chip but the driver requires it.
                 */
                int_codec: int-codec {
-                       rockchip,pins = <6 7 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <6 RK_PA7 RK_FUNC_GPIO &pcfg_pull_down>;
                };
 
                mic_det: mic-det {
-                       rockchip,pins = <6 11 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <6 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        headset {
                ts3a227e_int_l: ts3a227e-int-l {
-                       rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 };
index 5c94a33..406146c 100644 (file)
 &pinctrl {
        hdmi {
                vcc50_hdmi_en: vcc50-hdmi-en {
-                       rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pmic {
                dvs_1: dvs-1 {
-                       rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <7 RK_PB3 RK_FUNC_GPIO &pcfg_pull_down>;
                };
 
                dvs_2: dvs-2 {
-                       rockchip,pins = <7 15 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <7 RK_PB7 RK_FUNC_GPIO &pcfg_pull_down>;
                };
        };
 
        usb-host {
                usb2_pwr_en: usb2-pwr-en {
-                       rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index b54746d..fbef345 100644 (file)
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        regulator-state-mem {
-                               regulator-on-in-suspend;
-                               regulator-suspend-microvolt = <3300000>;
+                               regulator-off-in-suspend;
                        };
                };
        };
 &pinctrl {
        pinctrl-0 = <
                /* Common for sleep and wake, but no owners */
+               &ddr0_retention
+               &ddrio_pwroff
                &global_pwroff
 
                /* Wake only */
        >;
        pinctrl-1 = <
                /* Common for sleep and wake, but no owners */
+               &ddr0_retention
+               &ddrio_pwroff
                &global_pwroff
 
                /* Sleep only */
 
        backlight {
                bl_en: bl-en {
-                       rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        buttons {
                ap_lid_int_l: ap-lid-int-l {
-                       rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        charger {
                ac_present_ap: ac-present-ap {
-                       rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        cros-ec {
                ec_int: ec-int {
-                       rockchip,pins = <7 7 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        suspend {
                suspend_l_wake: suspend-l-wake {
-                       rockchip,pins = <0 17 RK_FUNC_GPIO &pcfg_output_low>;
+                       rockchip,pins = <0 RK_PC1 RK_FUNC_GPIO &pcfg_output_low>;
                };
 
                suspend_l_sleep: suspend-l-sleep {
-                       rockchip,pins = <0 17 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <0 RK_PC1 RK_FUNC_GPIO &pcfg_output_high>;
                };
        };
 
        trackpad {
                trackpad_int: trackpad-int {
-                       rockchip,pins = <7 3 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <7 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        usb-host {
                host1_pwr_en: host1-pwr-en {
-                       rockchip,pins = <0 11 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                usbotg_pwren_h: usbotg-pwren-h {
-                       rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 9d6814c..e248f55 100644 (file)
 &pinctrl {
        backlight {
                bl_pwr_en: bl_pwr_en {
-                       rockchip,pins = <2 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        buck-5v {
                drv_5v: drv-5v {
-                       rockchip,pins = <7 21 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        hdmi {
                vcc50_hdmi_en: vcc50-hdmi-en {
-                       rockchip,pins = <5 19 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <5 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        lcd {
                lcd_enable_h: lcd-en {
-                       rockchip,pins = <7 14 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                avdd_1v8_disp_en: avdd-1v8-disp-en {
-                       rockchip,pins = <2 13 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pmic {
                dvs_1: dvs-1 {
-                       rockchip,pins = <7 12 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>;
                };
 
                dvs_2: dvs-2 {
-                       rockchip,pins = <7 15 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <7 RK_PB7 RK_FUNC_GPIO &pcfg_pull_down>;
                };
        };
 };
index 2ba8989..b1613af 100644 (file)
 
 / {
        model = "Google Jerry";
-       compatible = "google,veyron-jerry-rev7", "google,veyron-jerry-rev6",
+       compatible = "google,veyron-jerry-rev15", "google,veyron-jerry-rev14",
+                    "google,veyron-jerry-rev13", "google,veyron-jerry-rev12",
+                    "google,veyron-jerry-rev11", "google,veyron-jerry-rev10",
+                    "google,veyron-jerry-rev7", "google,veyron-jerry-rev6",
                     "google,veyron-jerry-rev5", "google,veyron-jerry-rev4",
                     "google,veyron-jerry-rev3", "google,veyron-jerry",
                     "google,veyron", "rockchip,rk3288";
@@ -61,7 +64,9 @@
 
 &rk808 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pmic_int_l>;
+       pinctrl-0 = <&pmic_int_l &dvs_1 &dvs_2>;
+       dvs-gpios = <&gpio7 RK_PB4 GPIO_ACTIVE_HIGH>,
+                   <&gpio7 RK_PB7 GPIO_ACTIVE_HIGH>;
 
        regulators {
                mic_vcc: LDO_REG2 {
 &pinctrl {
        backlight {
                bl_pwr_en: bl_pwr_en {
-                       rockchip,pins = <2 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        buck-5v {
                drv_5v: drv-5v {
-                       rockchip,pins = <7 21 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        hdmi {
                vcc50_hdmi_en: vcc50-hdmi-en {
-                       rockchip,pins = <5 19 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <5 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        lcd {
                lcd_enable_h: lcd-en {
-                       rockchip,pins = <7 14 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                avdd_1v8_disp_en: avdd-1v8-disp-en {
-                       rockchip,pins = <2 13 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pmic {
                dvs_1: dvs-1 {
-                       rockchip,pins = <7 12 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>;
                };
 
                dvs_2: dvs-2 {
-                       rockchip,pins = <7 15 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <7 RK_PB7 RK_FUNC_GPIO &pcfg_pull_down>;
                };
        };
 };
index d889ab3..e852594 100644 (file)
 &pinctrl {
        hdmi {
                power_hdmi_on: power-hdmi-on {
-                       rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pmic {
                dvs_1: dvs-1 {
-                       rockchip,pins = <7 12 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>;
                };
 
                dvs_2: dvs-2 {
-                       rockchip,pins = <7 15 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <7 RK_PB7 RK_FUNC_GPIO &pcfg_pull_down>;
                };
        };
 };
diff --git a/arch/arm/boot/dts/rk3288-veyron-mighty.dts b/arch/arm/boot/dts/rk3288-veyron-mighty.dts
new file mode 100644 (file)
index 0000000..27fbc07
--- /dev/null
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Veyron Mighty Rev 1+ board device tree source
+ *
+ * Copyright 2015 Google, Inc
+ */
+
+/dts-v1/;
+
+#include "rk3288-veyron-jaq.dts"
+
+/ {
+       model = "Google Mighty";
+       compatible = "google,veyron-mighty-rev5", "google,veyron-mighty-rev4",
+                    "google,veyron-mighty-rev3", "google,veyron-mighty-rev2",
+                    "google,veyron-mighty-rev1", "google,veyron-mighty",
+                    "google,veyron", "rockchip,rk3288";
+};
+
+&sdmmc {
+       pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio
+                       &sdmmc_wp_gpio &sdmmc_bus4>;
+       wp-gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>;
+
+       /delete-property/ disable-wp;
+};
+
+&pinctrl {
+       sdmmc {
+               sdmmc_wp_gpio: sdmmc-wp-gpio {
+                       rockchip,pins = <7 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+};
index f95d0c5..468a181 100644 (file)
 &pinctrl {
        backlight {
                bl_pwr_en: bl_pwr_en {
-                       rockchip,pins = <2 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        buck-5v {
                drv_5v: drv-5v {
-                       rockchip,pins = <7 21 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        buttons {
                volum_down_l: volum-down-l {
-                       rockchip,pins = <5 11 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <5 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                volum_up_l: volum-up-l {
-                       rockchip,pins = <5 10 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <5 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        hdmi {
                vcc50_hdmi_en: vcc50-hdmi-en {
-                       rockchip,pins = <5 19 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <5 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        lcd {
                lcd_enable_h: lcd-en {
-                       rockchip,pins = <7 14 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                avdd_1v8_disp_en: avdd-1v8-disp-en {
-                       rockchip,pins = <2 13 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pmic {
                dvs_1: dvs-1 {
-                       rockchip,pins = <7 12 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>;
                };
 
                dvs_2: dvs-2 {
-                       rockchip,pins = <7 15 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <7 RK_PB7 RK_FUNC_GPIO &pcfg_pull_down>;
                };
        };
 
        prochot {
                gpio_prochot: gpio-prochot {
-                       rockchip,pins = <2 8 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        touchscreen {
                touch_int: touch-int {
-                       rockchip,pins = <2 14 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                touch_rst: touch-rst {
-                       rockchip,pins = <2 15 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 2950aad..9645be7 100644 (file)
 &pinctrl {
        buttons {
                pwr_key_h: pwr-key-h {
-                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        emmc {
                emmc_reset: emmc-reset {
-                       rockchip,pins = <7 12 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        sdmmc {
                sdmmc_wp_gpio: sdmmc-wp-gpio {
-                       rockchip,pins = <7 10 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <7 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 };
index a457044..fe950f9 100644 (file)
                 * We also have external pulls, so disable the internal ones.
                 */
                sdmmc_bus4: sdmmc-bus4 {
-                       rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_none_drv_8ma>,
-                                       <6 17 RK_FUNC_1 &pcfg_pull_none_drv_8ma>,
-                                       <6 18 RK_FUNC_1 &pcfg_pull_none_drv_8ma>,
-                                       <6 19 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <6 RK_PC0 1 &pcfg_pull_none_drv_8ma>,
+                                       <6 RK_PC1 1 &pcfg_pull_none_drv_8ma>,
+                                       <6 RK_PC2 1 &pcfg_pull_none_drv_8ma>,
+                                       <6 RK_PC3 1 &pcfg_pull_none_drv_8ma>;
                };
 
                sdmmc_clk: sdmmc-clk {
-                       rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <6 RK_PC4 1 &pcfg_pull_none_drv_8ma>;
                };
 
                sdmmc_cmd: sdmmc-cmd {
-                       rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <6 RK_PC5 1 &pcfg_pull_none_drv_8ma>;
                };
 
                /*
                 * think there's a card inserted
                 */
                sdmmc_cd_disabled: sdmmc-cd-disabled {
-                       rockchip,pins = <6 22 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <6 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                /* This is where we actually hook up CD */
                sdmmc_cd_gpio: sdmmc-cd-gpio {
-                       rockchip,pins = <7 5 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index e16421d..2ac8748 100644 (file)
 &pinctrl {
        backlight {
                bl_pwr_en: bl_pwr_en {
-                       rockchip,pins = <2 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        buck-5v {
                drv_5v: drv-5v {
-                       rockchip,pins = <7 21 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        hdmi {
                vcc50_hdmi_en: vcc50-hdmi-en {
-                       rockchip,pins = <5 19 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <5 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        lcd {
                lcd_enable_h: lcd-en {
-                       rockchip,pins = <7 14 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                avdd_1v8_disp_en: avdd-1v8-disp-en {
-                       rockchip,pins = <2 13 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pmic {
                dvs_1: dvs-1 {
-                       rockchip,pins = <7 12 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <7 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>;
                };
 
                dvs_2: dvs-2 {
-                       rockchip,pins = <7 15 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <7 RK_PB7 RK_FUNC_GPIO &pcfg_pull_down>;
                };
        };
 };
index 192dbc0..1252522 100644 (file)
                pinctrl-0 = <&bt_enable_l>, <&wifi_enable_h>;
 
                /*
-                * On the module itself this is one of these (depending
-                * on the actual card populated):
+                * Depending on the actual card populated GPIO4 D4 and D5
+                * correspond to one of these signals on the module:
+                *
+                * D4:
                 * - SDIO_RESET_L_WL_REG_ON
                 * - PDN (power down when low)
+                *
+                * D5:
+                * - BT_I2S_WS_BT_RFDISABLE_L
+                * - No connect
                 */
-               reset-gpios = <&gpio4 RK_PD4 GPIO_ACTIVE_LOW>;
+               reset-gpios = <&gpio4 RK_PD4 GPIO_ACTIVE_LOW>,
+                             <&gpio4 RK_PD5 GPIO_ACTIVE_LOW>;
        };
 
        vcc_5v: vcc-5v {
                regulator-boot-on;
                vin-supply = <&vcc_5v>;
        };
+
+       vdd_logic: vdd-logic {
+               compatible = "pwm-regulator";
+               regulator-name = "vdd_logic";
+
+               pwms = <&pwm1 0 1994 0>;
+               pwm-supply = <&vcc33_sys>;
+
+               pwm-dutycycle-range = <0x7b 0>;
+               pwm-dutycycle-unit = <0x94>;
+
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <950000>;
+               regulator-max-microvolt = <1350000>;
+               regulator-ramp-delay = <4000>;
+       };
 };
 
 &cpu0 {
                                regulator-max-microvolt = <1250000>;
                                regulator-ramp-delay = <6001>;
                                regulator-state-mem {
-                                       regulator-on-in-suspend;
-                                       regulator-suspend-microvolt = <1000000>;
+                                       regulator-off-in-suspend;
                                };
                        };
 
 &uart0 {
        status = "okay";
 
-       /* We need to go faster than 24MHz, so adjust clock parents / rates */
-       assigned-clocks = <&cru SCLK_UART0>;
-       assigned-clock-rates = <48000000>;
-
        /* Pins don't include flow control by default; add that in */
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
        pinctrl-names = "default", "sleep";
        pinctrl-0 = <
                /* Common for sleep and wake, but no owners */
+               &ddr0_retention
+               &ddrio_pwroff
                &global_pwroff
        >;
        pinctrl-1 = <
                /* Common for sleep and wake, but no owners */
+               &ddr0_retention
+               &ddrio_pwroff
                &global_pwroff
        >;
 
 
        buttons {
                pwr_key_l: pwr-key-l {
-                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        emmc {
                emmc_reset: emmc-reset {
-                       rockchip,pins = <2 9 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                /*
                 * We also have external pulls, so disable the internal ones.
                 */
                emmc_clk: emmc-clk {
-                       rockchip,pins = <3 18 RK_FUNC_2 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <3 RK_PC2 2 &pcfg_pull_none_drv_8ma>;
                };
 
                emmc_cmd: emmc-cmd {
-                       rockchip,pins = <3 16 RK_FUNC_2 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <3 RK_PC0 2 &pcfg_pull_none_drv_8ma>;
                };
 
                emmc_bus8: emmc-bus8 {
-                       rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
-                                       <3 1 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
-                                       <3 2 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
-                                       <3 3 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
-                                       <3 4 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
-                                       <3 5 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
-                                       <3 6 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
-                                       <3 7 RK_FUNC_2 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <3 RK_PA0 2 &pcfg_pull_none_drv_8ma>,
+                                       <3 RK_PA1 2 &pcfg_pull_none_drv_8ma>,
+                                       <3 RK_PA2 2 &pcfg_pull_none_drv_8ma>,
+                                       <3 RK_PA3 2 &pcfg_pull_none_drv_8ma>,
+                                       <3 RK_PA4 2 &pcfg_pull_none_drv_8ma>,
+                                       <3 RK_PA5 2 &pcfg_pull_none_drv_8ma>,
+                                       <3 RK_PA6 2 &pcfg_pull_none_drv_8ma>,
+                                       <3 RK_PA7 2 &pcfg_pull_none_drv_8ma>;
                };
        };
 
        pmic {
                pmic_int_l: pmic-int-l {
-                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        reboot {
                ap_warm_reset_h: ap-warm-reset-h {
-                       rockchip,pins = <RK_GPIO0 13 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        recovery-switch {
                rec_mode_l: rec-mode-l {
-                       rockchip,pins = <0 9 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        sdio0 {
                wifi_enable_h: wifienable-h {
-                       rockchip,pins = <4 28 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <4 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                /* NOTE: mislabelled on schematic; should be bt_enable_h */
                bt_enable_l: bt-enable-l {
-                       rockchip,pins = <4 29 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <4 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                /*
                 * We also have external pulls, so disable the internal ones.
                 */
                sdio0_bus4: sdio0-bus4 {
-                       rockchip,pins = <4 20 RK_FUNC_1 &pcfg_pull_none_drv_8ma>,
-                                       <4 21 RK_FUNC_1 &pcfg_pull_none_drv_8ma>,
-                                       <4 22 RK_FUNC_1 &pcfg_pull_none_drv_8ma>,
-                                       <4 23 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <4 RK_PC4 1 &pcfg_pull_none_drv_8ma>,
+                                       <4 RK_PC5 1 &pcfg_pull_none_drv_8ma>,
+                                       <4 RK_PC6 1 &pcfg_pull_none_drv_8ma>,
+                                       <4 RK_PC7 1 &pcfg_pull_none_drv_8ma>;
                };
 
                sdio0_cmd: sdio0-cmd {
-                       rockchip,pins = <4 24 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <4 RK_PD0 1 &pcfg_pull_none_drv_8ma>;
                };
 
                sdio0_clk: sdio0-clk {
-                       rockchip,pins = <4 25 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <4 RK_PD1 1 &pcfg_pull_none_drv_8ma>;
                };
        };
 
        tpm {
                tpm_int_h: tpm-int-h {
-                       rockchip,pins = <7 4 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        write-protect {
                fw_wp_ap: fw-wp-ap {
-                       rockchip,pins = <7 6 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <7 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 40b232e..ba06e9f 100644 (file)
 
        pmic {
                pmic_int: pmic-int {
-                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        usb_host {
                phy_pwr_en: phy-pwr-en {
-                       rockchip,pins = <RK_GPIO2 RK_PB1 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <2 RK_PB1 RK_FUNC_GPIO &pcfg_output_high>;
                };
 
                usb2_pwr_en: usb2-pwr-en {
 
        usb_otg {
                otg_vbus_drv: otg-vbus-drv {
-                       rockchip,pins = <RK_GPIO0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
 
                };
        };
index 8ce3dd2..aa017ab 100644 (file)
@@ -64,6 +64,7 @@
                        #cooling-cells = <2>; /* min followed by max */
                        clock-latency = <40000>;
                        clocks = <&cru ARMCLK>;
+                       dynamic-power-coefficient = <370>;
                };
                cpu1: cpu@501 {
                        device_type = "cpu";
@@ -74,6 +75,7 @@
                        #cooling-cells = <2>; /* min followed by max */
                        clock-latency = <40000>;
                        clocks = <&cru ARMCLK>;
+                       dynamic-power-coefficient = <370>;
                };
                cpu2: cpu@502 {
                        device_type = "cpu";
@@ -84,6 +86,7 @@
                        #cooling-cells = <2>; /* min followed by max */
                        clock-latency = <40000>;
                        clocks = <&cru ARMCLK>;
+                       dynamic-power-coefficient = <370>;
                };
                cpu3: cpu@503 {
                        device_type = "cpu";
@@ -94,6 +97,7 @@
                        #cooling-cells = <2>; /* min followed by max */
                        clock-latency = <40000>;
                        clocks = <&cru ARMCLK>;
+                       dynamic-power-coefficient = <370>;
                };
        };
 
                pinctrl-1 = <&otp_out>;
                pinctrl-2 = <&otp_gpio>;
                #thermal-sensor-cells = <1>;
+               rockchip,grf = <&grf>;
                rockchip,hw-tshut-temp = <95000>;
                status = "disabled";
        };
                reg = <0x0 0xffaf0080 0x0 0x20>;
        };
 
-       gic: interrupt-controller@ffc01000 {
-               compatible = "arm,gic-400";
-               interrupt-controller;
-               #interrupt-cells = <3>;
-               #address-cells = <0>;
-
-               reg = <0x0 0xffc01000 0x0 0x1000>,
-                     <0x0 0xffc02000 0x0 0x2000>,
-                     <0x0 0xffc04000 0x0 0x2000>,
-                     <0x0 0xffc06000 0x0 0x2000>;
-               interrupts = <GIC_PPI 9 0xf04>;
-       };
-
        efuse: efuse@ffb40000 {
                compatible = "rockchip,rk3288-efuse";
                reg = <0x0 0xffb40000 0x0 0x20>;
                };
        };
 
+       gic: interrupt-controller@ffc01000 {
+               compatible = "arm,gic-400";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+
+               reg = <0x0 0xffc01000 0x0 0x1000>,
+                     <0x0 0xffc02000 0x0 0x2000>,
+                     <0x0 0xffc04000 0x0 0x2000>,
+                     <0x0 0xffc06000 0x0 0x2000>;
+               interrupts = <GIC_PPI 9 0xf04>;
+       };
+
        pinctrl: pinctrl {
                compatible = "rockchip,rk3288-pinctrl";
                rockchip,grf = <&grf>;
 
                hdmi {
                        hdmi_cec_c0: hdmi-cec-c0 {
-                               rockchip,pins = <7 RK_PC0 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <7 RK_PC0 2 &pcfg_pull_none>;
                        };
 
                        hdmi_cec_c7: hdmi-cec-c7 {
-                               rockchip,pins = <7 RK_PC7 RK_FUNC_4 &pcfg_pull_none>;
+                               rockchip,pins = <7 RK_PC7 4 &pcfg_pull_none>;
                        };
 
                        hdmi_ddc: hdmi-ddc {
-                               rockchip,pins = <7 19 RK_FUNC_2 &pcfg_pull_none>,
-                                               <7 20 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <7 RK_PC3 2 &pcfg_pull_none>,
+                                               <7 RK_PC4 2 &pcfg_pull_none>;
                        };
                };
 
 
                sleep {
                        global_pwroff: global-pwroff {
-                               rockchip,pins = <0 0 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA0 1 &pcfg_pull_none>;
                        };
 
                        ddrio_pwroff: ddrio-pwroff {
-                               rockchip,pins = <0 1 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA1 1 &pcfg_pull_none>;
                        };
 
                        ddr0_retention: ddr0-retention {
-                               rockchip,pins = <0 2 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PA2 1 &pcfg_pull_up>;
                        };
 
                        ddr1_retention: ddr1-retention {
-                               rockchip,pins = <0 3 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PA3 1 &pcfg_pull_up>;
                        };
                };
 
                edp {
                        edp_hpd: edp-hpd {
-                               rockchip,pins = <7 11 RK_FUNC_2 &pcfg_pull_down>;
+                               rockchip,pins = <7 RK_PB3 2 &pcfg_pull_down>;
                        };
                };
 
                i2c0 {
                        i2c0_xfer: i2c0-xfer {
-                               rockchip,pins = <0 15 RK_FUNC_1 &pcfg_pull_none>,
-                                               <0 16 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PB7 1 &pcfg_pull_none>,
+                                               <0 RK_PC0 1 &pcfg_pull_none>;
                        };
                };
 
                i2c1 {
                        i2c1_xfer: i2c1-xfer {
-                               rockchip,pins = <8 4 RK_FUNC_1 &pcfg_pull_none>,
-                                               <8 5 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <8 RK_PA4 1 &pcfg_pull_none>,
+                                               <8 RK_PA5 1 &pcfg_pull_none>;
                        };
                };
 
                i2c2 {
                        i2c2_xfer: i2c2-xfer {
-                               rockchip,pins = <6 9 RK_FUNC_1 &pcfg_pull_none>,
-                                               <6 10 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <6 RK_PB1 1 &pcfg_pull_none>,
+                                               <6 RK_PB2 1 &pcfg_pull_none>;
                        };
                };
 
                i2c3 {
                        i2c3_xfer: i2c3-xfer {
-                               rockchip,pins = <2 16 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 17 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PC0 1 &pcfg_pull_none>,
+                                               <2 RK_PC1 1 &pcfg_pull_none>;
                        };
                };
 
                i2c4 {
                        i2c4_xfer: i2c4-xfer {
-                               rockchip,pins = <7 17 RK_FUNC_1 &pcfg_pull_none>,
-                                               <7 18 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <7 RK_PC1 1 &pcfg_pull_none>,
+                                               <7 RK_PC2 1 &pcfg_pull_none>;
                        };
                };
 
                i2c5 {
                        i2c5_xfer: i2c5-xfer {
-                               rockchip,pins = <7 19 RK_FUNC_1 &pcfg_pull_none>,
-                                               <7 20 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <7 RK_PC3 1 &pcfg_pull_none>,
+                                               <7 RK_PC4 1 &pcfg_pull_none>;
                        };
                };
 
                i2s0 {
                        i2s0_bus: i2s0-bus {
-                               rockchip,pins = <6 0 RK_FUNC_1 &pcfg_pull_none>,
-                                               <6 1 RK_FUNC_1 &pcfg_pull_none>,
-                                               <6 2 RK_FUNC_1 &pcfg_pull_none>,
-                                               <6 3 RK_FUNC_1 &pcfg_pull_none>,
-                                               <6 4 RK_FUNC_1 &pcfg_pull_none>,
-                                               <6 8 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <6 RK_PA0 1 &pcfg_pull_none>,
+                                               <6 RK_PA1 1 &pcfg_pull_none>,
+                                               <6 RK_PA2 1 &pcfg_pull_none>,
+                                               <6 RK_PA3 1 &pcfg_pull_none>,
+                                               <6 RK_PA4 1 &pcfg_pull_none>,
+                                               <6 RK_PB0 1 &pcfg_pull_none>;
                        };
                };
 
                lcdc {
                        lcdc_ctl: lcdc-ctl {
-                               rockchip,pins = <1 24 RK_FUNC_1 &pcfg_pull_none>,
-                                               <1 25 RK_FUNC_1 &pcfg_pull_none>,
-                                               <1 26 RK_FUNC_1 &pcfg_pull_none>,
-                                               <1 27 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PD0 1 &pcfg_pull_none>,
+                                               <1 RK_PD1 1 &pcfg_pull_none>,
+                                               <1 RK_PD2 1 &pcfg_pull_none>,
+                                               <1 RK_PD3 1 &pcfg_pull_none>;
                        };
                };
 
                sdmmc {
                        sdmmc_clk: sdmmc-clk {
-                               rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <6 RK_PC4 1 &pcfg_pull_none>;
                        };
 
                        sdmmc_cmd: sdmmc-cmd {
-                               rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <6 RK_PC5 1 &pcfg_pull_up>;
                        };
 
                        sdmmc_cd: sdmmc-cd {
-                               rockchip,pins = <6 22 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <6 RK_PC6 1 &pcfg_pull_up>;
                        };
 
                        sdmmc_bus1: sdmmc-bus1 {
-                               rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <6 RK_PC0 1 &pcfg_pull_up>;
                        };
 
                        sdmmc_bus4: sdmmc-bus4 {
-                               rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up>,
-                                               <6 17 RK_FUNC_1 &pcfg_pull_up>,
-                                               <6 18 RK_FUNC_1 &pcfg_pull_up>,
-                                               <6 19 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <6 RK_PC0 1 &pcfg_pull_up>,
+                                               <6 RK_PC1 1 &pcfg_pull_up>,
+                                               <6 RK_PC2 1 &pcfg_pull_up>,
+                                               <6 RK_PC3 1 &pcfg_pull_up>;
                        };
                };
 
                sdio0 {
                        sdio0_bus1: sdio0-bus1 {
-                               rockchip,pins = <4 20 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <4 RK_PC4 1 &pcfg_pull_up>;
                        };
 
                        sdio0_bus4: sdio0-bus4 {
-                               rockchip,pins = <4 20 RK_FUNC_1 &pcfg_pull_up>,
-                                               <4 21 RK_FUNC_1 &pcfg_pull_up>,
-                                               <4 22 RK_FUNC_1 &pcfg_pull_up>,
-                                               <4 23 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <4 RK_PC4 1 &pcfg_pull_up>,
+                                               <4 RK_PC5 1 &pcfg_pull_up>,
+                                               <4 RK_PC6 1 &pcfg_pull_up>,
+                                               <4 RK_PC7 1 &pcfg_pull_up>;
                        };
 
                        sdio0_cmd: sdio0-cmd {
-                               rockchip,pins = <4 24 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <4 RK_PD0 1 &pcfg_pull_up>;
                        };
 
                        sdio0_clk: sdio0-clk {
-                               rockchip,pins = <4 25 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <4 RK_PD1 1 &pcfg_pull_none>;
                        };
 
                        sdio0_cd: sdio0-cd {
-                               rockchip,pins = <4 26 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <4 RK_PD2 1 &pcfg_pull_up>;
                        };
 
                        sdio0_wp: sdio0-wp {
-                               rockchip,pins = <4 27 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <4 RK_PD3 1 &pcfg_pull_up>;
                        };
 
                        sdio0_pwr: sdio0-pwr {
-                               rockchip,pins = <4 28 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <4 RK_PD4 1 &pcfg_pull_up>;
                        };
 
                        sdio0_bkpwr: sdio0-bkpwr {
-                               rockchip,pins = <4 29 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <4 RK_PD5 1 &pcfg_pull_up>;
                        };
 
                        sdio0_int: sdio0-int {
-                               rockchip,pins = <4 30 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <4 RK_PD6 1 &pcfg_pull_up>;
                        };
                };
 
                sdio1 {
                        sdio1_bus1: sdio1-bus1 {
-                               rockchip,pins = <3 24 4 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PD0 4 &pcfg_pull_up>;
                        };
 
                        sdio1_bus4: sdio1-bus4 {
-                               rockchip,pins = <3 24 4 &pcfg_pull_up>,
-                                               <3 25 4 &pcfg_pull_up>,
-                                               <3 26 4 &pcfg_pull_up>,
-                                               <3 27 4 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PD0 4 &pcfg_pull_up>,
+                                               <3 RK_PD1 4 &pcfg_pull_up>,
+                                               <3 RK_PD2 4 &pcfg_pull_up>,
+                                               <3 RK_PD3 4 &pcfg_pull_up>;
                        };
 
                        sdio1_cd: sdio1-cd {
-                               rockchip,pins = <3 28 4 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PD4 4 &pcfg_pull_up>;
                        };
 
                        sdio1_wp: sdio1-wp {
-                               rockchip,pins = <3 29 4 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PD5 4 &pcfg_pull_up>;
                        };
 
                        sdio1_bkpwr: sdio1-bkpwr {
-                               rockchip,pins = <3 30 4 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PD6 4 &pcfg_pull_up>;
                        };
 
                        sdio1_int: sdio1-int {
-                               rockchip,pins = <3 31 4 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PD7 4 &pcfg_pull_up>;
                        };
 
                        sdio1_cmd: sdio1-cmd {
-                               rockchip,pins = <4 6 4 &pcfg_pull_up>;
+                               rockchip,pins = <4 RK_PA6 4 &pcfg_pull_up>;
                        };
 
                        sdio1_clk: sdio1-clk {
-                               rockchip,pins = <4 7 4 &pcfg_pull_none>;
+                               rockchip,pins = <4 RK_PA7 4 &pcfg_pull_none>;
                        };
 
                        sdio1_pwr: sdio1-pwr {
-                               rockchip,pins = <4 9 4 &pcfg_pull_up>;
+                               rockchip,pins = <4 RK_PB1 4 &pcfg_pull_up>;
                        };
                };
 
                emmc {
                        emmc_clk: emmc-clk {
-                               rockchip,pins = <3 18 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PC2 2 &pcfg_pull_none>;
                        };
 
                        emmc_cmd: emmc-cmd {
-                               rockchip,pins = <3 16 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PC0 2 &pcfg_pull_up>;
                        };
 
                        emmc_pwr: emmc-pwr {
-                               rockchip,pins = <3 9 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PB1 2 &pcfg_pull_up>;
                        };
 
                        emmc_bus1: emmc-bus1 {
-                               rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PA0 2 &pcfg_pull_up>;
                        };
 
                        emmc_bus4: emmc-bus4 {
-                               rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_up>,
-                                               <3 1 RK_FUNC_2 &pcfg_pull_up>,
-                                               <3 2 RK_FUNC_2 &pcfg_pull_up>,
-                                               <3 3 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PA0 2 &pcfg_pull_up>,
+                                               <3 RK_PA1 2 &pcfg_pull_up>,
+                                               <3 RK_PA2 2 &pcfg_pull_up>,
+                                               <3 RK_PA3 2 &pcfg_pull_up>;
                        };
 
                        emmc_bus8: emmc-bus8 {
-                               rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_up>,
-                                               <3 1 RK_FUNC_2 &pcfg_pull_up>,
-                                               <3 2 RK_FUNC_2 &pcfg_pull_up>,
-                                               <3 3 RK_FUNC_2 &pcfg_pull_up>,
-                                               <3 4 RK_FUNC_2 &pcfg_pull_up>,
-                                               <3 5 RK_FUNC_2 &pcfg_pull_up>,
-                                               <3 6 RK_FUNC_2 &pcfg_pull_up>,
-                                               <3 7 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PA0 2 &pcfg_pull_up>,
+                                               <3 RK_PA1 2 &pcfg_pull_up>,
+                                               <3 RK_PA2 2 &pcfg_pull_up>,
+                                               <3 RK_PA3 2 &pcfg_pull_up>,
+                                               <3 RK_PA4 2 &pcfg_pull_up>,
+                                               <3 RK_PA5 2 &pcfg_pull_up>,
+                                               <3 RK_PA6 2 &pcfg_pull_up>,
+                                               <3 RK_PA7 2 &pcfg_pull_up>;
                        };
                };
 
                spi0 {
                        spi0_clk: spi0-clk {
-                               rockchip,pins = <5 12 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <5 RK_PB4 1 &pcfg_pull_up>;
                        };
                        spi0_cs0: spi0-cs0 {
-                               rockchip,pins = <5 13 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <5 RK_PB5 1 &pcfg_pull_up>;
                        };
                        spi0_tx: spi0-tx {
-                               rockchip,pins = <5 14 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <5 RK_PB6 1 &pcfg_pull_up>;
                        };
                        spi0_rx: spi0-rx {
-                               rockchip,pins = <5 15 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <5 RK_PB7 1 &pcfg_pull_up>;
                        };
                        spi0_cs1: spi0-cs1 {
-                               rockchip,pins = <5 16 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <5 RK_PC0 1 &pcfg_pull_up>;
                        };
                };
                spi1 {
                        spi1_clk: spi1-clk {
-                               rockchip,pins = <7 12 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <7 RK_PB4 2 &pcfg_pull_up>;
                        };
                        spi1_cs0: spi1-cs0 {
-                               rockchip,pins = <7 13 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <7 RK_PB5 2 &pcfg_pull_up>;
                        };
                        spi1_rx: spi1-rx {
-                               rockchip,pins = <7 14 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <7 RK_PB6 2 &pcfg_pull_up>;
                        };
                        spi1_tx: spi1-tx {
-                               rockchip,pins = <7 15 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <7 RK_PB7 2 &pcfg_pull_up>;
                        };
                };
 
                spi2 {
                        spi2_cs1: spi2-cs1 {
-                               rockchip,pins = <8 3 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <8 RK_PA3 1 &pcfg_pull_up>;
                        };
                        spi2_clk: spi2-clk {
-                               rockchip,pins = <8 6 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <8 RK_PA6 1 &pcfg_pull_up>;
                        };
                        spi2_cs0: spi2-cs0 {
-                               rockchip,pins = <8 7 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <8 RK_PA7 1 &pcfg_pull_up>;
                        };
                        spi2_rx: spi2-rx {
-                               rockchip,pins = <8 8 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <8 RK_PB0 1 &pcfg_pull_up>;
                        };
                        spi2_tx: spi2-tx {
-                               rockchip,pins = <8 9 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <8 RK_PB1 1 &pcfg_pull_up>;
                        };
                };
 
                uart0 {
                        uart0_xfer: uart0-xfer {
-                               rockchip,pins = <4 16 RK_FUNC_1 &pcfg_pull_up>,
-                                               <4 17 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <4 RK_PC0 1 &pcfg_pull_up>,
+                                               <4 RK_PC1 1 &pcfg_pull_none>;
                        };
 
                        uart0_cts: uart0-cts {
-                               rockchip,pins = <4 18 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <4 RK_PC2 1 &pcfg_pull_up>;
                        };
 
                        uart0_rts: uart0-rts {
-                               rockchip,pins = <4 19 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <4 RK_PC3 1 &pcfg_pull_none>;
                        };
                };
 
                uart1 {
                        uart1_xfer: uart1-xfer {
-                               rockchip,pins = <5 8 RK_FUNC_1 &pcfg_pull_up>,
-                                               <5 9 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <5 RK_PB0 1 &pcfg_pull_up>,
+                                               <5 RK_PB1 1 &pcfg_pull_none>;
                        };
 
                        uart1_cts: uart1-cts {
-                               rockchip,pins = <5 10 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <5 RK_PB2 1 &pcfg_pull_up>;
                        };
 
                        uart1_rts: uart1-rts {
-                               rockchip,pins = <5 11 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <5 RK_PB3 1 &pcfg_pull_none>;
                        };
                };
 
                uart2 {
                        uart2_xfer: uart2-xfer {
-                               rockchip,pins = <7 22 RK_FUNC_1 &pcfg_pull_up>,
-                                               <7 23 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <7 RK_PC6 1 &pcfg_pull_up>,
+                                               <7 RK_PC7 1 &pcfg_pull_none>;
                        };
                        /* no rts / cts for uart2 */
                };
 
                uart3 {
                        uart3_xfer: uart3-xfer {
-                               rockchip,pins = <7 7 RK_FUNC_1 &pcfg_pull_up>,
-                                               <7 8 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <7 RK_PA7 1 &pcfg_pull_up>,
+                                               <7 RK_PB0 1 &pcfg_pull_none>;
                        };
 
                        uart3_cts: uart3-cts {
-                               rockchip,pins = <7 9 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <7 RK_PB1 1 &pcfg_pull_up>;
                        };
 
                        uart3_rts: uart3-rts {
-                               rockchip,pins = <7 10 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <7 RK_PB2 1 &pcfg_pull_none>;
                        };
                };
 
                uart4 {
                        uart4_xfer: uart4-xfer {
-                               rockchip,pins = <5 15 3 &pcfg_pull_up>,
-                                               <5 14 3 &pcfg_pull_none>;
+                               rockchip,pins = <5 RK_PB7 3 &pcfg_pull_up>,
+                                               <5 RK_PB6 3 &pcfg_pull_none>;
                        };
 
                        uart4_cts: uart4-cts {
-                               rockchip,pins = <5 12 3 &pcfg_pull_up>;
+                               rockchip,pins = <5 RK_PB4 3 &pcfg_pull_up>;
                        };
 
                        uart4_rts: uart4-rts {
-                               rockchip,pins = <5 13 3 &pcfg_pull_none>;
+                               rockchip,pins = <5 RK_PB5 3 &pcfg_pull_none>;
                        };
                };
 
                tsadc {
                        otp_gpio: otp-gpio {
-                               rockchip,pins = <0 10 RK_FUNC_GPIO &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
                        };
 
                        otp_out: otp-out {
-                               rockchip,pins = <0 10 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PB2 1 &pcfg_pull_none>;
                        };
                };
 
                pwm0 {
                        pwm0_pin: pwm0-pin {
-                               rockchip,pins = <7 0 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <7 RK_PA0 1 &pcfg_pull_none>;
                        };
                };
 
                pwm1 {
                        pwm1_pin: pwm1-pin {
-                               rockchip,pins = <7 1 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <7 RK_PA1 1 &pcfg_pull_none>;
                        };
                };
 
                pwm2 {
                        pwm2_pin: pwm2-pin {
-                               rockchip,pins = <7 22 3 &pcfg_pull_none>;
+                               rockchip,pins = <7 RK_PC6 3 &pcfg_pull_none>;
                        };
                };
 
                pwm3 {
                        pwm3_pin: pwm3-pin {
-                               rockchip,pins = <7 23 3 &pcfg_pull_none>;
+                               rockchip,pins = <7 RK_PC7 3 &pcfg_pull_none>;
                        };
                };
 
                gmac {
                        rgmii_pins: rgmii-pins {
-                               rockchip,pins = <3 30 3 &pcfg_pull_none>,
-                                               <3 31 3 &pcfg_pull_none>,
-                                               <3 26 3 &pcfg_pull_none>,
-                                               <3 27 3 &pcfg_pull_none>,
-                                               <3 28 3 &pcfg_pull_none_12ma>,
-                                               <3 29 3 &pcfg_pull_none_12ma>,
-                                               <3 24 3 &pcfg_pull_none_12ma>,
-                                               <3 25 3 &pcfg_pull_none_12ma>,
-                                               <4 0 3 &pcfg_pull_none>,
-                                               <4 5 3 &pcfg_pull_none>,
-                                               <4 6 3 &pcfg_pull_none>,
-                                               <4 9 3 &pcfg_pull_none_12ma>,
-                                               <4 4 3 &pcfg_pull_none_12ma>,
-                                               <4 1 3 &pcfg_pull_none>,
-                                               <4 3 3 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PD6 3 &pcfg_pull_none>,
+                                               <3 RK_PD7 3 &pcfg_pull_none>,
+                                               <3 RK_PD2 3 &pcfg_pull_none>,
+                                               <3 RK_PD3 3 &pcfg_pull_none>,
+                                               <3 RK_PD4 3 &pcfg_pull_none_12ma>,
+                                               <3 RK_PD5 3 &pcfg_pull_none_12ma>,
+                                               <3 RK_PD0 3 &pcfg_pull_none_12ma>,
+                                               <3 RK_PD1 3 &pcfg_pull_none_12ma>,
+                                               <4 RK_PA0 3 &pcfg_pull_none>,
+                                               <4 RK_PA5 3 &pcfg_pull_none>,
+                                               <4 RK_PA6 3 &pcfg_pull_none>,
+                                               <4 RK_PB1 3 &pcfg_pull_none_12ma>,
+                                               <4 RK_PA4 3 &pcfg_pull_none_12ma>,
+                                               <4 RK_PA1 3 &pcfg_pull_none>,
+                                               <4 RK_PA3 3 &pcfg_pull_none>;
                        };
 
                        rmii_pins: rmii-pins {
-                               rockchip,pins = <3 30 3 &pcfg_pull_none>,
-                                               <3 31 3 &pcfg_pull_none>,
-                                               <3 28 3 &pcfg_pull_none>,
-                                               <3 29 3 &pcfg_pull_none>,
-                                               <4 0 3 &pcfg_pull_none>,
-                                               <4 5 3 &pcfg_pull_none>,
-                                               <4 4 3 &pcfg_pull_none>,
-                                               <4 1 3 &pcfg_pull_none>,
-                                               <4 2 3 &pcfg_pull_none>,
-                                               <4 3 3 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PD6 3 &pcfg_pull_none>,
+                                               <3 RK_PD7 3 &pcfg_pull_none>,
+                                               <3 RK_PD4 3 &pcfg_pull_none>,
+                                               <3 RK_PD5 3 &pcfg_pull_none>,
+                                               <4 RK_PA0 3 &pcfg_pull_none>,
+                                               <4 RK_PA5 3 &pcfg_pull_none>,
+                                               <4 RK_PA4 3 &pcfg_pull_none>,
+                                               <4 RK_PA1 3 &pcfg_pull_none>,
+                                               <4 RK_PA2 3 &pcfg_pull_none>,
+                                               <4 RK_PA3 3 &pcfg_pull_none>;
                        };
                };
 
                spdif {
                        spdif_tx: spdif-tx {
-                               rockchip,pins = <RK_GPIO6 11 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <6 RK_PB3 1 &pcfg_pull_none>;
                        };
                };
        };
index 1c4507b..b1db924 100644 (file)
@@ -37,7 +37,6 @@
 &emmc {
        bus-width = <8>;
        cap-mmc-highspeed;
-       disable-wp;
        no-sd;
        no-sdio;
        non-removable;
index f47ac86..5876690 100644 (file)
 
                emmc {
                        emmc_bus8: emmc-bus8 {
-                               rockchip,pins = <2 RK_PA0 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                               <2 RK_PA1 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                               <2 RK_PA2 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                               <2 RK_PA3 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                               <2 RK_PA4 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                               <2 RK_PA5 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                               <2 RK_PA6 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                               <2 RK_PA7 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+                               rockchip,pins = <2 RK_PA0 2 &pcfg_pull_up_drv_8ma>,
+                                               <2 RK_PA1 2 &pcfg_pull_up_drv_8ma>,
+                                               <2 RK_PA2 2 &pcfg_pull_up_drv_8ma>,
+                                               <2 RK_PA3 2 &pcfg_pull_up_drv_8ma>,
+                                               <2 RK_PA4 2 &pcfg_pull_up_drv_8ma>,
+                                               <2 RK_PA5 2 &pcfg_pull_up_drv_8ma>,
+                                               <2 RK_PA6 2 &pcfg_pull_up_drv_8ma>,
+                                               <2 RK_PA7 2 &pcfg_pull_up_drv_8ma>;
                        };
 
                        emmc_clk: emmc-clk {
-                               rockchip,pins = <2 RK_PB6 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+                               rockchip,pins = <2 RK_PB6 1 &pcfg_pull_none_drv_8ma>;
                        };
 
                        emmc_cmd: emmc-cmd {
-                               rockchip,pins = <2 RK_PB4 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+                               rockchip,pins = <2 RK_PB4 2 &pcfg_pull_up_drv_8ma>;
                        };
                };
 
                gmac {
                        rmii_pins: rmii-pins {
-                               rockchip,pins = <1 RK_PC5 RK_FUNC_2 &pcfg_pull_none>,
-                                               <1 RK_PC3 RK_FUNC_2 &pcfg_pull_none>,
-                                               <1 RK_PC4 RK_FUNC_2 &pcfg_pull_none>,
-                                               <1 RK_PB2 RK_FUNC_3 &pcfg_pull_none_drv_12ma>,
-                                               <1 RK_PB3 RK_FUNC_3 &pcfg_pull_none_drv_12ma>,
-                                               <1 RK_PB4 RK_FUNC_3 &pcfg_pull_none_drv_12ma>,
-                                               <1 RK_PB5 RK_FUNC_3 &pcfg_pull_none>,
-                                               <1 RK_PB6 RK_FUNC_3 &pcfg_pull_none>,
-                                               <1 RK_PB7 RK_FUNC_3 &pcfg_pull_none>,
-                                               <1 RK_PC2 RK_FUNC_3 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PC5 2 &pcfg_pull_none>,
+                                               <1 RK_PC3 2 &pcfg_pull_none>,
+                                               <1 RK_PC4 2 &pcfg_pull_none>,
+                                               <1 RK_PB2 3 &pcfg_pull_none_drv_12ma>,
+                                               <1 RK_PB3 3 &pcfg_pull_none_drv_12ma>,
+                                               <1 RK_PB4 3 &pcfg_pull_none_drv_12ma>,
+                                               <1 RK_PB5 3 &pcfg_pull_none>,
+                                               <1 RK_PB6 3 &pcfg_pull_none>,
+                                               <1 RK_PB7 3 &pcfg_pull_none>,
+                                               <1 RK_PC2 3 &pcfg_pull_none>;
                        };
                };
 
                i2c0 {
                        i2c0_xfer: i2c0-xfer {
-                               rockchip,pins = <0 RK_PB1 RK_FUNC_1 &pcfg_pull_none_smt>,
-                                               <0 RK_PB2 RK_FUNC_1 &pcfg_pull_none_smt>;
+                               rockchip,pins = <0 RK_PB1 1 &pcfg_pull_none_smt>,
+                                               <0 RK_PB2 1 &pcfg_pull_none_smt>;
                        };
                };
 
                i2c1 {
                        i2c1_xfer: i2c1-xfer {
-                               rockchip,pins = <2 RK_PD3 RK_FUNC_1 &pcfg_pull_up>,
-                                               <2 RK_PD4 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <2 RK_PD3 1 &pcfg_pull_up>,
+                                               <2 RK_PD4 1 &pcfg_pull_up>;
                        };
                };
 
                i2c2m1 {
                        i2c2m1_xfer: i2c2m1-xfer {
-                               rockchip,pins = <0 RK_PC2 RK_FUNC_2 &pcfg_pull_none>,
-                                               <0 RK_PC6 RK_FUNC_3 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PC2 2 &pcfg_pull_none>,
+                                               <0 RK_PC6 3 &pcfg_pull_none>;
                        };
 
                        i2c2m1_gpio: i2c2m1-gpio {
 
                i2c2m05v {
                        i2c2m05v_xfer: i2c2m05v-xfer {
-                               rockchip,pins = <1 RK_PD5 RK_FUNC_2 &pcfg_pull_none>,
-                                               <1 RK_PD4 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PD5 2 &pcfg_pull_none>,
+                                               <1 RK_PD4 2 &pcfg_pull_none>;
                        };
 
                        i2c2m05v_gpio: i2c2m05v-gpio {
 
                i2c3 {
                        i2c3_xfer: i2c3-xfer {
-                               rockchip,pins = <0 RK_PB6 RK_FUNC_1 &pcfg_pull_none>,
-                                               <0 RK_PC4 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PB6 1 &pcfg_pull_none>,
+                                               <0 RK_PC4 2 &pcfg_pull_none>;
                        };
                };
 
                pwm0 {
                        pwm0_pin: pwm0-pin {
-                               rockchip,pins = <0 RK_PC5 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PC5 1 &pcfg_pull_none>;
                        };
                };
 
                pwm1 {
                        pwm1_pin: pwm1-pin {
-                               rockchip,pins = <0 RK_PC4 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PC4 1 &pcfg_pull_none>;
                        };
                };
 
                pwm2 {
                        pwm2_pin: pwm2-pin {
-                               rockchip,pins = <0 RK_PC6 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PC6 1 &pcfg_pull_none>;
                        };
                };
 
                pwm3 {
                        pwm3_pin: pwm3-pin {
-                               rockchip,pins = <0 RK_PC0 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PC0 1 &pcfg_pull_none>;
                        };
                };
 
                pwm4 {
                        pwm4_pin: pwm4-pin {
-                               rockchip,pins = <1 RK_PC1 RK_FUNC_3 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PC1 3 &pcfg_pull_none>;
                        };
                };
 
                pwm5 {
                        pwm5_pin: pwm5-pin {
-                               rockchip,pins = <1 RK_PA7 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PA7 2 &pcfg_pull_none>;
                        };
                };
 
                pwm6 {
                        pwm6_pin: pwm6-pin {
-                               rockchip,pins = <1 RK_PB0 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB0 2 &pcfg_pull_none>;
                        };
                };
 
                pwm7 {
                        pwm7_pin: pwm7-pin {
-                               rockchip,pins = <1 RK_PB1 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PB1 2 &pcfg_pull_none>;
                        };
                };
 
                sdmmc {
                        sdmmc_clk: sdmmc-clk {
-                               rockchip,pins = <3 RK_PC4 RK_FUNC_1 &pcfg_pull_none_drv_4ma>;
+                               rockchip,pins = <3 RK_PC4 1 &pcfg_pull_none_drv_4ma>;
                        };
 
                        sdmmc_cmd: sdmmc-cmd {
-                               rockchip,pins = <3 RK_PC5 RK_FUNC_1 &pcfg_pull_up_drv_4ma>;
+                               rockchip,pins = <3 RK_PC5 1 &pcfg_pull_up_drv_4ma>;
                        };
 
                        sdmmc_cd: sdmmc-cd {
-                               rockchip,pins = <0 RK_PA1 RK_FUNC_1 &pcfg_pull_up_drv_4ma>;
+                               rockchip,pins = <0 RK_PA1 1 &pcfg_pull_up_drv_4ma>;
                        };
 
                        sdmmc_bus1: sdmmc-bus1 {
-                               rockchip,pins = <3 RK_PC3 RK_FUNC_1 &pcfg_pull_up_drv_4ma>;
+                               rockchip,pins = <3 RK_PC3 1 &pcfg_pull_up_drv_4ma>;
                        };
 
                        sdmmc_bus4: sdmmc-bus4 {
-                               rockchip,pins = <3 RK_PC3 RK_FUNC_1 &pcfg_pull_up_drv_4ma>,
-                                               <3 RK_PC2 RK_FUNC_1 &pcfg_pull_up_drv_4ma>,
-                                               <3 RK_PC1 RK_FUNC_1 &pcfg_pull_up_drv_4ma>,
-                                               <3 RK_PC0 RK_FUNC_1 &pcfg_pull_up_drv_4ma>;
+                               rockchip,pins = <3 RK_PC3 1 &pcfg_pull_up_drv_4ma>,
+                                               <3 RK_PC2 1 &pcfg_pull_up_drv_4ma>,
+                                               <3 RK_PC1 1 &pcfg_pull_up_drv_4ma>,
+                                               <3 RK_PC0 1 &pcfg_pull_up_drv_4ma>;
                        };
                };
 
                spim0 {
                        spim0_clk: spim0-clk {
-                               rockchip,pins = <1 RK_PD0 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PD0 2 &pcfg_pull_up>;
                        };
 
                        spim0_cs0: spim0-cs0 {
-                               rockchip,pins = <1 RK_PD1 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PD1 2 &pcfg_pull_up>;
                        };
 
                        spim0_tx: spim0-tx {
-                               rockchip,pins = <1 RK_PD3 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PD3 2 &pcfg_pull_up>;
                        };
 
                        spim0_rx: spim0-rx {
-                               rockchip,pins = <1 RK_PD2 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PD2 2 &pcfg_pull_up>;
                        };
                };
 
                spim1 {
                        spim1_clk: spim1-clk {
-                               rockchip,pins = <0 RK_PA3 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PA3 1 &pcfg_pull_up>;
                        };
 
                        spim1_cs0: spim1-cs0 {
-                               rockchip,pins = <0 RK_PA4 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PA4 1 &pcfg_pull_up>;
                        };
 
                        spim1_rx: spim1-rx {
-                               rockchip,pins = <0 RK_PB0 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PB0 1 &pcfg_pull_up>;
                        };
 
                        spim1_tx: spim1-tx {
-                               rockchip,pins = <0 RK_PA7 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PA7 1 &pcfg_pull_up>;
                        };
                };
 
                tsadc {
                        otp_out: otp-out {
-                               rockchip,pins = <0 RK_PB7 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PB7 1 &pcfg_pull_none>;
                        };
 
                        otp_gpio: otp-gpio {
 
                uart0 {
                        uart0_xfer: uart0-xfer {
-                               rockchip,pins = <3 RK_PA6 RK_FUNC_1 &pcfg_pull_up>,
-                                               <3 RK_PA5 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PA6 1 &pcfg_pull_up>,
+                                               <3 RK_PA5 1 &pcfg_pull_none>;
                        };
 
                        uart0_cts: uart0-cts {
-                               rockchip,pins = <3 RK_PA4 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PA4 1 &pcfg_pull_none>;
                        };
 
                        uart0_rts: uart0-rts {
-                               rockchip,pins = <3 RK_PA3 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PA3 1 &pcfg_pull_none>;
                        };
 
                        uart0_rts_gpio: uart0-rts-gpio {
 
                uart1 {
                        uart1_xfer: uart1-xfer {
-                               rockchip,pins = <1 RK_PD3 RK_FUNC_1 &pcfg_pull_up>,
-                                               <1 RK_PD2 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PD3 1 &pcfg_pull_up>,
+                                               <1 RK_PD2 1 &pcfg_pull_none>;
                        };
 
                        uart1_cts: uart1-cts {
-                               rockchip,pins = <1 RK_PD0 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PD0 1 &pcfg_pull_none>;
                        };
 
                        uart1_rts: uart1-rts {
-                               rockchip,pins = <1 RK_PD1 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PD1 1 &pcfg_pull_none>;
                        };
                };
 
                uart2m0 {
                        uart2m0_xfer: uart2m0-xfer {
-                               rockchip,pins = <2 RK_PD2 RK_FUNC_1 &pcfg_pull_up>,
-                                               <2 RK_PD1 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PD2 1 &pcfg_pull_up>,
+                                               <2 RK_PD1 1 &pcfg_pull_none>;
                        };
                };
 
                uart2m1 {
                        uart2m1_xfer: uart2m1-xfer {
-                               rockchip,pins = <3 RK_PC3 RK_FUNC_2 &pcfg_pull_up>,
-                                               <3 RK_PC2 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PC3 2 &pcfg_pull_up>,
+                                               <3 RK_PC2 2 &pcfg_pull_none>;
                        };
                };
 
                uart2_5v {
                        uart2_5v_cts: uart2_5v-cts {
-                               rockchip,pins = <1 RK_PD4 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PD4 1 &pcfg_pull_none>;
                        };
 
                        uart2_5v_rts: uart2_5v-rts {
-                               rockchip,pins = <1 RK_PD5 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PD5 1 &pcfg_pull_none>;
                        };
                };
        };
index eb6d192..fbbd937 100644 (file)
                vdd_core-supply = <&ldo14_reg>;
 
                clock-frequency = <16000000>;
-               clocks = <&clock_cam 0>;
+               clocks = <&camera 0>;
                clock-names = "mclk";
                nreset-gpios = <&gpb 2 0>;
                nstby-gpios = <&gpb 0 0>;
index a44d5eb..2ad642f 100644 (file)
                        clock-names = "sclk_cam0", "sclk_cam1";
                        #address-cells = <1>;
                        #size-cells = <1>;
+                       #clock-cells = <1>;
+                       clock-output-names = "cam_a_clkout", "cam_b_clkout";
                        ranges;
 
-                       clock_cam: clock-controller {
-                               #clock-cells = <1>;
-                       };
-
                        csis0: csis@fa600000 {
                                compatible = "samsung,s5pv210-csis";
                                reg = <0xfa600000 0x4000>;
index d159ee4..2e2c1a7 100644 (file)
@@ -1,46 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * sama5d2.dtsi - Device Tree Include file for SAMA5D2 family SoC
  *
  *  Copyright (C) 2015 Atmel,
  *                2015 Ludovic Desroches <ludovic.desroches@atmel.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 #include <dt-bindings/dma/at91.h>
                                ranges = <0 0xf8044000 0x1420>;
                        };
 
-                       rstc@f8048000 {
+                       reset_controller: rstc@f8048000 {
                                compatible = "atmel,sama5d3-rstc";
                                reg = <0xf8048000 0x10>;
                                clocks = <&clk32k>;
                        };
 
-                       shdwc@f8048010 {
+                       shutdown_controller: shdwc@f8048010 {
                                compatible = "atmel,sama5d2-shdwc";
                                reg = <0xf8048010 0x10>;
                                clocks = <&clk32k>;
                                clocks = <&pmc PMC_TYPE_CORE PMC_MCK2>;
                        };
 
-                       watchdog@f8048040 {
+                       watchdog: watchdog@f8048040 {
                                compatible = "atmel,sama5d4-wdt";
                                reg = <0xf8048040 0x10>;
                                interrupts = <4 IRQ_TYPE_LEVEL_HIGH 7>;
index b632143..66695b9 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * sama5d36ek_cmp.dts - Device Tree file for SAMA5D36-EK CMP board
  *
  *  Copyright (C) 2016 Atmel,
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 /dts-v1/;
 #include "sama5d36.dtsi"
index a02f590..9d25636 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * sama5d3xcm_cmp.dtsi - Device Tree Include file for SAMA5D36 CMP CPU Module
  *
  *  Copyright (C) 2016 Atmel,
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 / {
index 97e171d..8a6916a 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * sama5d3xmb_cmp.dts - Device Tree file for SAMA5D3x CMP mother board
  *
  *  Copyright (C) 2016 Atmel,
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 #include "sama5d3xcm_cmp.dtsi"
 
index 6c1e41f..6ab27a7 100644 (file)
@@ -1,46 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * sama5d4.dtsi - Device Tree Include file for SAMA5D4 family SoC
  *
  *  Copyright (C) 2014 Atmel,
  *                2014 Nicolas Ferre <nicolas.ferre@atmel.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 #include <dt-bindings/clock/at91.h>
index df2bab1..64dc079 100644 (file)
@@ -9,6 +9,7 @@
 &mmc {
        status = "okay";
        cap-sd-highspeed;
+       cap-mmc-highspeed;
        broken-cd;
        bus-width = <4>;
 };
index e6ed7c0..81fabf0 100644 (file)
                        status = "disabled";
                };
 
+               gpu@a0300000 {
+                       /*
+                        * This block is referred to as "Smart Graphics Adapter SGA500"
+                        * in documentation but is in practice a pretty straight-forward
+                        * MALI-400 GPU block.
+                        */
+                       compatible = "stericsson,db8500-mali", "arm,mali-400";
+                       reg = <0xa0300000 0x10000>;
+                       interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "gp",
+                                         "gpmmu",
+                                         "pp0",
+                                         "ppmmu0",
+                                         "combined";
+                       clocks = <&prcmu_clk PRCMU_ACLK>, <&prcmu_clk PRCMU_SGACLK>;
+                       clock-names = "bus", "core";
+                       mali-supply = <&db8500_sga_reg>;
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
+               };
+
                mcde@a0350000 {
-                       compatible = "stericsson,mcde";
-                       reg = <0xa0350000 0x1000>, /* MCDE */
-                             <0xa0351000 0x1000>, /* DSI link 1 */
-                             <0xa0352000 0x1000>, /* DSI link 2 */
-                             <0xa0353000 0x1000>; /* DSI link 3 */
+                       compatible = "ste,mcde";
+                       reg = <0xa0350000 0x1000>;
                        interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+                       epod-supply = <&db8500_b2r2_mcde_reg>;
+                       vana-supply = <&ab8500_ldo_ana_reg>;
                        clocks = <&prcmu_clk PRCMU_MCDECLK>, /* Main MCDE clock */
                                 <&prcmu_clk PRCMU_LCDCLK>, /* LCD clock */
-                                <&prcmu_clk PRCMU_PLLDSI>, /* HDMI clock */
-                                <&prcmu_clk PRCMU_DSI0CLK>, /* DSI 0 */
-                                <&prcmu_clk PRCMU_DSI1CLK>, /* DSI 1 */
-                                <&prcmu_clk PRCMU_DSI0ESCCLK>, /* TVout clock 0 */
-                                <&prcmu_clk PRCMU_DSI1ESCCLK>, /* TVout clock 1 */
-                                <&prcmu_clk PRCMU_DSI2ESCCLK>; /* TVout clock 2 */
+                                <&prcmu_clk PRCMU_PLLDSI>; /* HDMI clock */
+                       clock-names = "mcde", "lcd", "hdmi";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+                       status = "disabled";
+
+                       dsi0: dsi@a0351000 {
+                               compatible = "ste,mcde-dsi";
+                               reg = <0xa0351000 0x1000>;
+                               vana-supply = <&ab8500_ldo_ana_reg>;
+                               clocks = <&prcmu_clk PRCMU_DSI0CLK>, <&prcmu_clk PRCMU_DSI0ESCCLK>;
+                               clock-names = "hs", "lp";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+                       dsi1: dsi@a0352000 {
+                               compatible = "ste,mcde-dsi";
+                               reg = <0xa0352000 0x1000>;
+                               vana-supply = <&ab8500_ldo_ana_reg>;
+                               clocks = <&prcmu_clk PRCMU_DSI1CLK>, <&prcmu_clk PRCMU_DSI1ESCCLK>;
+                               clock-names = "hs", "lp";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+                       dsi2: dsi@a0353000 {
+                               compatible = "ste,mcde-dsi";
+                               reg = <0xa0353000 0x1000>;
+                               vana-supply = <&ab8500_ldo_ana_reg>;
+                               /* This DSI port only has the Low Power / Energy Save clock */
+                               clocks = <&prcmu_clk PRCMU_DSI2ESCCLK>;
+                               clock-names = "lp";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
                };
 
                cryp@a03cb000 {
index 35e944d..eeaea21 100644 (file)
                                };
                        };
                };
+
+               mcde@a0350000 {
+                       status = "okay";
+
+                       dsi@a0351000 {
+                               panel {
+                                       compatible = "samsung,s6d16d0";
+                                       reg = <0>;
+                                       vdd1-supply = <&ab8500_ldo_aux1_reg>;
+                                       reset-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+                               };
+                       };
+               };
        };
 };
index 0e7d77d..7686844 100644 (file)
                                };
                        };
                };
+
+               mcde@a0350000 {
+                       status = "okay";
+
+                       dsi@a0351000 {
+                               panel {
+                                       compatible = "samsung,s6d16d0";
+                                       reg = <0>;
+                                       vdd1-supply = <&ab8500_ldo_aux1_reg>;
+                                       reset-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+                               };
+                       };
+               };
        };
 };
index 588b6ef..4a49544 100644 (file)
        };
 
        soc {
+               romem: nvmem@1fff7800 {
+                       compatible = "st,stm32f4-otp";
+                       reg = <0x1fff7800 0x400>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ts_cal1: calib@22c {
+                               reg = <0x22c 0x2>;
+                       };
+                       ts_cal2: calib@22e {
+                               reg = <0x22e 0x2>;
+                       };
+               };
+
                timer2: timer@40000000 {
                        compatible = "st,stm32-timer";
                        reg = <0x40000000 0x400>;
index 3c72168..6f1d0ac 100644 (file)
        };
 };
 
+&rcc {
+       compatible = "st,stm32f769-rcc", "st,stm32f746-rcc", "st,stm32-rcc";
+};
+
 &cec {
        pinctrl-0 = <&cec_pins_a>;
        pinctrl-names = "default";
index 980b276..e44e7ba 100644 (file)
                                };
                        };
 
+                       sdmmc1_b4_pins_a: sdmmc1-b4-0 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
+                                                <STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
+                                                <STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */
+                                                <STM32_PINMUX('C', 11, AF12)>, /* SDMMC1_D3 */
+                                                <STM32_PINMUX('C', 12, AF12)>, /* SDMMC1_CK */
+                                                <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
+                                       slew-rate = <3>;
+                                       drive-push-pull;
+                                       bias-disable;
+                               };
+                       };
+
+                       sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
+                                                <STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
+                                                <STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */
+                                                <STM32_PINMUX('C', 11, AF12)>, /* SDMMC1_D3 */
+                                                <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */
+                                       slew-rate = <3>;
+                                       drive-push-pull;
+                                       bias-disable;
+                               };
+                               pins2{
+                                       pinmux = <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
+                                       slew-rate = <3>;
+                                       drive-open-drain;
+                                       bias-disable;
+                               };
+                       };
+
+                       sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('C', 8, ANALOG)>, /* SDMMC1_D0 */
+                                                <STM32_PINMUX('C', 9, ANALOG)>, /* SDMMC1_D1 */
+                                                <STM32_PINMUX('C', 10, ANALOG)>, /* SDMMC1_D2 */
+                                                <STM32_PINMUX('C', 11, ANALOG)>, /* SDMMC1_D3 */
+                                                <STM32_PINMUX('C', 12, ANALOG)>, /* SDMMC1_CK */
+                                                <STM32_PINMUX('D', 2, ANALOG)>; /* SDMMC1_CMD */
+                               };
+                       };
+
+                       sdmmc1_dir_pins_a: sdmmc1-dir-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('C', 6, AF8)>, /* SDMMC1_D0DIR */
+                                                <STM32_PINMUX('C', 7, AF8)>, /* SDMMC1_D123DIR */
+                                                <STM32_PINMUX('B', 9, AF7)>; /* SDMMC1_CDIR */
+                                       slew-rate = <3>;
+                                       drive-push-pull;
+                                       bias-pull-up;
+                               };
+                               pins2{
+                                       pinmux = <STM32_PINMUX('B', 8, AF7)>; /* SDMMC1_CKIN */
+                                       bias-pull-up;
+                               };
+                       };
+
+                       sdmmc1_dir_sleep_pins_a: sdmmc1-dir-sleep-0 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('C', 6, ANALOG)>, /* SDMMC1_D0DIR */
+                                                <STM32_PINMUX('C', 7, ANALOG)>, /* SDMMC1_D123DIR */
+                                                <STM32_PINMUX('B', 9, ANALOG)>, /* SDMMC1_CDIR */
+                                                <STM32_PINMUX('B', 8, ANALOG)>; /* SDMMC1_CKIN */
+                               };
+                       };
+
                        usart1_pins: usart1@0 {
                                pins1 {
                                        pinmux = <STM32_PINMUX('B', 14, AF4)>; /* USART1_TX */
index 5cac79e..c065266 100644 (file)
                        dma-requests = <32>;
                };
 
+               sdmmc1: sdmmc@52007000 {
+                       compatible = "arm,pl18x", "arm,primecell";
+                       arm,primecell-periphid = <0x10153180>;
+                       reg = <0x52007000 0x1000>;
+                       interrupts = <49>;
+                       interrupt-names = "cmd_irq";
+                       clocks = <&rcc SDMMC1_CK>;
+                       clock-names = "apb_pclk";
+                       resets = <&rcc STM32H7_AHB3_RESET(SDMMC1)>;
+                       cap-sd-highspeed;
+                       cap-mmc-highspeed;
+                       max-frequency = <120000000>;
+               };
+
                exti: interrupt-controller@58000000 {
                        compatible = "st,stm32h7-exti";
                        interrupt-controller;
index dd06c8f..3acd2e9 100644 (file)
        aliases {
                serial0 = &usart2;
        };
+
+       v3v3: regulator-v3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "v3v3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
 };
 
 &clk_hse {
        };
 };
 
+&sdmmc1 {
+       pinctrl-names = "default", "opendrain", "sleep";
+       pinctrl-0 = <&sdmmc1_b4_pins_a>;
+       pinctrl-1 = <&sdmmc1_b4_od_pins_a>;
+       pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;
+       broken-cd;
+       st,neg-edge;
+       bus-width = <4>;
+       vmmc-supply = <&v3v3>;
+       status = "okay";
+};
+
 &usart2 {
        pinctrl-0 = <&usart2_pins>;
        pinctrl-names = "default";
index ebc3f09..ab78ad5 100644 (file)
                regulator-always-on;
        };
 
+       v2v9_sd: regulator-v2v9_sd {
+               compatible = "regulator-fixed";
+               regulator-name = "v2v9_sd";
+               regulator-min-microvolt = <2900000>;
+               regulator-max-microvolt = <2900000>;
+               regulator-always-on;
+       };
+
        usbotg_hs_phy: usb-phy {
                #phy-cells = <0>;
                compatible = "usb-nop-xceiv";
                clocks = <&rcc USB1ULPI_CK>;
                clock-names = "main_clk";
        };
-
 };
 
 &adc_12 {
        };
 };
 
+&sdmmc1 {
+       pinctrl-names = "default", "opendrain", "sleep";
+       pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
+       pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>;
+       pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>;
+       broken-cd;
+       st,sig-dir;
+       st,neg-edge;
+       st,use-ckin;
+       bus-width = <4>;
+       vmmc-supply = <&v2v9_sd>;
+       status = "okay";
+};
+
 &usart1 {
        pinctrl-0 = <&usart1_pins>;
        pinctrl-names = "default";
index 9ec4694..85c417d 100644 (file)
                                };
                        };
 
+                       cec_pins_sleep_a: cec-sleep-0 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('A', 15, ANALOG)>; /* HDMI_CEC */
+                               };
+                       };
+
+                       cec_pins_b: cec-1 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('B', 6, AF5)>;
+                                       bias-disable;
+                                       drive-open-drain;
+                                       slew-rate = <0>;
+                               };
+                       };
+
+                       cec_pins_sleep_b: cec-sleep-1 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('B', 6, ANALOG)>; /* HDMI_CEC */
+                               };
+                       };
+
                        ethernet0_rgmii_pins_a: rgmii-0 {
                                pins1 {
                                        pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
                                };
                        };
 
+                       i2c1_pins_sleep_a: i2c1-1 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('D', 12, ANALOG)>, /* I2C1_SCL */
+                                                <STM32_PINMUX('F', 15, ANALOG)>; /* I2C1_SDA */
+                               };
+                       };
+
                        i2c2_pins_a: i2c2-0 {
                                pins {
                                        pinmux = <STM32_PINMUX('H', 4, AF4)>, /* I2C2_SCL */
                                };
                        };
 
+                       i2c2_pins_sleep_a: i2c2-1 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('H', 4, ANALOG)>, /* I2C2_SCL */
+                                                <STM32_PINMUX('H', 5, ANALOG)>; /* I2C2_SDA */
+                               };
+                       };
+
                        i2c5_pins_a: i2c5-0 {
                                pins {
                                        pinmux = <STM32_PINMUX('A', 11, AF4)>, /* I2C5_SCL */
                                };
                        };
 
+                       i2c5_pins_sleep_a: i2c5-1 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('A', 11, ANALOG)>, /* I2C5_SCL */
+                                                <STM32_PINMUX('A', 12, ANALOG)>; /* I2C5_SDA */
+
+                               };
+                       };
+
+                       ltdc_pins_a: ltdc-a-0 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('G',  7, AF14)>, /* LCD_CLK */
+                                                <STM32_PINMUX('I', 10, AF14)>, /* LCD_HSYNC */
+                                                <STM32_PINMUX('I',  9, AF14)>, /* LCD_VSYNC */
+                                                <STM32_PINMUX('F', 10, AF14)>, /* LCD_DE */
+                                                <STM32_PINMUX('H',  2, AF14)>, /* LCD_R0 */
+                                                <STM32_PINMUX('H',  3, AF14)>, /* LCD_R1 */
+                                                <STM32_PINMUX('H',  8, AF14)>, /* LCD_R2 */
+                                                <STM32_PINMUX('H',  9, AF14)>, /* LCD_R3 */
+                                                <STM32_PINMUX('H', 10, AF14)>, /* LCD_R4 */
+                                                <STM32_PINMUX('C',  0, AF14)>, /* LCD_R5 */
+                                                <STM32_PINMUX('H', 12, AF14)>, /* LCD_R6 */
+                                                <STM32_PINMUX('E', 15, AF14)>, /* LCD_R7 */
+                                                <STM32_PINMUX('E',  5, AF14)>, /* LCD_G0 */
+                                                <STM32_PINMUX('E',  6, AF14)>, /* LCD_G1 */
+                                                <STM32_PINMUX('H', 13, AF14)>, /* LCD_G2 */
+                                                <STM32_PINMUX('H', 14, AF14)>, /* LCD_G3 */
+                                                <STM32_PINMUX('H', 15, AF14)>, /* LCD_G4 */
+                                                <STM32_PINMUX('I',  0, AF14)>, /* LCD_G5 */
+                                                <STM32_PINMUX('I',  1, AF14)>, /* LCD_G6 */
+                                                <STM32_PINMUX('I',  2, AF14)>, /* LCD_G7 */
+                                                <STM32_PINMUX('D',  9, AF14)>, /* LCD_B0 */
+                                                <STM32_PINMUX('G', 12, AF14)>, /* LCD_B1 */
+                                                <STM32_PINMUX('G', 10, AF14)>, /* LCD_B2 */
+                                                <STM32_PINMUX('D', 10, AF14)>, /* LCD_B3 */
+                                                <STM32_PINMUX('I',  4, AF14)>, /* LCD_B4 */
+                                                <STM32_PINMUX('A',  3, AF14)>, /* LCD_B5 */
+                                                <STM32_PINMUX('B',  8, AF14)>, /* LCD_B6 */
+                                                <STM32_PINMUX('D',  8, AF14)>; /* LCD_B7 */
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <1>;
+                               };
+                       };
+
+                       ltdc_pins_sleep_a: ltdc-a-1 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('G',  7, ANALOG)>, /* LCD_CLK */
+                                                <STM32_PINMUX('I', 10, ANALOG)>, /* LCD_HSYNC */
+                                                <STM32_PINMUX('I',  9, ANALOG)>, /* LCD_VSYNC */
+                                                <STM32_PINMUX('F', 10, ANALOG)>, /* LCD_DE */
+                                                <STM32_PINMUX('H',  2, ANALOG)>, /* LCD_R0 */
+                                                <STM32_PINMUX('H',  3, ANALOG)>, /* LCD_R1 */
+                                                <STM32_PINMUX('H',  8, ANALOG)>, /* LCD_R2 */
+                                                <STM32_PINMUX('H',  9, ANALOG)>, /* LCD_R3 */
+                                                <STM32_PINMUX('H', 10, ANALOG)>, /* LCD_R4 */
+                                                <STM32_PINMUX('C',  0, ANALOG)>, /* LCD_R5 */
+                                                <STM32_PINMUX('H', 12, ANALOG)>, /* LCD_R6 */
+                                                <STM32_PINMUX('E', 15, ANALOG)>, /* LCD_R7 */
+                                                <STM32_PINMUX('E',  5, ANALOG)>, /* LCD_G0 */
+                                                <STM32_PINMUX('E',  6, ANALOG)>, /* LCD_G1 */
+                                                <STM32_PINMUX('H', 13, ANALOG)>, /* LCD_G2 */
+                                                <STM32_PINMUX('H', 14, ANALOG)>, /* LCD_G3 */
+                                                <STM32_PINMUX('H', 15, ANALOG)>, /* LCD_G4 */
+                                                <STM32_PINMUX('I',  0, ANALOG)>, /* LCD_G5 */
+                                                <STM32_PINMUX('I',  1, ANALOG)>, /* LCD_G6 */
+                                                <STM32_PINMUX('I',  2, ANALOG)>, /* LCD_G7 */
+                                                <STM32_PINMUX('D',  9, ANALOG)>, /* LCD_B0 */
+                                                <STM32_PINMUX('G', 12, ANALOG)>, /* LCD_B1 */
+                                                <STM32_PINMUX('G', 10, ANALOG)>, /* LCD_B2 */
+                                                <STM32_PINMUX('D', 10, ANALOG)>, /* LCD_B3 */
+                                                <STM32_PINMUX('I',  4, ANALOG)>, /* LCD_B4 */
+                                                <STM32_PINMUX('A',  3, ANALOG)>, /* LCD_B5 */
+                                                <STM32_PINMUX('B',  8, ANALOG)>, /* LCD_B6 */
+                                                <STM32_PINMUX('D',  8, ANALOG)>; /* LCD_B7 */
+                               };
+                       };
+
+                       ltdc_pins_b: ltdc-b-0 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('I', 14, AF14)>, /* LCD_CLK */
+                                                <STM32_PINMUX('I', 12, AF14)>, /* LCD_HSYNC */
+                                                <STM32_PINMUX('I', 13, AF14)>, /* LCD_VSYNC */
+                                                <STM32_PINMUX('K',  7, AF14)>, /* LCD_DE */
+                                                <STM32_PINMUX('I', 15, AF14)>, /* LCD_R0 */
+                                                <STM32_PINMUX('J',  0, AF14)>, /* LCD_R1 */
+                                                <STM32_PINMUX('J',  1, AF14)>, /* LCD_R2 */
+                                                <STM32_PINMUX('J',  2, AF14)>, /* LCD_R3 */
+                                                <STM32_PINMUX('J',  3, AF14)>, /* LCD_R4 */
+                                                <STM32_PINMUX('J',  4, AF14)>, /* LCD_R5 */
+                                                <STM32_PINMUX('J',  5, AF14)>, /* LCD_R6 */
+                                                <STM32_PINMUX('J',  6, AF14)>, /* LCD_R7 */
+                                                <STM32_PINMUX('J',  7, AF14)>, /* LCD_G0 */
+                                                <STM32_PINMUX('J',  8, AF14)>, /* LCD_G1 */
+                                                <STM32_PINMUX('J',  9, AF14)>, /* LCD_G2 */
+                                                <STM32_PINMUX('J', 10, AF14)>, /* LCD_G3 */
+                                                <STM32_PINMUX('J', 11, AF14)>, /* LCD_G4 */
+                                                <STM32_PINMUX('K',  0, AF14)>, /* LCD_G5 */
+                                                <STM32_PINMUX('K',  1, AF14)>, /* LCD_G6 */
+                                                <STM32_PINMUX('K',  2, AF14)>, /* LCD_G7 */
+                                                <STM32_PINMUX('J', 12, AF14)>, /* LCD_B0 */
+                                                <STM32_PINMUX('J', 13, AF14)>, /* LCD_B1 */
+                                                <STM32_PINMUX('J', 14, AF14)>, /* LCD_B2 */
+                                                <STM32_PINMUX('J', 15, AF14)>, /* LCD_B3 */
+                                                <STM32_PINMUX('K',  3, AF14)>, /* LCD_B4 */
+                                                <STM32_PINMUX('K',  4, AF14)>, /* LCD_B5 */
+                                                <STM32_PINMUX('K',  5, AF14)>, /* LCD_B6 */
+                                                <STM32_PINMUX('K',  6, AF14)>; /* LCD_B7 */
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <1>;
+                               };
+                       };
+
+                       ltdc_pins_sleep_b: ltdc-b-1 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('I', 14, ANALOG)>, /* LCD_CLK */
+                                                <STM32_PINMUX('I', 12, ANALOG)>, /* LCD_HSYNC */
+                                                <STM32_PINMUX('I', 13, ANALOG)>, /* LCD_VSYNC */
+                                                <STM32_PINMUX('K',  7, ANALOG)>, /* LCD_DE */
+                                                <STM32_PINMUX('I', 15, ANALOG)>, /* LCD_R0 */
+                                                <STM32_PINMUX('J',  0, ANALOG)>, /* LCD_R1 */
+                                                <STM32_PINMUX('J',  1, ANALOG)>, /* LCD_R2 */
+                                                <STM32_PINMUX('J',  2, ANALOG)>, /* LCD_R3 */
+                                                <STM32_PINMUX('J',  3, ANALOG)>, /* LCD_R4 */
+                                                <STM32_PINMUX('J',  4, ANALOG)>, /* LCD_R5 */
+                                                <STM32_PINMUX('J',  5, ANALOG)>, /* LCD_R6 */
+                                                <STM32_PINMUX('J',  6, ANALOG)>, /* LCD_R7 */
+                                                <STM32_PINMUX('J',  7, ANALOG)>, /* LCD_G0 */
+                                                <STM32_PINMUX('J',  8, ANALOG)>, /* LCD_G1 */
+                                                <STM32_PINMUX('J',  9, ANALOG)>, /* LCD_G2 */
+                                                <STM32_PINMUX('J', 10, ANALOG)>, /* LCD_G3 */
+                                                <STM32_PINMUX('J', 11, ANALOG)>, /* LCD_G4 */
+                                                <STM32_PINMUX('K',  0, ANALOG)>, /* LCD_G5 */
+                                                <STM32_PINMUX('K',  1, ANALOG)>, /* LCD_G6 */
+                                                <STM32_PINMUX('K',  2, ANALOG)>, /* LCD_G7 */
+                                                <STM32_PINMUX('J', 12, ANALOG)>, /* LCD_B0 */
+                                                <STM32_PINMUX('J', 13, ANALOG)>, /* LCD_B1 */
+                                                <STM32_PINMUX('J', 14, ANALOG)>, /* LCD_B2 */
+                                                <STM32_PINMUX('J', 15, ANALOG)>, /* LCD_B3 */
+                                                <STM32_PINMUX('K',  3, ANALOG)>, /* LCD_B4 */
+                                                <STM32_PINMUX('K',  4, ANALOG)>, /* LCD_B5 */
+                                                <STM32_PINMUX('K',  5, ANALOG)>, /* LCD_B6 */
+                                                <STM32_PINMUX('K',  6, ANALOG)>; /* LCD_B7 */
+                               };
+                       };
+
                        m_can1_pins_a: m-can1-0 {
                                pins1 {
                                        pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */
                                };
                        };
 
+                       sdmmc1_b4_pins_a: sdmmc1-b4-0 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
+                                                <STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
+                                                <STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */
+                                                <STM32_PINMUX('C', 11, AF12)>, /* SDMMC1_D3 */
+                                                <STM32_PINMUX('C', 12, AF12)>, /* SDMMC1_CK */
+                                                <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
+                                       slew-rate = <3>;
+                                       drive-push-pull;
+                                       bias-disable;
+                               };
+                       };
+
+                       sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
+                                                <STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
+                                                <STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */
+                                                <STM32_PINMUX('C', 11, AF12)>, /* SDMMC1_D3 */
+                                                <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */
+                                       slew-rate = <3>;
+                                       drive-push-pull;
+                                       bias-disable;
+                               };
+                               pins2{
+                                       pinmux = <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
+                                       slew-rate = <3>;
+                                       drive-open-drain;
+                                       bias-disable;
+                               };
+                       };
+
+                       sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('C', 8, ANALOG)>, /* SDMMC1_D0 */
+                                                <STM32_PINMUX('C', 9, ANALOG)>, /* SDMMC1_D1 */
+                                                <STM32_PINMUX('C', 10, ANALOG)>, /* SDMMC1_D2 */
+                                                <STM32_PINMUX('C', 11, ANALOG)>, /* SDMMC1_D3 */
+                                                <STM32_PINMUX('C', 12, ANALOG)>, /* SDMMC1_CK */
+                                                <STM32_PINMUX('D', 2, ANALOG)>; /* SDMMC1_CMD */
+                               };
+                       };
+
+                       sdmmc1_dir_pins_a: sdmmc1-dir-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('F', 2, AF11)>, /* SDMMC1_D0DIR */
+                                                <STM32_PINMUX('C', 7, AF8)>, /* SDMMC1_D123DIR */
+                                                <STM32_PINMUX('B', 9, AF11)>; /* SDMMC1_CDIR */
+                                       slew-rate = <3>;
+                                       drive-push-pull;
+                                       bias-pull-up;
+                               };
+                               pins2{
+                                       pinmux = <STM32_PINMUX('E', 4, AF8)>; /* SDMMC1_CKIN */
+                                       bias-pull-up;
+                               };
+                       };
+
+                       sdmmc1_dir_sleep_pins_a: sdmmc1-dir-sleep-0 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('F', 2, ANALOG)>, /* SDMMC1_D0DIR */
+                                                <STM32_PINMUX('C', 7, ANALOG)>, /* SDMMC1_D123DIR */
+                                                <STM32_PINMUX('B', 9, ANALOG)>, /* SDMMC1_CDIR */
+                                                <STM32_PINMUX('E', 4, ANALOG)>; /* SDMMC1_CKIN */
+                               };
+                       };
+
+                       spdifrx_pins_a: spdifrx-0 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('G', 12, AF8)>; /* SPDIF_IN1 */
+                                       bias-disable;
+                               };
+                       };
+
+                       spdifrx_sleep_pins_a: spdifrx-1 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('G', 12, ANALOG)>; /* SPDIF_IN1 */
+                               };
+                       };
+
                        uart4_pins_a: uart4-0 {
                                pins1 {
                                        pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
                                };
                        };
 
+                       i2c4_pins_sleep_a: i2c4-1 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('Z', 4, ANALOG)>, /* I2C4_SCL */
+                                                <STM32_PINMUX('Z', 5, ANALOG)>; /* I2C4_SDA */
+                               };
+                       };
+
                        spi1_pins_a: spi1-0 {
                                pins1 {
                                        pinmux = <STM32_PINMUX('Z', 0, AF5)>, /* SPI1_SCK */
diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts
new file mode 100644 (file)
index 0000000..098dbfb
--- /dev/null
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+
+/dts-v1/;
+
+#include "stm32mp157c.dtsi"
+#include "stm32mp157-pinctrl.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
+
+/ {
+       model = "STMicroelectronics STM32MP157A-DK1 Discovery Board";
+       compatible = "st,stm32mp157a-dk1", "st,stm32mp157";
+
+       aliases {
+               ethernet0 = &ethernet0;
+               serial0 = &uart4;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory@c0000000 {
+               reg = <0xc0000000 0x20000000>;
+       };
+
+       led {
+               compatible = "gpio-leds";
+               blue {
+                       label = "heartbeat";
+                       gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+                       default-state = "off";
+               };
+       };
+};
+
+&cec {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&cec_pins_b>;
+       pinctrl-1 = <&cec_pins_sleep_b>;
+       status = "okay";
+};
+
+&ethernet0 {
+       status = "okay";
+       pinctrl-0 = <&ethernet0_rgmii_pins_a>;
+       pinctrl-1 = <&ethernet0_rgmii_pins_sleep_a>;
+       pinctrl-names = "default", "sleep";
+       phy-mode = "rgmii";
+       max-speed = <1000>;
+       phy-handle = <&phy0>;
+
+       mdio0 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "snps,dwmac-mdio";
+               phy0: ethernet-phy@0 {
+                       reg = <0>;
+               };
+       };
+};
+
+
+&i2c4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c4_pins_a>;
+       i2c-scl-rising-time-ns = <185>;
+       i2c-scl-falling-time-ns = <20>;
+       status = "okay";
+       /* spare dmas for other usage */
+       /delete-property/dmas;
+       /delete-property/dma-names;
+
+       pmic: stpmic@33 {
+               compatible = "st,stpmic1";
+               reg = <0x33>;
+               interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               status = "okay";
+
+               regulators {
+                       compatible = "st,stpmic1-regulators";
+                       ldo1-supply = <&v3v3>;
+                       ldo3-supply = <&vdd_ddr>;
+                       ldo6-supply = <&v3v3>;
+                       pwr_sw1-supply = <&bst_out>;
+                       pwr_sw2-supply = <&bst_out>;
+
+                       vddcore: buck1 {
+                               regulator-name = "vddcore";
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-initial-mode = <0>;
+                               regulator-over-current-protection;
+                       };
+
+                       vdd_ddr: buck2 {
+                               regulator-name = "vdd_ddr";
+                               regulator-min-microvolt = <1350000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-initial-mode = <0>;
+                               regulator-over-current-protection;
+                       };
+
+                       vdd: buck3 {
+                               regulator-name = "vdd";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                               st,mask-reset;
+                               regulator-initial-mode = <0>;
+                               regulator-over-current-protection;
+                       };
+
+                       v3v3: buck4 {
+                               regulator-name = "v3v3";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                               regulator-over-current-protection;
+                               regulator-initial-mode = <0>;
+                       };
+
+                       v1v8_audio: ldo1 {
+                               regulator-name = "v1v8_audio";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               interrupts = <IT_CURLIM_LDO1 0>;
+                       };
+
+                       v3v3_hdmi: ldo2 {
+                               regulator-name = "v3v3_hdmi";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                               interrupts = <IT_CURLIM_LDO2 0>;
+                       };
+
+                       vtt_ddr: ldo3 {
+                               regulator-name = "vtt_ddr";
+                               regulator-min-microvolt = <500000>;
+                               regulator-max-microvolt = <750000>;
+                               regulator-always-on;
+                               regulator-over-current-protection;
+                       };
+
+                       vdd_usb: ldo4 {
+                               regulator-name = "vdd_usb";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               interrupts = <IT_CURLIM_LDO4 0>;
+                       };
+
+                       vdda: ldo5 {
+                               regulator-name = "vdda";
+                               regulator-min-microvolt = <2900000>;
+                               regulator-max-microvolt = <2900000>;
+                               interrupts = <IT_CURLIM_LDO5 0>;
+                               regulator-boot-on;
+                       };
+
+                       v1v2_hdmi: ldo6 {
+                               regulator-name = "v1v2_hdmi";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               interrupts = <IT_CURLIM_LDO6 0>;
+                       };
+
+                       vref_ddr: vref_ddr {
+                               regulator-name = "vref_ddr";
+                               regulator-always-on;
+                               regulator-over-current-protection;
+                       };
+
+                        bst_out: boost {
+                               regulator-name = "bst_out";
+                               interrupts = <IT_OCP_BOOST 0>;
+                        };
+
+                       vbus_otg: pwr_sw1 {
+                               regulator-name = "vbus_otg";
+                               interrupts = <IT_OCP_OTG 0>;
+                        };
+
+                        vbus_sw: pwr_sw2 {
+                               regulator-name = "vbus_sw";
+                               interrupts = <IT_OCP_SWOUT 0>;
+                               regulator-active-discharge;
+                        };
+               };
+
+               onkey {
+                       compatible = "st,stpmic1-onkey";
+                       interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 0>;
+                       interrupt-names = "onkey-falling", "onkey-rising";
+                       power-off-time-sec = <10>;
+                       status = "okay";
+               };
+
+               watchdog {
+                       compatible = "st,stpmic1-wdt";
+                       status = "disabled";
+               };
+       };
+};
+
+&ipcc {
+       status = "okay";
+};
+
+&iwdg2 {
+       timeout-sec = <32>;
+       status = "okay";
+};
+
+&rng1 {
+       status = "okay";
+};
+
+&rtc {
+       status = "okay";
+};
+
+&sdmmc1 {
+       pinctrl-names = "default", "opendrain", "sleep";
+       pinctrl-0 = <&sdmmc1_b4_pins_a>;
+       pinctrl-1 = <&sdmmc1_b4_od_pins_a>;
+       pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;
+       broken-cd;
+       st,neg-edge;
+       bus-width = <4>;
+       vmmc-supply = <&v3v3>;
+       status = "okay";
+};
+
+&uart4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart4_pins_a>;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/stm32mp157c-dk2.dts b/arch/arm/boot/dts/stm32mp157c-dk2.dts
new file mode 100644 (file)
index 0000000..20ea601
--- /dev/null
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+
+/dts-v1/;
+
+#include "stm32mp157a-dk1.dts"
+
+/ {
+       model = "STMicroelectronics STM32MP157C-DK2 Discovery Board";
+       compatible = "st,stm32mp157c-dk2", "st,stm32mp157";
+
+       reg18: reg18 {
+               compatible = "regulator-fixed";
+               regulator-name = "reg18";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-always-on;
+       };
+};
+
+&dsi {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       status = "okay";
+       phy-dsi-supply = <&reg18>;
+
+       ports {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               port@0 {
+                       reg = <0>;
+                       dsi_in: endpoint {
+                               remote-endpoint = <&ltdc_ep1_out>;
+                       };
+               };
+
+               port@1 {
+                       reg = <1>;
+                       dsi_out: endpoint {
+                               remote-endpoint = <&panel_in>;
+                       };
+               };
+       };
+
+       panel@0 {
+               compatible = "orisetech,otm8009a";
+               reg = <0>;
+               reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>;
+               power-supply = <&v3v3>;
+               status = "okay";
+
+               port {
+                       panel_in: endpoint {
+                               remote-endpoint = <&dsi_out>;
+                       };
+               };
+       };
+};
+
+&ltdc {
+       status = "okay";
+
+       port {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               ltdc_ep1_out: endpoint@1 {
+                       reg = <1>;
+                       remote-endpoint = <&dsi_in>;
+               };
+       };
+};
index d66edb0..62a8c78 100644 (file)
@@ -7,6 +7,8 @@
 
 #include "stm32mp157c.dtsi"
 #include "stm32mp157-pinctrl.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
 
 / {
        model = "STMicroelectronics STM32MP157C eval daughter";
                regulator-always-on;
        };
 
-       vdd_usb: vdd-usb {
-               compatible = "regulator-fixed";
-               regulator-name = "vdd_usb";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
+       sd_switch: regulator-sd_switch {
+               compatible = "regulator-gpio";
+               regulator-name = "sd_switch";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <2900000>;
+               regulator-type = "voltage";
                regulator-always-on;
+
+               gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>;
+               gpios-states = <0>;
+               states = <1800000 0x1 2900000 0x0>;
        };
 };
 
        i2c-scl-rising-time-ns = <185>;
        i2c-scl-falling-time-ns = <20>;
        status = "okay";
+       /* spare dmas for other usage */
+       /delete-property/dmas;
+       /delete-property/dma-names;
+
+       pmic: stpmic@33 {
+               compatible = "st,stpmic1";
+               reg = <0x33>;
+               interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               status = "okay";
+
+               regulators {
+                       compatible = "st,stpmic1-regulators";
+                       ldo1-supply = <&v3v3>;
+                       ldo2-supply = <&v3v3>;
+                       ldo3-supply = <&vdd_ddr>;
+                       ldo5-supply = <&v3v3>;
+                       ldo6-supply = <&v3v3>;
+                       pwr_sw1-supply = <&bst_out>;
+                       pwr_sw2-supply = <&bst_out>;
+
+                       vddcore: buck1 {
+                               regulator-name = "vddcore";
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-initial-mode = <0>;
+                               regulator-over-current-protection;
+                       };
+
+                       vdd_ddr: buck2 {
+                               regulator-name = "vdd_ddr";
+                               regulator-min-microvolt = <1350000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-initial-mode = <0>;
+                               regulator-over-current-protection;
+                       };
+
+                       vdd: buck3 {
+                               regulator-name = "vdd";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                               st,mask-reset;
+                               regulator-initial-mode = <0>;
+                               regulator-over-current-protection;
+                       };
+
+                       v3v3: buck4 {
+                               regulator-name = "v3v3";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                               regulator-over-current-protection;
+                               regulator-initial-mode = <0>;
+                       };
+
+                       vdda: ldo1 {
+                               regulator-name = "vdda";
+                               regulator-min-microvolt = <2900000>;
+                               regulator-max-microvolt = <2900000>;
+                               interrupts = <IT_CURLIM_LDO1 0>;
+                       };
+
+                       v2v8: ldo2 {
+                               regulator-name = "v2v8";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                               interrupts = <IT_CURLIM_LDO2 0>;
+                       };
+
+                       vtt_ddr: ldo3 {
+                               regulator-name = "vtt_ddr";
+                               regulator-min-microvolt = <500000>;
+                               regulator-max-microvolt = <750000>;
+                               regulator-always-on;
+                               regulator-over-current-protection;
+                       };
+
+                       vdd_usb: ldo4 {
+                               regulator-name = "vdd_usb";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               interrupts = <IT_CURLIM_LDO4 0>;
+                       };
+
+                       vdd_sd: ldo5 {
+                               regulator-name = "vdd_sd";
+                               regulator-min-microvolt = <2900000>;
+                               regulator-max-microvolt = <2900000>;
+                               interrupts = <IT_CURLIM_LDO5 0>;
+                               regulator-boot-on;
+                       };
+
+                       v1v8: ldo6 {
+                               regulator-name = "v1v8";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               interrupts = <IT_CURLIM_LDO6 0>;
+                       };
+
+                       vref_ddr: vref_ddr {
+                               regulator-name = "vref_ddr";
+                               regulator-always-on;
+                               regulator-over-current-protection;
+                       };
+
+                       bst_out: boost {
+                               regulator-name = "bst_out";
+                               interrupts = <IT_OCP_BOOST 0>;
+                       };
+
+                       vbus_otg: pwr_sw1 {
+                               regulator-name = "vbus_otg";
+                               interrupts = <IT_OCP_OTG 0>;
+                        };
+
+                        vbus_sw: pwr_sw2 {
+                               regulator-name = "vbus_sw";
+                               interrupts = <IT_OCP_SWOUT 0>;
+                               regulator-active-discharge;
+                        };
+               };
+
+               onkey {
+                       compatible = "st,stpmic1-onkey";
+                       interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 0>;
+                       interrupt-names = "onkey-falling", "onkey-rising";
+                       power-off-time-sec = <10>;
+                       status = "okay";
+               };
+
+               watchdog {
+                       compatible = "st,stpmic1-wdt";
+                       status = "disabled";
+               };
+       };
+};
+
+&ipcc {
+       status = "okay";
 };
 
 &iwdg2 {
        status = "okay";
 };
 
+&sdmmc1 {
+       pinctrl-names = "default", "opendrain", "sleep";
+       pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
+       pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>;
+       pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>;
+       broken-cd;
+       st,sig-dir;
+       st,neg-edge;
+       st,use-ckin;
+       bus-width = <4>;
+       vmmc-supply = <&vdd_sd>;
+       vqmmc-supply = <&sd_switch>;
+       status = "okay";
+};
+
 &timers6 {
        status = "okay";
        /* spare dmas for other usage */
index f8bbfff..2afeee6 100644 (file)
                        status = "disabled";
                };
 
+               spdifrx: audio-controller@4000d000 {
+                       compatible = "st,stm32h7-spdifrx";
+                       #sound-dai-cells = <0>;
+                       reg = <0x4000d000 0x400>;
+                       clocks = <&rcc SPDIF_K>;
+                       clock-names = "kclk";
+                       interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+                       dmas = <&dmamux1 93 0x400 0x01>,
+                              <&dmamux1 94 0x400 0x01>;
+                       dma-names = "rx", "rx-ctrl";
+                       status = "disabled";
+               };
+
                usart2: serial@4000e000 {
                        compatible = "st,stm32h7-uart";
                        reg = <0x4000e000 0x400>;
                        status = "disabled";
                };
 
+               ipcc: mailbox@4c001000 {
+                       compatible = "st,stm32mp1-ipcc";
+                       #mbox-cells = <1>;
+                       reg = <0x4c001000 0x400>;
+                       st,proc-id = <0>;
+                       interrupts-extended =
+                               <&intc GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+                               <&intc GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+                               <&exti 61 1>;
+                       interrupt-names = "rx", "tx", "wakeup";
+                       clocks = <&rcc IPCC>;
+                       wakeup-source;
+                       status = "disabled";
+               };
+
                rcc: rcc@50000000 {
                        compatible = "st,stm32mp1-rcc", "syscon";
                        reg = <0x50000000 0x1000>;
                syscfg: syscon@50020000 {
                        compatible = "st,stm32mp157-syscfg", "syscon";
                        reg = <0x50020000 0x400>;
+                       clocks = <&rcc SYSCFG>;
                };
 
                lptimer2: timer@50021000 {
                        status = "disabled";
                };
 
+               sdmmc1: sdmmc@58005000 {
+                       compatible = "arm,pl18x", "arm,primecell";
+                       arm,primecell-periphid = <0x10153180>;
+                       reg = <0x58005000 0x1000>;
+                       interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "cmd_irq";
+                       clocks = <&rcc SDMMC1_K>;
+                       clock-names = "apb_pclk";
+                       resets = <&rcc SDMMC1_R>;
+                       cap-sd-highspeed;
+                       cap-mmc-highspeed;
+                       max-frequency = <120000000>;
+               };
+
                crc1: crc@58009000 {
                        compatible = "st,stm32f7-crc";
                        reg = <0x58009000 0x400>;
                        status = "disabled";
                };
 
+               bsec: nvmem@5c005000 {
+                       compatible = "st,stm32mp15-bsec";
+                       reg = <0x5c005000 0x400>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ts_cal1: calib@5c {
+                               reg = <0x5c 0x2>;
+                       };
+                       ts_cal2: calib@5e {
+                               reg = <0x5e 0x2>;
+                       };
+               };
+
                i2c6: i2c@5c009000 {
                        compatible = "st,stm32f7-i2c";
                        reg = <0x5c009000 0x400>;
index cf7b392..7426298 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PH5";
-               function = "gpio_in";
-               bias-pull-down;
-       };
-};
-
 &reg_usb0_vbus {
        status = "okay";
 };
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
-       usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
+       usb0_vbus_det-gpios = <&pio 7 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PH5 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
        status = "okay";
index 197a1f2..7306c65 100644 (file)
                function = "gpio_out";
                drive-strength = <20>;
        };
-
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
 };
 
 &reg_ahci_5v {
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
        usb1_vbus-supply = <&reg_usb1_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
        status = "okay";
index 896e27a..8ee3ff4 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PH5";
-               function = "gpio_in";
-               bias-pull-down;
-       };
-};
-
 &pwm {
        pinctrl-names = "default";
        pinctrl-0 = <&pwm0_pin>;
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
-       usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
+       usb0_vbus_det-gpios = <&pio 7 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PH5 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
        status = "okay";
index f63767c..bf2044b 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PH5";
-               function = "gpio_in";
-               bias-pull-down;
-       };
-};
-
 &reg_usb0_vbus {
        status = "okay";
 };
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
-       usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
+       usb0_vbus_det-gpios = <&pio 7 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PH5 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
        status = "okay";
index 26d0c1d..ca87838 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PH5";
-               function = "gpio_in";
-               bias-pull-down;
-       };
-};
-
 &pwm {
        pinctrl-names = "default";
        pinctrl-0 = <&pwm0_pin>;
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
-       usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
+       usb0_vbus_det-gpios = <&pio 7 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PH5 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
index 71c27ea..76016f2 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PH5";
-               function = "gpio_in";
-               bias-pull-down;
-       };
-};
-
 &reg_dcdc2 {
        regulator-always-on;
        regulator-min-microvolt = <1000000>;
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
-       usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
+       usb0_vbus_det-gpios = <&pio 7 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PH5 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
        status = "okay";
index 2f0d966..0a562b2 100644 (file)
@@ -61,8 +61,6 @@
 
        gpio-keys {
                compatible = "gpio-keys-polled";
-               pinctrl-names = "default";
-               pinctrl-0 = <&key_pins_inet9f>;
                poll-interval = <20>;
 
                left-joystick-left {
@@ -70,7 +68,7 @@
                        linux,code = <ABS_X>;
                        linux,input-type = <EV_ABS>;
                        linux,input-value = <0xffffffff>; /* -1 */
-                       gpios = <&pio 0 6 GPIO_ACTIVE_LOW>; /* PA6 */
+                       gpios = <&pio 0 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA6 */
                };
 
                left-joystick-right {
@@ -78,7 +76,7 @@
                        linux,code = <ABS_X>;
                        linux,input-type = <EV_ABS>;
                        linux,input-value = <1>;
-                       gpios = <&pio 0 5 GPIO_ACTIVE_LOW>; /* PA5 */
+                       gpios = <&pio 0 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA5 */
                };
 
                left-joystick-up {
@@ -86,7 +84,7 @@
                        linux,code = <ABS_Y>;
                        linux,input-type = <EV_ABS>;
                        linux,input-value = <0xffffffff>; /* -1 */
-                       gpios = <&pio 0 8 GPIO_ACTIVE_LOW>; /* PA8 */
+                       gpios = <&pio 0 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA8 */
                };
 
                left-joystick-down {
@@ -94,7 +92,7 @@
                        linux,code = <ABS_Y>;
                        linux,input-type = <EV_ABS>;
                        linux,input-value = <1>;
-                       gpios = <&pio 0 9 GPIO_ACTIVE_LOW>; /* PA9 */
+                       gpios = <&pio 0 9 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA9 */
                };
 
                right-joystick-left {
                        linux,code = <ABS_Z>;
                        linux,input-type = <EV_ABS>;
                        linux,input-value = <0xffffffff>; /* -1 */
-                       gpios = <&pio 0 1 GPIO_ACTIVE_LOW>; /* PA1 */
+                       gpios = <&pio 0 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA1 */
                };
 
                right-joystick-right {
                        linux,code = <ABS_Z>;
                        linux,input-type = <EV_ABS>;
                        linux,input-value = <1>;
-                       gpios = <&pio 0 0 GPIO_ACTIVE_LOW>; /* PA0 */
+                       gpios = <&pio 0 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA0 */
                };
 
                right-joystick-up {
                        linux,code = <ABS_RZ>;
                        linux,input-type = <EV_ABS>;
                        linux,input-value = <0xffffffff>; /* -1 */
-                       gpios = <&pio 0 3 GPIO_ACTIVE_LOW>; /* PA3 */
+                       gpios = <&pio 0 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA3 */
                };
 
                right-joystick-down {
                        linux,code = <ABS_RZ>;
                        linux,input-type = <EV_ABS>;
                        linux,input-value = <1>;
-                       gpios = <&pio 0 4 GPIO_ACTIVE_LOW>; /* PA4 */
+                       gpios = <&pio 0 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA4 */
                };
 
                dpad-left {
                        linux,code = <ABS_HAT0X>;
                        linux,input-type = <EV_ABS>;
                        linux,input-value = <0xffffffff>; /* -1 */
-                       gpios = <&pio 7 23 GPIO_ACTIVE_LOW>; /* PH23 */
+                       gpios = <&pio 7 23 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PH23 */
                };
 
                dpad-right {
                        linux,code = <ABS_HAT0X>;
                        linux,input-type = <EV_ABS>;
                        linux,input-value = <1>;
-                       gpios = <&pio 7 24 GPIO_ACTIVE_LOW>; /* PH24 */
+                       gpios = <&pio 7 24 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PH24 */
                };
 
                dpad-up {
                        linux,code = <ABS_HAT0Y>;
                        linux,input-type = <EV_ABS>;
                        linux,input-value = <0xffffffff>; /* -1 */
-                       gpios = <&pio 7 25 GPIO_ACTIVE_LOW>; /* PH25 */
+                       gpios = <&pio 7 25 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PH25 */
                };
 
                dpad-down {
                        linux,code = <ABS_HAT0Y>;
                        linux,input-type = <EV_ABS>;
                        linux,input-value = <1>;
-                       gpios = <&pio 7 26 GPIO_ACTIVE_LOW>; /* PH26 */
+                       gpios = <&pio 7 26 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PH26 */
                };
 
                x {
                        label = "Button X";
                        linux,code = <BTN_X>;
-                       gpios = <&pio 0 16 GPIO_ACTIVE_LOW>; /* PA16 */
+                       gpios = <&pio 0 16 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA16 */
                };
 
                y {
                        label = "Button Y";
                        linux,code = <BTN_Y>;
-                       gpios = <&pio 0 14 GPIO_ACTIVE_LOW>; /* PA14 */
+                       gpios = <&pio 0 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA14 */
                };
 
                a {
                        label = "Button A";
                        linux,code = <BTN_A>;
-                       gpios = <&pio 0 17 GPIO_ACTIVE_LOW>; /* PA17 */
+                       gpios = <&pio 0 17 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA17 */
                };
 
                b {
                        label = "Button B";
                        linux,code = <BTN_B>;
-                       gpios = <&pio 0 15 GPIO_ACTIVE_LOW>; /* PA15 */
+                       gpios = <&pio 0 15 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA15 */
                };
 
                select {
                        label = "Select Button";
                        linux,code = <BTN_SELECT>;
-                       gpios = <&pio 0 11 GPIO_ACTIVE_LOW>; /* PA11 */
+                       gpios = <&pio 0 11 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA11 */
                };
 
                start {
                        label = "Start Button";
                        linux,code = <BTN_START>;
-                       gpios = <&pio 0 12 GPIO_ACTIVE_LOW>; /* PA12 */
+                       gpios = <&pio 0 12 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA12 */
                };
 
                top-left {
                        label = "Top Left Button";
                        linux,code = <BTN_TL>;
-                       gpios = <&pio 7 22 GPIO_ACTIVE_LOW>; /* PH22 */
+                       gpios = <&pio 7 22 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PH22 */
                };
 
                top-right {
                        label = "Top Right Button";
                        linux,code = <BTN_TR>;
-                       gpios = <&pio 0 13 GPIO_ACTIVE_LOW>; /* PA13 */
+                       gpios = <&pio 0 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PA13 */
                };
        };
 };
        status = "okay";
 };
 
-&pio {
-       key_pins_inet9f: key-pins {
-               pins = "PA0", "PA1", "PA3", "PA4",
-                      "PA5", "PA6", "PA8", "PA9",
-                      "PA11", "PA12", "PA13",
-                      "PA14", "PA15", "PA16", "PA17",
-                      "PH22", "PH23", "PH24", "PH25", "PH26";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PH5";
-               function = "gpio_in";
-               bias-pull-down;
-       };
-};
-
 &reg_dcdc2 {
        regulator-always-on;
        regulator-min-microvolt = <1000000>;
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
-       usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
+       usb0_vbus_det-gpios = <&pio 7 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PH5 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
        status = "okay";
index 0dbf695..58ad2ad 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &reg_usb1_vbus {
        status = "okay";
 };
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
        usb1_vbus-supply = <&reg_usb1_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
        status = "okay";
index b74a614..a8e537f 100644 (file)
                function = "gpio_out";
                drive-strength = <20>;
        };
-
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PH5";
-               function = "gpio_in";
-               bias-pull-down;
-       };
 };
 
 &reg_ahci_5v {
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio   = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
-       usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
+       usb0_vbus_det-gpios = <&pio 7 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH5 */
        usb0_vbus-supply   = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
index d82a604..0f1e781 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 #include "axp209.dtsi"
 
 &reg_dcdc2 {
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
        usb1_vbus-supply = <&reg_vcc5v0>; /* USB1 VBUS is always on */
        usb2_vbus-supply = <&reg_vcc5v0>; /* USB2 VBUS is always on */
        status = "okay";
index 84b25be..24a3d23 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PH5";
-               function = "gpio_in";
-               bias-pull-down;
-       };
-};
-
 &pwm {
        pinctrl-names = "default";
        pinctrl-0 = <&pwm0_pin>;
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
-       usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
+       usb0_vbus_det-gpios = <&pio 7 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PH5 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
        status = "okay";
index 73c3ac4..e88daa4 100644 (file)
                        #dma-cells = <2>;
                };
 
-               nfc: nand@1c03000 {
+               nfc: nand-controller@1c03000 {
                        compatible = "allwinner,sun4i-a10-nand";
                        reg = <0x01c03000 0x1000>;
                        interrupts = <37>;
                                      "tcon-ch0",
                                      "tcon-ch1";
                        clock-output-names = "tcon0-pixel-clock";
+                       #clock-cells = <0>;
                        dmas = <&dma SUN4I_DMA_DEDICATED 14>;
 
                        ports {
                                      "tcon-ch0",
                                      "tcon-ch1";
                        clock-output-names = "tcon1-pixel-clock";
+                       #clock-cells = <0>;
                        dmas = <&dma SUN4I_DMA_DEDICATED 15>;
 
                        ports {
                        phy-names = "usb";
                        extcon = <&usbphy 0>;
                        allwinner,sram = <&otg_sram 1>;
+                       dr_mode = "otg";
                        status = "disabled";
                };
 
                usbphy: phy@1c13400 {
                        #phy-cells = <1>;
                        compatible = "allwinner,sun4i-a10-usb-phy";
-                       reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>;
+                       reg = <0x01c13400 0x10>, <0x01c14800 0x4>, <0x01c1c800 0x4>;
                        reg-names = "phy_ctrl", "pmu1", "pmu2";
                        clocks = <&ccu CLK_USB_PHY>;
                        clock-names = "usb_phy";
                        interrupts = <39>;
                        clocks = <&ccu CLK_AHB_EHCI0>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        interrupts = <64>;
                        clocks = <&ccu CLK_USB_OHCI0>, <&ccu CLK_AHB_OHCI0>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        interrupts = <40>;
                        clocks = <&ccu CLK_AHB_EHCI1>;
                        phys = <&usbphy 2>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        interrupts = <65>;
                        clocks = <&ccu CLK_USB_OHCI1>, <&ccu CLK_AHB_OHCI1>;
                        phys = <&usbphy 2>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
index c88f089..8af0eae 100644 (file)
 };
 
 &pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PG12";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
        led_pins_t004: led-pin {
                pins = "PB2";
                function = "gpio_out";
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */
+       usb0_id_det-gpios = <&pio 6 12 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PG12 */
        usb1_vbus-supply = <&reg_usb1_vbus>;
        status = "okay";
 };
index 262c2ff..5340b41 100644 (file)
                function = "gpio_out";
                drive-strength = <20>;
        };
-
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PG12";
-               function = "gpio_in";
-               bias-pull-up;
-       };
 };
 
 &reg_usb0_vbus {
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */
+       usb0_id_det-gpios = <&pio 6 12 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PG12 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
        status = "okay";
index f3cede9..a23bf24 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PG1";
-               function = "gpio_in";
-               bias-pull-down;
-       };
-
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PG2";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &pwm {
        pinctrl-names = "default";
        pinctrl-0 = <&pwm0_pin>;
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
-       usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */
+       usb0_id_det-gpios = <&pio 6 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PG2 */
+       usb0_vbus_det-gpios = <&pio 6 1 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PG1 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_ldo3>;
        status = "okay";
index 9369f74..9b9f2a5 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PG2";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 #include "axp209.dtsi"
 
 &reg_dcdc2 {
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpios = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
+       usb0_id_det-gpios = <&pio 6 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PG2 */
        usb0_vbus_det-gpios = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_ldo3>;
index ca8f3fd..ba8d75b 100644 (file)
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
-       usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */
+       usb0_id_det-gpios = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
+       usb0_vbus_det-gpios = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_vcc5v0>;
        status = "okay";
index 943868e..5df398d 100644 (file)
                function = "gpio_out";
                drive-strength = <20>;
        };
-
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PG2";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PG1";
-               function = "gpio_in";
-               bias-pull-down;
-       };
 };
 
 &reg_usb0_vbus {
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
-       usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */
+       usb0_id_det-gpios = <&pio 6 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PG2 */
+       usb0_vbus_det-gpios = <&pio 6 1 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PG1 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
        status = "okay";
index 9409c23..3910122 100644 (file)
@@ -74,8 +74,6 @@
 
        bridge {
                compatible = "dumb-vga-dac";
-               #address-cells = <1>;
-               #size-cells = <0>;
 
                ports {
                        #address-cells = <1>;
                function = "gpio_out";
                drive-strength = <20>;
        };
-
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PG2";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PG1";
-               function = "gpio_in";
-               bias-pull-down;
-       };
 };
 
 &reg_usb0_vbus {
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
-       usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */
+       usb0_id_det-gpios = <&pio 6 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PG2 */
+       usb0_vbus_det-gpios = <&pio 6 1 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PG1 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
        status = "okay";
index 7257f39..fde559a 100644 (file)
                power-supply = <&reg_vcc3v3>;
                enable-gpios = <&axp_gpio 0 GPIO_ACTIVE_HIGH>; /* AXP GPIO0 */
                backlight = <&backlight>;
-               #address-cells = <1>;
-               #size-cells = <0>;
 
-               port@0 {
-                       reg = <0>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
-                       panel_input: endpoint@0 {
-                               reg = <0>;
+               port {
+                       panel_input: endpoint {
                                remote-endpoint = <&tcon0_out_lcd>;
                        };
                };
index 732873c..be486d2 100644 (file)
                /delete-property/stdout-path;
        };
 
-       i2c_lcd: i2c-gpio {
+       i2c_lcd: i2c {
                /* The lcd panel i2c interface is hooked up via gpios */
                compatible = "i2c-gpio";
-               pinctrl-names = "default";
-               pinctrl-0 = <&i2c_lcd_pins>;
-               gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>, /* PG12, sda */
-                       <&pio 6 10 GPIO_ACTIVE_HIGH>; /* PG10, scl */
+               sda-gpios = <&pio 6 12 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PG12 */
+               scl-gpios = <&pio 6 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PG10 */
                i2c-gpio,delay-us = <5>;
        };
 };
        };
 };
 
-&pio {
-       i2c_lcd_pins: i2c-lcd-pin {
-               pins = "PG10", "PG12";
-               function = "gpio_out";
-               bias-pull-up;
-       };
-};
-
 &reg_usb0_vbus {
        gpio = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */
 };
index 3f70b8c..a32cde3 100644 (file)
        status = "okay";
 
        nand@0 {
-               #address-cells = <2>;
-               #size-cells = <2>;
                reg = <0>;
                allwinner,rb = <0>;
                nand-ecc-mode = "hw";
 };
 
 &usbphy {
-       usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
+       usb0_id_det-gpios = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb1_vbus-supply = <&reg_vcc5v0>;
        status = "okay";
index 86e46aa..d003b89 100644 (file)
 };
 
 &usbphy {
-       usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
-       usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */
+       usb0_id_det-gpios = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
+       usb0_vbus_det-gpios = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
        status = "okay";
index f4298fa..4bf4943 100644 (file)
@@ -84,9 +84,7 @@
 
        onewire {
                compatible = "w1-gpio";
-               gpios = <&pio 3 2 GPIO_ACTIVE_HIGH>; /* PD2 */
-               pinctrl-names = "default";
-               pinctrl-0 = <&chip_w1_pin>;
+               gpios = <&pio 3 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PD2 */
        };
 };
 
        status = "okay";
 };
 
-&pio {
-       chip_w1_pin: chip-w1-pin {
-               pins = "PD2";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &reg_dcdc2 {
        regulator-min-microvolt = <1000000>;
        regulator-max-microvolt = <1400000>;
 &usbphy {
        status = "okay";
 
-       usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
+       usb0_id_det-gpios = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_vcc5v0>;
index 5b1f0e1..1a9926d 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PG1";
-               function = "gpio_in";
-               bias-pull-down;
-       };
-
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PG2";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &reg_dcdc2 {
        regulator-always-on;
        regulator-min-microvolt = <1000000>;
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
-       usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */
+       usb0_id_det-gpios = <&pio 6 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PG2 */
+       usb0_vbus_det-gpios = <&pio 6 1 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PG1 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_ldo3>;
index 5497d98..2fb438c 100644 (file)
                compatible = "simple-bus";
                #address-cells = <1>;
                #size-cells = <1>;
+               dma-ranges;
                ranges;
 
                system-control@1c00000 {
                        };
                };
 
+               mbus: dram-controller@1c01000 {
+                       compatible = "allwinner,sun5i-a13-mbus";
+                       reg = <0x01c01000 0x1000>;
+                       clocks = <&ccu 99>;
+                       dma-ranges = <0x00000000 0x40000000 0x20000000>;
+                       #interconnect-cells = <1>;
+               };
+
                dma: dma-controller@1c02000 {
                        compatible = "allwinner,sun4i-a10-dma";
                        reg = <0x01c02000 0x1000>;
                        #dma-cells = <2>;
                };
 
-               nfc: nand@1c03000 {
+               nfc: nand-controller@1c03000 {
                        compatible = "allwinner,sun4i-a10-nand";
                        reg = <0x01c03000 0x1000>;
                        interrupts = <37>;
                        status = "disabled";
 
                        port {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
 
-                               tve0_in_tcon0: endpoint@0 {
-                                       reg = <0>;
+                               tve0_in_tcon0: endpoint {
                                        remote-endpoint = <&tcon0_out_tve0>;
                                };
                        };
                                      "tcon-ch0",
                                      "tcon-ch1";
                        clock-output-names = "tcon-pixel-clock";
+                       #clock-cells = <0>;
                        status = "disabled";
 
                        ports {
                                #size-cells = <0>;
 
                                tcon0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       tcon0_in_be0: endpoint@0 {
-                                               reg = <0>;
+                                       tcon0_in_be0: endpoint {
                                                remote-endpoint = <&be0_out_tcon0>;
                                        };
                                };
                        phy-names = "usb";
                        extcon = <&usbphy 0>;
                        allwinner,sram = <&otg_sram 1>;
+                       dr_mode = "otg";
                        status = "disabled";
                };
 
                usbphy: phy@1c13400 {
                        #phy-cells = <1>;
                        compatible = "allwinner,sun5i-a13-usb-phy";
-                       reg = <0x01c13400 0x10 0x01c14800 0x4>;
+                       reg = <0x01c13400 0x10>, <0x01c14800 0x4>;
                        reg-names = "phy_ctrl", "pmu1";
                        clocks = <&ccu CLK_USB_PHY0>;
                        clock-names = "usb_phy";
                        interrupts = <39>;
                        clocks = <&ccu CLK_AHB_EHCI>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        interrupts = <40>;
                        clocks = <&ccu CLK_USB_OHCI>, <&ccu CLK_AHB_OHCI>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                                bias-pull-up;
                        };
 
-                       mmc2_8bit_pins: mmc2-8bit-pins {
+                       mmc2_4bit_pc_pins: mmc2-4bit-pc-pins {
                                pins = "PC6", "PC7", "PC8", "PC9",
-                                      "PC10", "PC11", "PC12", "PC13",
-                                      "PC14", "PC15";
+                                      "PC10", "PC11";
                                function = "mmc2";
                                drive-strength = <30>;
                                bias-pull-up;
                        };
 
-                       mmc2_4bit_pc_pins: mmc2-4bit-pc-pins {
+                       mmc2_8bit_pins: mmc2-8bit-pins {
                                pins = "PC6", "PC7", "PC8", "PC9",
-                                      "PC10", "PC11";
+                                      "PC10", "PC11", "PC12", "PC13",
+                                      "PC14", "PC15";
                                function = "mmc2";
                                drive-strength = <30>;
                                bias-pull-up;
                                function = "nand0";
                        };
 
+                       pwm0_pin: pwm0-pin {
+                               pins = "PB2";
+                               function = "pwm";
+                       };
+
                        spi2_pe_pins: spi2-pe-pins {
                                pins = "PE1", "PE2", "PE3";
                                function = "spi2";
                                pins = "PG11", "PG12";
                                function = "uart3";
                        };
-
-                       pwm0_pin: pwm0-pin {
-                               pins = "PB2";
-                               function = "pwm";
-                       };
                };
 
                timer@1c20c00 {
                        clock-names = "ahb", "mod",
                                      "ram";
                        resets = <&ccu RST_DE_FE>;
+                       interconnects = <&mbus 19>;
+                       interconnect-names = "dma-mem";
                        status = "disabled";
 
                        ports {
                                #size-cells = <0>;
 
                                fe0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       fe0_out_be0: endpoint@0 {
-                                               reg = <0>;
+                                       fe0_out_be0: endpoint {
                                                remote-endpoint = <&be0_in_fe0>;
                                        };
                                };
                        clock-names = "ahb", "mod",
                                      "ram";
                        resets = <&ccu RST_DE_BE>;
+                       interconnects = <&mbus 18>;
+                       interconnect-names = "dma-mem";
                        status = "disabled";
 
                        assigned-clocks = <&ccu CLK_DE_BE>;
                                #size-cells = <0>;
 
                                be0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       be0_in_fe0: endpoint@0 {
-                                               reg = <0>;
+                                       be0_in_fe0: endpoint {
                                                remote-endpoint = <&fe0_out_be0>;
                                        };
                                };
 
                                be0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       be0_out_tcon0: endpoint@0 {
-                                               reg = <0>;
+                                       be0_out_tcon0: endpoint {
                                                remote-endpoint = <&tcon0_in_be0>;
                                        };
                                };
index 0b7bedf..c3d56dc 100644 (file)
        i2c_lcd: i2c {
                /* The lcd panel i2c interface is hooked up via gpios */
                compatible = "i2c-gpio";
-               pinctrl-names = "default";
-               pinctrl-0 = <&i2c_lcd_pins>;
-               gpios = <&pio 0 23 GPIO_ACTIVE_HIGH>, /* PA23, sda */
-                       <&pio 0 24 GPIO_ACTIVE_HIGH>; /* PA24, scl */
+               sda-gpios = <&pio 0 23 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PA23 */
+               scl-gpios = <&pio 0 24 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PA24 */
                i2c-gpio,delay-us = <5>;
        };
 };
        status = "okay";
 };
 
-&pio {
-       i2c_lcd_pins: i2c-lcd-pins {
-               pins = "PA23", "PA24";
-               function = "gpio_out";
-               bias-pull-up;
-       };
-};
-
 &reg_usb2_vbus {
        gpio = <&pio 7 24 GPIO_ACTIVE_HIGH>;
        status = "okay";
index e17a65b..09832b4 100644 (file)
        vga-dac {
                compatible = "dumb-vga-dac";
                vdd-supply = <&reg_vga_3v3>;
-               #address-cells = <1>;
-               #size-cells = <0>;
 
                ports {
                        #address-cells = <1>;
                        #size-cells = <0>;
 
                        port@0 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
                                reg = <0>;
 
-                               vga_dac_in: endpoint@0 {
-                                       reg = <0>;
+                               vga_dac_in: endpoint {
                                        remote-endpoint = <&tcon0_out_vga>;
                                };
                        };
 
                        port@1 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
                                reg = <1>;
 
-                               vga_dac_out: endpoint@0 {
-                                       reg = <0>;
+                               vga_dac_out: endpoint {
                                        remote-endpoint = <&vga_con_in>;
                                };
                        };
 };
 
 &usbphy {
-       usb0_id_det-gpio = <&pio 0 15 GPIO_ACTIVE_HIGH>; /* PA15 */
-       usb0_vbus_det-gpio = <&pio 0 16 GPIO_ACTIVE_HIGH>; /* PA16 */
+       usb0_id_det-gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>; /* PA15 */
+       usb0_vbus_det-gpios = <&pio 0 16 GPIO_ACTIVE_HIGH>; /* PA16 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb0_vbus-supply = <&reg_drivevbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
index 0832ac5..091eb2a 100644 (file)
 &spdif {
        pinctrl-names = "default";
        pinctrl-0 = <&spdif_tx_pin>;
-       spdif-out = "okay";
        status = "okay";
 };
 
index 13304b8..c04efad 100644 (file)
                                      "tcon-ch0",
                                      "tcon-ch1";
                        clock-output-names = "tcon0-pixel-clock";
+                       #clock-cells = <0>;
 
                        ports {
                                #address-cells = <1>;
                                      "tcon-ch0",
                                      "tcon-ch1";
                        clock-output-names = "tcon1-pixel-clock";
+                       #clock-cells = <0>;
 
                        ports {
                                #address-cells = <1>;
                                };
 
                                hdmi_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
                                };
                        };
                        phys = <&usbphy 0>;
                        phy-names = "usb";
                        extcon = <&usbphy 0>;
+                       dr_mode = "otg";
                        status = "disabled";
                };
 
                        clocks = <&ccu CLK_AHB1_EHCI0>;
                        resets = <&ccu RST_AHB1_EHCI0>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        clocks = <&ccu CLK_AHB1_OHCI0>, <&ccu CLK_USB_OHCI0>;
                        resets = <&ccu RST_AHB1_OHCI0>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        clocks = <&ccu CLK_AHB1_EHCI1>;
                        resets = <&ccu RST_AHB1_EHCI1>;
                        phys = <&usbphy 2>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        clocks = <&ccu CLK_AHB1_OHCI1>, <&ccu CLK_USB_OHCI1>;
                        resets = <&ccu RST_AHB1_OHCI1>;
                        phys = <&usbphy 2>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                };
 
                gic: interrupt-controller@1c81000 {
-                       compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
+                       compatible = "arm,gic-400";
                        reg = <0x01c81000 0x1000>,
                              <0x01c82000 0x2000>,
                              <0x01c84000 0x2000>,
                                };
 
                                be0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       be0_out_drc0: endpoint@0 {
-                                               reg = <0>;
+                                       be0_out_drc0: endpoint {
                                                remote-endpoint = <&drc0_in_be0>;
                                        };
                                };
                                #size-cells = <0>;
 
                                drc0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       drc0_in_be0: endpoint@0 {
-                                               reg = <0>;
+                                       drc0_in_be0: endpoint {
                                                remote-endpoint = <&be0_out_drc0>;
                                        };
                                };
                        gpio-controller;
                        interrupt-controller;
                        #interrupt-cells = <3>;
-                       #size-cells = <0>;
                        #gpio-cells = <3>;
 
                        s_ir_rx_pin: s-ir-rx-pin {
index 60b355f..bc3170a 100644 (file)
 };
 
 &usbphy {
-       usb0_id_det-gpio = <&pio 0 15 GPIO_ACTIVE_HIGH>; /* PA15 */
+       usb0_id_det-gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>; /* PA15 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb0_vbus-supply = <&reg_drivevbus>;
        usb1_vbus-supply = <&reg_dldo1>;
index 86143de..7de2abd 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PA15";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &p2wi {
        status = "okay";
 
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 0 15 GPIO_ACTIVE_HIGH>; /* PA15 */
+       usb0_id_det-gpios = <&pio 0 15 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PA15 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb0_vbus-supply = <&reg_drivevbus>;
        usb1_vbus-supply = <&reg_dldo1>;
index 81bc85d..4df9216 100644 (file)
                        "SPI-MISO", "SPI-CE1", "",
                "IO-6", "IO-3", "IO-2", "IO-0", "", "", "", "",
                "", "", "", "", "", "", "", "";
-
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
 };
 
 #include "axp209.dtsi"
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
index 200685b..08e5a5a 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &reg_ahci_5v {
        status = "okay";
 };
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
        usb1_vbus-supply = <&reg_usb1_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
        status = "okay";
index f91e1be..3e170cf 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 #include "axp209.dtsi"
 
 &ac_power_supply {
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
index 823aabc..c34a83f 100644 (file)
 };
 
 &usbphy {
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
-       usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+       usb0_id_det-gpios = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+       usb0_vbus_det-gpios = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
index 5e41119..e40dd47 100644 (file)
                function = "gpio_out";
                drive-strength = <20>;
        };
-
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PH5";
-               function = "gpio_in";
-               bias-pull-down;
-       };
 };
 
 &reg_ahci_5v {
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
-       usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
+       usb0_vbus_det-gpios = <&pio 7 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PH5 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
index 4e1c590..95c6f89 100644 (file)
 };
 
 &pio {
+       vcc-pa-supply = <&reg_vcc3v3>;
+       vcc-pc-supply = <&reg_vcc3v3>;
+       vcc-pe-supply = <&reg_ldo3>;
+       vcc-pf-supply = <&reg_vcc3v3>;
+       vcc-pg-supply = <&reg_ldo4>;
+
        led_pins_olinuxinolime: led-pins {
                pins = "PH2";
                function = "gpio_out";
                drive-strength = <20>;
        };
-
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PH5";
-               function = "gpio_in";
-               bias-pull-down;
-       };
 };
 
 &reg_ahci_5v {
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
-       usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
+       usb0_vbus_det-gpios = <&pio 7 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PH5 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
index 840ae11..0dcba07 100644 (file)
                function = "gpio_out";
                drive-strength = <20>;
        };
-
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-
-       usb0_vbus_detect_pin: usb0-vbus-detect-pin {
-               pins = "PH5";
-               function = "gpio_in";
-               bias-pull-down;
-       };
 };
 
 #include "axp209.dtsi"
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
-       usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
+       usb0_vbus_det-gpios = <&pio 7 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PH5 */
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
index 1588108..9628041 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &reg_dcdc2 {
        regulator-always-on;
        regulator-min-microvolt = <1000000>;
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
index d64de2e..7b35326 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &reg_dcdc2 {
        regulator-always-on;
        regulator-min-microvolt = <1000000>;
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
index 538ea15..173b676 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &reg_ahci_5v {
        gpio = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */
        status = "okay";
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
        usb1_vbus-supply = <&reg_usb1_vbus>;
        usb2_vbus-supply = <&reg_usb1_vbus>;
        status = "okay";
index a72ed43..14a88aa 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &reg_ahci_5v {
        gpio = <&pio 7 2 GPIO_ACTIVE_HIGH>;
        status = "okay";
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
        usb1_vbus-supply = <&reg_usb1_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
        status = "okay";
index ffade25..6a66b04 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &pwm {
        pinctrl-names = "default";
        pinctrl-0 = <&pwm0_pin>;
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
index c27e560..f8475a3 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH4";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &reg_dcdc2 {
        regulator-always-on;
        regulator-min-microvolt = <1000000>;
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+       usb0_id_det-gpios = <&pio 7 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH4 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb0_vbus-supply = <&reg_usb0_vbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
index 641a8fa..9ad8e44 100644 (file)
                        #dma-cells = <2>;
                };
 
-               nfc: nand@1c03000 {
+               nfc: nand-controller@1c03000 {
                        compatible = "allwinner,sun4i-a10-nand";
                        reg = <0x01c03000 0x1000>;
                        interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
                                      "tcon-ch0",
                                      "tcon-ch1";
                        clock-output-names = "tcon0-pixel-clock";
+                       #clock-cells = <0>;
                        dmas = <&dma SUN4I_DMA_DEDICATED 14>;
 
                        ports {
                                      "tcon-ch0",
                                      "tcon-ch1";
                        clock-output-names = "tcon1-pixel-clock";
+                       #clock-cells = <0>;
                        dmas = <&dma SUN4I_DMA_DEDICATED 15>;
 
                        ports {
                        phy-names = "usb";
                        extcon = <&usbphy 0>;
                        allwinner,sram = <&otg_sram 1>;
+                       dr_mode = "otg";
                        status = "disabled";
                };
 
                usbphy: phy@1c13400 {
                        #phy-cells = <1>;
                        compatible = "allwinner,sun7i-a20-usb-phy";
-                       reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>;
+                       reg = <0x01c13400 0x10>, <0x01c14800 0x4>, <0x01c1c800 0x4>;
                        reg-names = "phy_ctrl", "pmu1", "pmu2";
                        clocks = <&ccu CLK_USB_PHY>;
                        clock-names = "usb_phy";
                        interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&ccu CLK_AHB_EHCI0>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&ccu CLK_USB_OHCI0>, <&ccu CLK_AHB_OHCI0>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&ccu CLK_AHB_EHCI1>;
                        phys = <&usbphy 2>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&ccu CLK_USB_OHCI1>, <&ccu CLK_AHB_OHCI1>;
                        phys = <&usbphy 2>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        #interrupt-cells = <3>;
                        #gpio-cells = <3>;
 
+                       /omit-if-no-ref/
+                       can_pa_pins: can-pa-pins {
+                               pins = "PA16", "PA17";
+                               function = "can";
+                       };
+
+                       /omit-if-no-ref/
                        can_ph_pins: can-ph-pins {
                                pins = "PH20", "PH21";
                                function = "can";
                        };
 
+                       /omit-if-no-ref/
                        clk_out_a_pin: clk-out-a-pin {
                                pins = "PI12";
                                function = "clk_out_a";
                        };
 
+                       /omit-if-no-ref/
                        clk_out_b_pin: clk-out-b-pin {
                                pins = "PI13";
                                function = "clk_out_b";
                        };
 
+                       /omit-if-no-ref/
                        emac_pa_pins: emac-pa-pins {
                                pins = "PA0", "PA1", "PA2",
                                       "PA3", "PA4", "PA5", "PA6",
                                function = "emac";
                        };
 
+                       /omit-if-no-ref/
+                       emac_ph_pins: emac-ph-pins {
+                               pins = "PH8", "PH9", "PH10", "PH11",
+                                      "PH14", "PH15", "PH16", "PH17",
+                                      "PH18", "PH19", "PH20", "PH21",
+                                      "PH22", "PH23", "PH24", "PH25",
+                                      "PH26";
+                               function = "emac";
+                       };
+
+                       /omit-if-no-ref/
                        gmac_mii_pins: gmac-mii-pins {
                                pins = "PA0", "PA1", "PA2",
                                       "PA3", "PA4", "PA5", "PA6",
                                function = "gmac";
                        };
 
+                       /omit-if-no-ref/
                        gmac_rgmii_pins: gmac-rgmii-pins {
                                pins = "PA0", "PA1", "PA2",
                                       "PA3", "PA4", "PA5", "PA6",
                                drive-strength = <40>;
                        };
 
+                       /omit-if-no-ref/
                        i2c0_pins: i2c0-pins {
                                pins = "PB0", "PB1";
                                function = "i2c0";
                        };
 
+                       /omit-if-no-ref/
                        i2c1_pins: i2c1-pins {
                                pins = "PB18", "PB19";
                                function = "i2c1";
                        };
 
+                       /omit-if-no-ref/
                        i2c2_pins: i2c2-pins {
                                pins = "PB20", "PB21";
                                function = "i2c2";
                        };
 
+                       /omit-if-no-ref/
                        i2c3_pins: i2c3-pins {
                                pins = "PI0", "PI1";
                                function = "i2c3";
                        };
 
+                       /omit-if-no-ref/
                        ir0_rx_pin: ir0-rx-pin {
                                pins = "PB4";
                                function = "ir0";
                        };
 
+                       /omit-if-no-ref/
                        ir0_tx_pin: ir0-tx-pin {
                                pins = "PB3";
                                function = "ir0";
                        };
 
+                       /omit-if-no-ref/
                        ir1_rx_pin: ir1-rx-pin {
                                pins = "PB23";
                                function = "ir1";
                        };
 
+                       /omit-if-no-ref/
                        ir1_tx_pin: ir1-tx-pin {
                                pins = "PB22";
                                function = "ir1";
                        };
 
+                       /omit-if-no-ref/
                        mmc0_pins: mmc0-pins {
                                pins = "PF0", "PF1", "PF2",
                                       "PF3", "PF4", "PF5";
                                bias-pull-up;
                        };
 
+                       /omit-if-no-ref/
                        mmc2_pins: mmc2-pins {
                                pins = "PC6", "PC7", "PC8",
                                       "PC9", "PC10", "PC11";
                                bias-pull-up;
                        };
 
+                       /omit-if-no-ref/
                        mmc3_pins: mmc3-pins {
                                pins = "PI4", "PI5", "PI6",
                                       "PI7", "PI8", "PI9";
                                bias-pull-up;
                        };
 
+                       /omit-if-no-ref/
                        ps2_0_pins: ps2-0-pins {
                                pins = "PI20", "PI21";
                                function = "ps2";
                        };
 
+                       /omit-if-no-ref/
                        ps2_1_ph_pins: ps2-1-ph-pins {
                                pins = "PH12", "PH13";
                                function = "ps2";
                        };
 
+                       /omit-if-no-ref/
                        pwm0_pin: pwm0-pin {
                                pins = "PB2";
                                function = "pwm";
                        };
 
+                       /omit-if-no-ref/
                        pwm1_pin: pwm1-pin {
                                pins = "PI3";
                                function = "pwm";
                        };
 
+                       /omit-if-no-ref/
                        spdif_tx_pin: spdif-tx-pin {
                                pins = "PB13";
                                function = "spdif";
                                bias-pull-up;
                        };
 
+                       /omit-if-no-ref/
                        spi0_pi_pins: spi0-pi-pins {
                                pins = "PI11", "PI12", "PI13";
                                function = "spi0";
                        };
 
+                       /omit-if-no-ref/
                        spi0_cs0_pi_pin: spi0-cs0-pi-pin {
                                pins = "PI10";
                                function = "spi0";
                        };
 
+                       /omit-if-no-ref/
                        spi0_cs1_pi_pin: spi0-cs1-pi-pin {
                                pins = "PI14";
                                function = "spi0";
                        };
 
+                       /omit-if-no-ref/
                        spi1_pi_pins: spi1-pi-pins {
                                pins = "PI17", "PI18", "PI19";
                                function = "spi1";
                        };
 
+                       /omit-if-no-ref/
                        spi1_cs0_pi_pin: spi1-cs0-pi-pin {
                                pins = "PI16";
                                function = "spi1";
                        };
 
+                       /omit-if-no-ref/
                        spi2_pb_pins: spi2-pb-pins {
                                pins = "PB15", "PB16", "PB17";
                                function = "spi2";
                        };
 
+                       /omit-if-no-ref/
                        spi2_cs0_pb_pin: spi2-cs0-pb-pin {
                                pins = "PB14";
                                function = "spi2";
                        };
 
+                       /omit-if-no-ref/
                        spi2_pc_pins: spi2-pc-pins {
                                pins = "PC20", "PC21", "PC22";
                                function = "spi2";
                        };
 
+                       /omit-if-no-ref/
                        spi2_cs0_pc_pin: spi2-cs0-pc-pin {
                                pins = "PC19";
                                function = "spi2";
                        };
 
+                       /omit-if-no-ref/
                        uart0_pb_pins: uart0-pb-pins {
                                pins = "PB22", "PB23";
                                function = "uart0";
                        };
 
+                       /omit-if-no-ref/
+                       uart0_pf_pins: uart0-pf-pins {
+                               pins = "PF2", "PF4";
+                               function = "uart0";
+                       };
+
+                       /omit-if-no-ref/
+                       uart1_pa_pins: uart1-pa-pins {
+                               pins = "PA10", "PA11";
+                               function = "uart1";
+                       };
+
+                       /omit-if-no-ref/
+                       uart1_cts_rts_pa_pins: uart1-cts-rts-pa-pins {
+                               pins = "PA12", "PA13";
+                               function = "uart1";
+                       };
+
+                       /omit-if-no-ref/
+                       uart2_pa_pins: uart2-pa-pins {
+                               pins = "PA2", "PA3";
+                               function = "uart2";
+                       };
+
+                       /omit-if-no-ref/
+                       uart2_cts_rts_pa_pins: uart2-cts-rts-pa-pins {
+                               pins = "PA0", "PA1";
+                               function = "uart2";
+                       };
+
+                       /omit-if-no-ref/
                        uart2_pi_pins: uart2-pi-pins {
                                pins = "PI18", "PI19";
                                function = "uart2";
                        };
 
+                       /omit-if-no-ref/
                        uart2_cts_rts_pi_pins: uart2-cts-rts-pi-pins {
                                pins = "PI16", "PI17";
                                function = "uart2";
                        };
 
+                       /omit-if-no-ref/
                        uart3_pg_pins: uart3-pg-pins {
                                pins = "PG6", "PG7";
                                function = "uart3";
                        };
 
+                       /omit-if-no-ref/
                        uart3_cts_rts_pg_pins: uart3-cts-rts-pg-pins {
                                pins = "PG8", "PG9";
                                function = "uart3";
                        };
 
+                       /omit-if-no-ref/
                        uart3_ph_pins: uart3-ph-pins {
                                pins = "PH0", "PH1";
                                function = "uart3";
                        };
 
+                       /omit-if-no-ref/
+                       uart3_cts_rts_ph_pins: uart3-cts-rts-ph-pins {
+                               pins = "PH2", "PH3";
+                               function = "uart3";
+                       };
+
+                       /omit-if-no-ref/
                        uart4_pg_pins: uart4-pg-pins {
                                pins = "PG10", "PG11";
                                function = "uart4";
                        };
 
+                       /omit-if-no-ref/
                        uart4_ph_pins: uart4-ph-pins {
                                pins = "PH4", "PH5";
                                function = "uart4";
                        };
 
+                       /omit-if-no-ref/
+                       uart5_ph_pins: uart5-ph-pins {
+                               pins = "PH6", "PH7";
+                               function = "uart5";
+                       };
+
+                       /omit-if-no-ref/
                        uart5_pi_pins: uart5-pi-pins {
                                pins = "PI10", "PI11";
                                function = "uart5";
                        };
 
+                       /omit-if-no-ref/
+                       uart6_pa_pins: uart6-pa-pins {
+                               pins = "PA12", "PA13";
+                               function = "uart6";
+                       };
+
+                       /omit-if-no-ref/
                        uart6_pi_pins: uart6-pi-pins {
                                pins = "PI12", "PI13";
                                function = "uart6";
                        };
 
+                       /omit-if-no-ref/
+                       uart7_pa_pins: uart7-pa-pins {
+                               pins = "PA14", "PA15";
+                               function = "uart7";
+                       };
+
+                       /omit-if-no-ref/
                        uart7_pi_pins: uart7-pi-pins {
                                pins = "PI20", "PI21";
                                function = "uart7";
                };
 
                gic: interrupt-controller@1c81000 {
-                       compatible = "arm,gic-400", "arm,cortex-a7-gic", "arm,cortex-a15-gic";
+                       compatible = "arm,gic-400";
                        reg = <0x01c81000 0x1000>,
                              <0x01c82000 0x2000>,
                              <0x01c84000 0x2000>,
index 43fe215..af2fa69 100644 (file)
                        #dma-cells = <1>;
                };
 
-               nfc: nand@1c03000 {
-                       compatible = "allwinner,sun4i-a10-nand";
+               nfc: nand-controller@1c03000 {
+                       compatible = "allwinner,sun8i-a23-nand-controller";
                        reg = <0x01c03000 0x1000>;
                        interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&ccu CLK_BUS_NAND>, <&ccu CLK_NAND>;
                        clock-names = "ahb", "mod";
                        resets = <&ccu RST_BUS_NAND>;
                        reset-names = "ahb";
+                       dmas = <&dma 5>;
+                       dma-names = "rxtx";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&nand_pins &nand_cs0_pin &nand_rb0_pin>;
                        status = "disabled";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        clock-names = "ahb",
                                      "tcon-ch0";
                        clock-output-names = "tcon-pixel-clock";
+                       #clock-cells = <0>;
                        resets = <&ccu RST_BUS_LCD>;
                        reset-names = "lcd";
                        status = "disabled";
                                #size-cells = <0>;
 
                                tcon0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       tcon0_in_drc0: endpoint@0 {
-                                               reg = <0>;
+                                       tcon0_in_drc0: endpoint {
                                                remote-endpoint = <&drc0_out_tcon0>;
                                        };
                                };
 
                                tcon0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
                                };
                        };
                        phys = <&usbphy 0>;
                        phy-names = "usb";
                        extcon = <&usbphy 0>;
+                       dr_mode = "otg";
                        status = "disabled";
                };
 
                        clocks = <&ccu CLK_BUS_EHCI>;
                        resets = <&ccu RST_BUS_EHCI>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        clocks = <&ccu CLK_BUS_OHCI>, <&ccu CLK_USB_OHCI>;
                        resets = <&ccu RST_BUS_OHCI>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                                function = "nand0";
                        };
 
-                       nand_pins_cs0: nand-pins-cs0 {
+                       nand_cs0_pin: nand-cs0-pin {
                                pins = "PC4";
                                function = "nand0";
                                bias-pull-up;
                        };
 
-                       nand_pins_cs1: nand-pins-cs1 {
+                       nand_cs1_pin: nand-cs1-pin {
                                pins = "PC3";
                                function = "nand0";
                                bias-pull-up;
                        };
 
-                       nand_pins_rb0: nand-pins-rb0 {
+                       nand_rb0_pin: nand-rb0-pin {
                                pins = "PC6";
                                function = "nand0";
                                bias-pull-up;
                        };
 
-                       nand_pins_rb1: nand-pins-rb1 {
+                       nand_rb1_pin: nand-rb1-pin {
                                pins = "PC7";
                                function = "nand0";
                                bias-pull-up;
                };
 
                gic: interrupt-controller@1c81000 {
-                       compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
+                       compatible = "arm,gic-400";
                        reg = <0x01c81000 0x1000>,
                              <0x01c82000 0x2000>,
                              <0x01c84000 0x2000>,
                                #size-cells = <0>;
 
                                fe0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       fe0_out_be0: endpoint@0 {
-                                               reg = <0>;
+                                       fe0_out_be0: endpoint {
                                                remote-endpoint = <&be0_in_fe0>;
                                        };
                                };
                                #size-cells = <0>;
 
                                be0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       be0_in_fe0: endpoint@0 {
-                                               reg = <0>;
+                                       be0_in_fe0: endpoint {
                                                remote-endpoint = <&fe0_out_be0>;
                                        };
                                };
 
                                be0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       be0_out_drc0: endpoint@0 {
-                                               reg = <0>;
+                                       be0_out_drc0: endpoint {
                                                remote-endpoint = <&drc0_in_be0>;
                                        };
                                };
                                #size-cells = <0>;
 
                                drc0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       drc0_in_be0: endpoint@0 {
-                                               reg = <0>;
+                                       drc0_in_be0: endpoint {
                                                remote-endpoint = <&be0_out_drc0>;
                                        };
                                };
 
                                drc0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       drc0_out_tcon0: endpoint@0 {
-                                               reg = <0>;
+                                       drc0_out_tcon0: endpoint {
                                                remote-endpoint = <&tcon0_in_drc0>;
                                        };
                                };
                        status = "disabled";
                };
 
+               r_i2c: i2c@1f02400 {
+                       compatible = "allwinner,sun8i-a23-i2c",
+                                    "allwinner,sun6i-a31-i2c";
+                       reg = <0x01f02400 0x400>;
+                       interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&r_i2c_pins>;
+                       clocks = <&apb0_gates 6>;
+                       resets = <&apb0_rst 6>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
                r_pio: pinctrl@1f02c00 {
                        compatible = "allwinner,sun8i-a23-r-pinctrl";
                        reg = <0x01f02c00 0x400>;
                        #interrupt-cells = <3>;
                        #gpio-cells = <3>;
 
+                       r_i2c_pins: r-i2c-pins {
+                               pins = "PL0", "PL1";
+                               function = "s_i2c";
+                               bias-pull-up;
+                       };
+
                        r_rsb_pins: r-rsb-pins {
                                pins = "PL0", "PL1";
                                function = "s_rsb";
index d4dab7c..5659c63 100644 (file)
@@ -65,3 +65,9 @@
 &panel {
        compatible = "bananapi,s070wv20-ct16", "simple-panel";
 };
+
+&tcon0_out {
+       tcon0_out_lcd: endpoint {
+               remote-endpoint = <&panel_input>;
+       };
+};
index b0bc236..9c5750c 100644 (file)
        model = "Q8 A33 Tablet";
        compatible = "allwinner,q8-a33", "allwinner,sun8i-a33";
 };
+
+&tcon0_out {
+       tcon0_out_lcd: endpoint@0 {
+               reg = <0>;
+               remote-endpoint = <&panel_input>;
+       };
+};
index f366726..785798e 100644 (file)
 
        panel {
                compatible = "netron-dy,e231732";
-               #address-cells = <1>;
-               #size-cells = <0>;
 
-               port@0 {
-                       reg = <0>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
-                       panel_input: endpoint@0 {
-                               reg = <0>;
+               port {
+                       panel_input: endpoint {
                                remote-endpoint = <&tcon0_out_panel>;
                        };
                };
index 1111a64..1532a0e 100644 (file)
                        phys = <&dphy>;
                        phy-names = "dphy";
                        status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
-                       ports {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                                       reg = <0>;
-
-                                       dsi_in_tcon0: endpoint {
-                                               remote-endpoint = <&tcon0_out_dsi>;
-                                       };
+                       port {
+                               dsi_in_tcon0: endpoint {
+                                       remote-endpoint = <&tcon0_out_dsi>;
                                };
                        };
                };
 };
 
 &tcon0_out {
+       #address-cells = <1>;
+       #size-cells = <0>;
+
        tcon0_out_dsi: endpoint@1 {
                reg = <1>;
                remote-endpoint = <&dsi_in_tcon0>;
index 838be7b..9d34eab 100644 (file)
        };
 };
 
+&usb_otg {
+       dr_mode = "otg";
+       status = "okay";
+};
+
+&usb_power_supply {
+       status = "okay";
+};
+
 &usbphy {
+       usb0_id_det-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */
+       usb0_vbus_power-supply = <&usb_power_supply>;
+       usb0_vbus-supply = <&reg_drivevbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
        status = "okay";
 };
index fcbec3d..ea299d3 100644 (file)
        };
 };
 
+&usb_otg {
+       dr_mode = "otg";
+       status = "okay";
+};
+
+&usb_power_supply {
+       status = "okay";
+};
+
 &usbphy {
+       usb0_id_det-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */
+       usb0_vbus_power-supply = <&usb_power_supply>;
+       usb0_vbus-supply = <&reg_drivevbus>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
        usb2_vbus-supply = <&reg_usb2_vbus>;
        status = "okay";
index 98e8cea..66d0780 100644 (file)
@@ -46,6 +46,7 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/input/input.h>
 
 / {
        model = "TBS A711 Tablet";
                };
        };
 
+       reg_gps: reg-gps {
+               compatible = "regulator-fixed";
+               regulator-name = "gps";
+               regulator-min-microvolt = <3000000>;
+               regulator-max-microvolt = <3000000>;
+       };
+
        reg_vbat: reg-vbat {
                compatible = "regulator-fixed";
                regulator-name = "vbat";
        status = "okay";
 };
 
+&i2c1 {
+       clock-frequency = <400000>;
+       status = "okay";
+
+       accelerometer@18 {
+               compatible = "bosch,bma250";
+               reg = <0x18>;
+               interrupt-parent = <&pio>;
+               interrupts = <7 10 IRQ_TYPE_EDGE_RISING>; /* PH10 / EINT10 */
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_dcdc1>;
        pinctrl-names = "default";
        status = "okay";
 };
 
+&r_lradc {
+       vref-supply = <&reg_aldo2>;
+       status = "okay";
+
+       button@210 {
+               label = "Volume Up";
+               linux,code = <KEY_VOLUMEUP>;
+               channel = <0>;
+               voltage = <210000>;
+       };
+
+       button@410 {
+               label = "Volume Down";
+               linux,code = <KEY_VOLUMEDOWN>;
+               channel = <0>;
+               voltage = <410000>;
+       };
+};
+
 &r_rsb {
        status = "okay";
 
 };
 
 &tcon0_out {
-       tcon0_out_lcd: endpoint@0 {
-               reg = <0>;
+       tcon0_out_lcd: endpoint {
                remote-endpoint = <&panel_input>;
        };
 };
 &uart1 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
+       uart-has-rtscts;
+       status = "okay";
+
+       bluetooth {
+               compatible = "brcm,bcm20702a1";
+               clocks = <&ac100_rtc 1>;
+               clock-names = "lpo";
+               vbat-supply = <&reg_vbat>;
+               vddio-supply = <&reg_dldo1>;
+               device-wakeup-gpios = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+               host-wakeup-gpios = <&r_pio 0 5 GPIO_ACTIVE_HIGH>; /* PL5 */
+               shutdown-gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */
+               max-speed = <1500000>;
+       };
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart2_pb_pins>;
        status = "okay";
+
+       gnss {
+               compatible = "u-blox,neo-6m";
+
+               v-bckp-supply = <&reg_rtc_ldo>;
+               vcc-supply = <&reg_gps>;
+               current-speed = <9600>;
+       };
 };
 
 &usb_otg {
 &usbphy {
        usb0_id_det-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */
        usb0_vbus-supply = <&reg_drivevbus>;
-       usb1_vbus_supply = <&reg_vmain>;
-       usb2_vbus_supply = <&reg_vmain>;
+       usb1_vbus-supply = <&reg_vmain>;
+       usb2_vbus-supply = <&reg_vmain>;
        status = "okay";
 };
index b099d2f..392b0ca 100644 (file)
                #size-cells = <0>;
 
                cpu0: cpu@0 {
-                       clocks = <&ccu CLK_C0CPUX>;
-                       clock-names = "cpu";
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
+                       clocks = <&ccu CLK_C0CPUX>;
                        operating-points-v2 = <&cpu0_opp_table>;
                        cci-control-port = <&cci_control0>;
                        enable-method = "allwinner,sun8i-a83t-smp";
                        reg = <0>;
+                       #cooling-cells = <2>;
                };
 
                cpu@1 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
+                       clocks = <&ccu CLK_C0CPUX>;
                        operating-points-v2 = <&cpu0_opp_table>;
                        cci-control-port = <&cci_control0>;
                        enable-method = "allwinner,sun8i-a83t-smp";
                        reg = <1>;
+                       #cooling-cells = <2>;
                };
 
                cpu@2 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
+                       clocks = <&ccu CLK_C0CPUX>;
                        operating-points-v2 = <&cpu0_opp_table>;
                        cci-control-port = <&cci_control0>;
                        enable-method = "allwinner,sun8i-a83t-smp";
                        reg = <2>;
+                       #cooling-cells = <2>;
                };
 
                cpu@3 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
+                       clocks = <&ccu CLK_C0CPUX>;
                        operating-points-v2 = <&cpu0_opp_table>;
                        cci-control-port = <&cci_control0>;
                        enable-method = "allwinner,sun8i-a83t-smp";
                        reg = <3>;
+                       #cooling-cells = <2>;
                };
 
                cpu100: cpu@100 {
-                       clocks = <&ccu CLK_C1CPUX>;
-                       clock-names = "cpu";
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
+                       clocks = <&ccu CLK_C1CPUX>;
                        operating-points-v2 = <&cpu1_opp_table>;
                        cci-control-port = <&cci_control1>;
                        enable-method = "allwinner,sun8i-a83t-smp";
                        reg = <0x100>;
+                       #cooling-cells = <2>;
                };
 
                cpu@101 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
+                       clocks = <&ccu CLK_C1CPUX>;
                        operating-points-v2 = <&cpu1_opp_table>;
                        cci-control-port = <&cci_control1>;
                        enable-method = "allwinner,sun8i-a83t-smp";
                        reg = <0x101>;
+                       #cooling-cells = <2>;
                };
 
                cpu@102 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
+                       clocks = <&ccu CLK_C1CPUX>;
                        operating-points-v2 = <&cpu1_opp_table>;
                        cci-control-port = <&cci_control1>;
                        enable-method = "allwinner,sun8i-a83t-smp";
                        reg = <0x102>;
+                       #cooling-cells = <2>;
                };
 
                cpu@103 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
+                       clocks = <&ccu CLK_C1CPUX>;
                        operating-points-v2 = <&cpu1_opp_table>;
                        cci-control-port = <&cci_control1>;
                        enable-method = "allwinner,sun8i-a83t-smp";
                        reg = <0x103>;
+                       #cooling-cells = <2>;
                };
        };
 
                                                reg = <0>;
                                                remote-endpoint = <&tcon0_in_mixer0>;
                                        };
+
+                                       mixer0_out_tcon1: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&tcon1_in_mixer0>;
+                                       };
                                };
                        };
                };
                                #size-cells = <0>;
 
                                mixer1_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       mixer1_out_tcon1: endpoint {
+                                       mixer1_out_tcon0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&tcon0_in_mixer1>;
+                                       };
+
+                                       mixer1_out_tcon1: endpoint@1 {
+                                               reg = <1>;
                                                remote-endpoint = <&tcon1_in_mixer1>;
                                        };
                                };
                        clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_TCON0>;
                        clock-names = "ahb", "tcon-ch0";
                        clock-output-names = "tcon-pixel-clock";
+                       #clock-cells = <0>;
                        resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>;
                        reset-names = "lcd", "lvds";
 
                                                reg = <0>;
                                                remote-endpoint = <&mixer0_out_tcon0>;
                                        };
+
+                                       tcon0_in_mixer1: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&mixer1_out_tcon0>;
+                                       };
                                };
 
                                tcon0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
                                };
                        };
                                #size-cells = <0>;
 
                                tcon1_in: port@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       tcon1_in_mixer1: endpoint {
+                                       tcon1_in_mixer0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&mixer0_out_tcon1>;
+                                       };
+
+                                       tcon1_in_mixer1: endpoint@1 {
+                                               reg = <1>;
                                                remote-endpoint = <&mixer1_out_tcon1>;
                                        };
                                };
                        phys = <&usbphy 0>;
                        phy-names = "usb";
                        extcon = <&usbphy 0>;
+                       dr_mode = "otg";
                        status = "disabled";
                };
 
                        clocks = <&ccu CLK_BUS_EHCI0>;
                        resets = <&ccu RST_BUS_EHCI0>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        clocks = <&ccu CLK_BUS_OHCI0>, <&ccu CLK_USB_OHCI0>;
                        resets = <&ccu RST_BUS_OHCI0>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        clocks = <&ccu CLK_BUS_EHCI1>;
                        resets = <&ccu RST_BUS_EHCI1>;
                        phys = <&usbphy 2>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                                function = "i2c1";
                        };
 
+                       /omit-if-no-ref/
+                       i2c2_pe_pins: i2c2-pe-pins {
+                               pins = "PE14", "PE15";
+                               function = "i2c2";
+                       };
+
                        i2c2_ph_pins: i2c2-ph-pins {
                                pins = "PH4", "PH5";
                                function = "i2c2";
                                pins = "PG8", "PG9";
                                function = "uart1";
                        };
+
+                       /omit-if-no-ref/
+                       uart2_pb_pins: uart2-pb-pins {
+                               pins = "PB0", "PB1";
+                               function = "uart2";
+                       };
                };
 
                timer@1c20c00 {
                        status = "disabled";
                };
 
+               uart2: serial@1c28800 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28800 0x400>;
+                       interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&ccu CLK_BUS_UART2>;
+                       resets = <&ccu RST_BUS_UART2>;
+                       status = "disabled";
+               };
+
+               uart3: serial@1c28c00 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28c00 0x400>;
+                       interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&ccu CLK_BUS_UART3>;
+                       resets = <&ccu RST_BUS_UART3>;
+                       status = "disabled";
+               };
+
+               uart4: serial@1c29000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c29000 0x400>;
+                       interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&ccu CLK_BUS_UART4>;
+                       resets = <&ccu RST_BUS_UART4>;
+                       status = "disabled";
+               };
+
                i2c0: i2c@1c2ac00 {
                        compatible = "allwinner,sun8i-a83t-i2c",
                                     "allwinner,sun6i-a31-i2c";
                };
 
                gic: interrupt-controller@1c81000 {
-                       compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
+                       compatible = "arm,gic-400";
                        reg = <0x01c81000 0x1000>,
                              <0x01c82000 0x2000>,
                              <0x01c84000 0x2000>,
                        status = "disabled";
                };
 
+               r_lradc: lradc@1f03c00 {
+                       compatible = "allwinner,sun8i-a83t-r-lradc";
+                       reg = <0x01f03c00 0x100>;
+                       interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
                r_pio: pinctrl@1f02c00 {
                        compatible = "allwinner,sun8i-a83t-r-pinctrl";
                        reg = <0x01f02c00 0x400>;
index 1db2541..78a37a4 100644 (file)
@@ -28,7 +28,6 @@
 
        leds {
                compatible = "gpio-leds";
-               pinctrl-names = "default";
 
                pwr_led {
                        label = "bananapi-m2-zero:red:pwr";
@@ -39,7 +38,6 @@
 
        gpio_keys {
                compatible = "gpio-keys";
-               pinctrl-names = "default";
 
                sw4 {
                        label = "power";
@@ -67,8 +65,9 @@
 
        wifi_pwrseq: wifi_pwrseq {
                compatible = "mmc-pwrseq-simple";
-               pinctrl-names = "default";
                reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */
+               clocks = <&rtc 1>;
+               clock-names = "ext_clock";
        };
 };
 
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
 &uart1 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
+       uart-has-rtscts;
        status = "okay";
+
+       bluetooth {
+               compatible = "brcm,bcm43438-bt";
+               clocks = <&rtc 1>;
+               clock-names = "lpo";
+               vbat-supply = <&reg_vcc3v3>;
+               vddio-supply = <&reg_vcc3v3>;
+               device-wakeup-gpios = <&pio 6 13 GPIO_ACTIVE_HIGH>; /* PG13 */
+               host-wakeup-gpios = <&pio 6 11 GPIO_ACTIVE_HIGH>; /* PG11 */
+               shutdown-gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */
+       };
+
 };
 
 &usb_otg {
index 84cd9c0..4970eda 100644 (file)
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index 25540b7..6277f13 100644 (file)
 
 &ir {
        pinctrl-names = "default";
-       pinctrl-0 = <&ir_pins_a>;
+       pinctrl-0 = <&r_ir_rx_pin>;
        status = "okay";
 };
 
 
 &spdif {
        pinctrl-names = "default";
-       pinctrl-0 = <&spdif_tx_pins_a>;
+       pinctrl-0 = <&spdif_tx_pin>;
        status = "okay";
 };
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index 2c952ea..ff0a7a9 100644 (file)
 
 &ir {
        pinctrl-names = "default";
-       pinctrl-0 = <&ir_pins_a>;
+       pinctrl-0 = <&r_ir_rx_pin>;
        status = "okay";
 };
 
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
-       cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
-       cd-inverted;
+       cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
        status = "okay";
 };
 
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index 4ec94d7..4ba533b 100644 (file)
@@ -64,7 +64,6 @@
 
        wifi_pwrseq: wifi_pwrseq {
                compatible = "mmc-pwrseq-simple";
-               pinctrl-names = "default";
                reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */
        };
 
 
 &ir {
        pinctrl-names = "default";
-       pinctrl-0 = <&ir_pins_a>;
+       pinctrl-0 = <&r_ir_rx_pin>;
        status = "okay";
 };
 
index 9412668..69243dc 100644 (file)
@@ -93,7 +93,7 @@
 
 &ir {
        pinctrl-names = "default";
-       pinctrl-0 = <&ir_pins_a>;
+       pinctrl-0 = <&r_ir_rx_pin>;
        status = "okay";
 };
 
index 6246d3e..07867a0 100644 (file)
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index f110ee3..4df29a6 100644 (file)
@@ -59,8 +59,6 @@
 
        leds {
                compatible = "gpio-leds";
-               pinctrl-names = "default";
-               pinctrl-0 = <&leds_npi>, <&leds_r_npi>;
 
                status {
                        label = "nanopi:blue:status";
@@ -78,8 +76,6 @@
        r_gpio_keys {
                compatible = "gpio-keys";
                input-name = "k1";
-               pinctrl-names = "default";
-               pinctrl-0 = <&sw_r_npi>;
 
                k1 {
                        label = "k1";
        status = "okay";
 };
 
-&pio {
-       leds_npi: led_pins {
-               pins = "PA10";
-               function = "gpio_out";
-       };
-};
-
-&r_pio {
-       leds_r_npi: led_pins {
-               pins = "PL10";
-               function = "gpio_out";
-       };
-
-       sw_r_npi: key_pins {
-               pins = "PL3";
-               function = "gpio_in";
-       };
-};
-
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index f1fc6bd..597c425 100644 (file)
@@ -75,8 +75,6 @@
 
        leds {
                compatible = "gpio-leds";
-               pinctrl-names = "default";
-               pinctrl-0 = <&leds_opc>, <&leds_r_opc>;
 
                status_led {
                        label = "orangepi:red:status";
@@ -92,8 +90,6 @@
 
        r_gpio_keys {
                compatible = "gpio-keys";
-               pinctrl-names = "default";
-               pinctrl-0 = <&sw_r_opc>;
 
                sw2 {
                        label = "sw2";
 
        wifi_pwrseq: wifi_pwrseq {
                compatible = "mmc-pwrseq-simple";
-               pinctrl-names = "default";
-               pinctrl-0 = <&wifi_pwrseq_pin_orangepi>;
                reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 WIFI_EN */
        };
 };
 
 &ir {
        pinctrl-names = "default";
-       pinctrl-0 = <&ir_pins_a>;
+       pinctrl-0 = <&r_ir_rx_pin>;
        status = "okay";
 };
 
        };
 };
 
-&pio {
-       leds_opc: led_pins {
-               pins = "PA15";
-               function = "gpio_out";
-       };
-};
-
-&r_pio {
-       leds_r_opc: led_pins {
-               pins = "PL10";
-               function = "gpio_out";
-       };
-
-       sw_r_opc: key_pins {
-               pins = "PL3", "PL4";
-               function = "gpio_in";
-       };
-
-       wifi_pwrseq_pin_orangepi: wifi_pwrseq_pin {
-               pins = "PL7";
-               function = "gpio_out";
-       };
-};
-
 &reg_usb1_vbus {
        gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>;
        status = "okay";
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index 476ae8e..6f9c97a 100644 (file)
@@ -74,8 +74,6 @@
 
        leds {
                compatible = "gpio-leds";
-               pinctrl-names = "default";
-               pinctrl-0 = <&leds_opc>, <&leds_r_opc>;
 
                pwr_led {
                        label = "orangepi:green:pwr";
@@ -91,8 +89,6 @@
 
        r_gpio_keys {
                compatible = "gpio-keys";
-               pinctrl-names = "default";
-               pinctrl-0 = <&sw_r_opc>;
 
                sw4 {
                        label = "sw4";
 
 &ir {
        pinctrl-names = "default";
-       pinctrl-0 = <&ir_pins_a>;
+       pinctrl-0 = <&r_ir_rx_pin>;
        status = "okay";
 };
 
        status = "okay";
 };
 
-&pio {
-       leds_opc: led_pins {
-               pins = "PA15";
-               function = "gpio_out";
-       };
-};
-
-&r_pio {
-       leds_r_opc: led_pins {
-               pins = "PL10";
-               function = "gpio_out";
-       };
-
-       sw_r_opc: key_pins {
-               pins = "PL3";
-               function = "gpio_in";
-       };
-};
-
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index 245fd65..8408491 100644 (file)
@@ -73,8 +73,6 @@
 
        leds {
                compatible = "gpio-leds";
-               pinctrl-names = "default";
-               pinctrl-0 = <&leds_opc>, <&leds_r_opc>;
 
                pwr_led {
                        label = "orangepi:green:pwr";
@@ -90,8 +88,6 @@
 
        r_gpio_keys {
                compatible = "gpio-keys";
-               pinctrl-names = "default";
-               pinctrl-0 = <&sw_r_opc>;
 
                sw4 {
                        label = "sw4";
        status = "okay";
 };
 
-&pio {
-       leds_opc: led_pins {
-               pins = "PA15";
-               function = "gpio_out";
-       };
-};
-
-&r_pio {
-       leds_r_opc: led_pins {
-               pins = "PL10";
-               function = "gpio_out";
-       };
-
-       sw_r_opc: key_pins {
-               pins = "PL3";
-               function = "gpio_in";
-       };
-};
-
 &reg_usb0_vbus {
        gpio = <&r_pio 0 2 GPIO_ACTIVE_HIGH>; /* PL2 */
        status = "okay";
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index 4624033..5aff8ec 100644 (file)
@@ -73,8 +73,6 @@
 
        leds {
                compatible = "gpio-leds";
-               pinctrl-names = "default";
-               pinctrl-0 = <&leds_opc>, <&leds_r_opc>;
 
                pwr_led {
                        label = "orangepi:green:pwr";
@@ -90,8 +88,6 @@
 
        r_gpio_keys {
                compatible = "gpio-keys";
-               pinctrl-names = "default";
-               pinctrl-0 = <&sw_r_opc>;
 
                sw4 {
                        label = "sw4";
 
 &ir {
        pinctrl-names = "default";
-       pinctrl-0 = <&ir_pins_a>;
+       pinctrl-0 = <&r_ir_rx_pin>;
        status = "okay";
 };
 
        status = "okay";
 };
 
-&pio {
-       leds_opc: led_pins {
-               pins = "PA15";
-               function = "gpio_out";
-       };
-};
-
 &r_i2c {
        status = "okay";
 
        };
 };
 
-&r_pio {
-       leds_r_opc: led_pins {
-               pins = "PL10";
-               function = "gpio_out";
-       };
-
-       sw_r_opc: key_pins {
-               pins = "PL3";
-               function = "gpio_in";
-       };
-};
-
 &reg_usb0_vbus {
        gpio = <&r_pio 0 2 GPIO_ACTIVE_HIGH>; /* PL2 */
        status = "okay";
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index ac8438c..97f4978 100644 (file)
@@ -63,8 +63,6 @@
 
        reg_usb3_vbus: usb3-vbus {
                compatible = "regulator-fixed";
-               pinctrl-names = "default";
-               pinctrl-0 = <&usb3_vbus_pin_a>;
                regulator-name = "usb3-vbus";
                regulator-min-microvolt = <5000000>;
                regulator-max-microvolt = <5000000>;
        bias-pull-up;
 };
 
-&pio {
-       usb3_vbus_pin_a: usb3_vbus_pin {
-               pins = "PG11";
-               function = "gpio_out";
-       };
-};
-
 &r_i2c {
        status = "okay";
 
index c834048..b8f46e2 100644 (file)
@@ -79,7 +79,6 @@
 
        wifi_pwrseq: wifi_pwrseq {
                compatible = "mmc-pwrseq-simple";
-               pinctrl-names = "default";
                reset-gpios = <&pio 0 9 GPIO_ACTIVE_LOW>; /* PA9 */
                post-power-on-delay-ms = <200>;
        };
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
diff --git a/arch/arm/boot/dts/sun8i-h3-rervision-dvk.dts b/arch/arm/boot/dts/sun8i-h3-rervision-dvk.dts
new file mode 100644 (file)
index 0000000..4738f3a
--- /dev/null
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Bootlin
+ * Author: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+ */
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "RerVision H3-DVK";
+       compatible = "rervision,h3-dvk", "allwinner,sun8i-h3";
+
+       aliases {
+               ethernet0 = &emac;
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       connector {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_con_in: endpoint {
+                               remote-endpoint = <&hdmi_out_con>;
+                       };
+               };
+       };
+};
+
+&de {
+       status = "okay";
+};
+
+&ehci1 {
+       status = "okay";
+};
+
+&ehci2 {
+       status = "okay";
+};
+
+&ehci3 {
+       status = "okay";
+};
+
+&emac {
+       phy-handle = <&int_mii_phy>;
+       phy-mode = "mii";
+       allwinner,leds-active-low;
+       status = "okay";
+};
+
+&hdmi {
+       status = "okay";
+};
+
+&hdmi_out {
+       hdmi_out_con: endpoint {
+               remote-endpoint = <&hdmi_con_in>;
+       };
+};
+
+&mmc0 {
+       bus-width = <4>;
+       cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+       status = "okay";
+       vmmc-supply = <&reg_vcc3v3>;
+};
+
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_8bit_pins>;
+       vmmc-supply = <&reg_vcc3v3>;
+       bus-width = <8>;
+       non-removable;
+       cap-mmc-hw-reset;
+       status = "okay";
+};
+
+&ohci1 {
+       status = "okay";
+};
+
+&ohci2 {
+       status = "okay";
+};
+
+&ohci3 {
+       status = "okay";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pa_pins>;
+       status = "okay";
+};
+
+&usb_otg {
+       status = "okay";
+       dr_mode = "peripheral";
+};
+
+&usbphy {
+       status = "okay";
+};
index 959d265..e37c30e 100644 (file)
 &rtc {
        compatible = "allwinner,sun8i-h3-rtc";
 };
+
+&sid {
+       compatible = "allwinner,sun8i-h3-sid";
+};
index 53104f4..3d9a152 100644 (file)
                backlight = <&backlight>;
                enable-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */
                power-supply = <&reg_dc1sw>;
-               #address-cells = <1>;
-               #size-cells = <0>;
 
-               port@0 {
-                       reg = <0>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
-                       panel_input: endpoint@0 {
-                               reg = <0>;
+               port {
+                       panel_input: endpoint {
                                remote-endpoint = <&tcon0_out_lcd>;
                        };
                };
        status = "okay";
 };
 
-&tcon0_out {
-       tcon0_out_lcd: endpoint@0 {
-               reg = <0>;
-               remote-endpoint = <&panel_input>;
-       };
-};
-
 &usbphy {
        usb1_vbus-supply = <&reg_dldo1>;
 };
index 32cf1ab..246dec5 100644 (file)
@@ -34,8 +34,6 @@
 
        /* 2Gb Macronix MX30LF2G18AC (3V) */
        nand@0 {
-               #address-cells = <1>;
-               #size-cells = <1>;
                reg = <0>;
                allwinner,rb = <0>;
                nand-ecc-mode = "hw";
index 316998e..4f48eec 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_det: usb0-id-detect-pin {
-               pins = "PD10";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &r_rsb {
        status = "okay";
 
 
 &usbphy {
        status = "okay";
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_det>;
        usb0_vbus-supply = <&reg_drivevbus>;
-       usb0_id_det-gpios = <&pio 3 10 GPIO_ACTIVE_HIGH>; /* PD10 */
+       usb0_id_det-gpios = <&pio 3 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PD10 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb1_vbus-supply = <&reg_usb1_vbus>;
 };
index 06b6858..bb856e5 100644 (file)
                        clocks = <&ccu CLK_BUS_EHCI1>;
                        resets = <&ccu RST_BUS_EHCI1>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                                 <&ccu CLK_USB_OHCI1>;
                        resets = <&ccu RST_BUS_OHCI1>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        clocks = <&ccu CLK_BUS_EHCI2>;
                        resets = <&ccu RST_BUS_EHCI2>;
                        phys = <&usbphy 2>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                                 <&ccu CLK_USB_OHCI2>;
                        resets = <&ccu RST_BUS_OHCI2>;
                        phys = <&usbphy 2>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&ccu CLK_BUS_SATA>, <&ccu CLK_SATA>;
                        resets = <&ccu RST_BUS_SATA>;
-                       resets-name = "ahci";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+                       reset-names = "ahci";
                        status = "disabled";
 
                };
                                #size-cells = <0>;
 
                                tcon_top_mixer0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       tcon_top_mixer0_in_mixer0: endpoint@0 {
-                                               reg = <0>;
+                                       tcon_top_mixer0_in_mixer0: endpoint {
                                                remote-endpoint = <&mixer0_out_tcon_top>;
                                        };
                                };
index 189e479..b3d8b8f 100644 (file)
        status = "okay";
 };
 
-&pio {
-       usb0_id_detect_pin: usb0-id-detect-pin {
-               pins = "PH8";
-               function = "gpio_in";
-               bias-pull-up;
-       };
-};
-
 &r_rsb {
        status = "okay";
 
 };
 
 &usbphy {
-       pinctrl-names = "default";
-       pinctrl-0 = <&usb0_id_detect_pin>;
-       usb0_id_det-gpio = <&pio 7 8 GPIO_ACTIVE_HIGH>; /* PH8 */
+       usb0_id_det-gpios = <&pio 7 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH8 */
        usb0_vbus_power-supply = <&usb_power_supply>;
        usb0_vbus-supply = <&reg_drivevbus>;
        status = "okay";
index 99c8cf7..2e4587d 100644 (file)
@@ -96,6 +96,6 @@
 };
 
 &usbphy {
-       usb0_id_det-gpio = <&pio 5 6 GPIO_ACTIVE_HIGH>;
+       usb0_id_det-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
        status = "okay";
 };
index 21e1806..df72b17 100644 (file)
                                #size-cells = <0>;
 
                                mixer0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       mixer0_out_tcon0: endpoint@0 {
-                                               reg = <0>;
+                                       mixer0_out_tcon0: endpoint {
                                                remote-endpoint = <&tcon0_in_mixer0>;
                                        };
                                };
                        clock-names = "ahb",
                                      "tcon-ch0";
                        clock-output-names = "tcon-pixel-clock";
+                       #clock-cells = <0>;
                        resets = <&ccu RST_BUS_TCON0>;
                        reset-names = "lcd";
                        status = "disabled";
                                #size-cells = <0>;
 
                                tcon0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       tcon0_in_mixer0: endpoint@0 {
-                                               reg = <0>;
+                                       tcon0_in_mixer0: endpoint {
                                                remote-endpoint = <&mixer0_out_tcon0>;
                                        };
                                };
                };
 
                gic: interrupt-controller@1c81000 {
-                       compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
+                       compatible = "arm,gic-400";
                        reg = <0x01c81000 0x1000>,
                              <0x01c82000 0x1000>,
                              <0x01c84000 0x2000>,
index bf97f62..f05cabd 100644 (file)
 
 #include "axp22x.dtsi"
 
+&mmc0 {
+       vmmc-supply = <&reg_dcdc1>;
+       bus-width = <4>;
+       cd-gpios = <&pio 7 13 GPIO_ACTIVE_LOW>; /* PH13 */
+       status = "okay";
+};
+
+&mmc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pg_pins>;
+       vmmc-supply = <&reg_dldo2>;
+       vqmmc-supply = <&reg_dldo1>;
+       mmc-pwrseq = <&wifi_pwrseq>;
+       bus-width = <4>;
+       non-removable;
+       status = "okay";
+};
+
 &reg_aldo3 {
        regulator-always-on;
        regulator-min-microvolt = <2700000>;
        regulator-name = "vcc-wifi";
 };
 
-&mmc0 {
-       vmmc-supply = <&reg_dcdc1>;
-       bus-width = <4>;
-       cd-gpios = <&pio 7 13 GPIO_ACTIVE_LOW>; /* PH13 */
-       status = "okay";
-};
-
-&mmc1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&mmc1_pg_pins>;
-       vmmc-supply = <&reg_dldo2>;
-       vqmmc-supply = <&reg_dldo1>;
-       mmc-pwrseq = <&wifi_pwrseq>;
-       bus-width = <4>;
-       non-removable;
-       status = "okay";
-};
-
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pb_pins>;
index 28c0349..18156ff 100644 (file)
        vga-dac {
                compatible = "corpro,gm7123", "adi,adv7123", "dumb-vga-dac";
                vdd-supply = <&reg_dcdc1>;
-               #address-cells = <1>;
-               #size-cells = <0>;
 
                ports {
                        #address-cells = <1>;
                        #size-cells = <0>;
 
                        port@0 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
                                reg = <0>;
 
-                               vga_dac_in: endpoint@0 {
-                                       reg = <0>;
+                               vga_dac_in: endpoint {
                                        remote-endpoint = <&tcon0_out_vga>;
                                };
                        };
 
                        port@1 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
                                reg = <1>;
 
-                               vga_dac_out: endpoint@0 {
-                                       reg = <0>;
+                               vga_dac_out: endpoint {
                                        remote-endpoint = <&vga_con_in>;
                                };
                        };
 };
 
 &tcon0_out {
-       tcon0_out_vga: endpoint@0 {
-               reg = <0>;
+       tcon0_out_vga: endpoint {
                remote-endpoint = <&vga_dac_in>;
        };
 };
index 864715e..2ed28d9 100644 (file)
@@ -82,7 +82,7 @@
 
        reg_usb1_vbus: usb1-vbus {
                compatible = "regulator-fixed";
-               pinctrl-names = "default";
+               regulator-name = "usb1-vbus";
                regulator-min-microvolt = <5000000>;
                regulator-max-microvolt = <5000000>;
                enable-active-high;
@@ -91,7 +91,7 @@
 
        reg_usb3_vbus: usb3-vbus {
                compatible = "regulator-fixed";
-               pinctrl-names = "default";
+               regulator-name = "usb3-vbus";
                regulator-min-microvolt = <5000000>;
                regulator-max-microvolt = <5000000>;
                enable-active-high;
index 6fb292e..0c1eec9 100644 (file)
                status = "disabled";
        };
 
-       soc {
+       soc@20000 {
                compatible = "simple-bus";
                #address-cells = <1>;
                #size-cells = <1>;
                        clocks = <&usb_clocks CLK_BUS_HCI0>;
                        resets = <&usb_clocks RST_USB0_HCI>;
                        phys = <&usbphy1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                                 <&usb_clocks CLK_USB_OHCI0>;
                        resets = <&usb_clocks RST_USB0_HCI>;
                        phys = <&usbphy1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        clocks = <&usb_clocks CLK_BUS_HCI1>;
                        resets = <&usb_clocks RST_USB1_HCI>;
                        phys = <&usbphy2>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        clocks = <&usb_clocks CLK_BUS_HCI2>;
                        resets = <&usb_clocks RST_USB2_HCI>;
                        phys = <&usbphy3>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                                 <&usb_clocks CLK_USB_OHCI2>;
                        resets = <&usb_clocks RST_USB2_HCI>;
                        phys = <&usbphy3>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                };
 
                gic: interrupt-controller@1c41000 {
-                       compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
+                       compatible = "arm,gic-400";
                        reg = <0x01c41000 0x1000>,
                              <0x01c42000 0x2000>,
                              <0x01c44000 0x2000>,
                                #size-cells = <0>;
 
                                fe0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       fe0_out_deu0: endpoint@0 {
-                                               reg = <0>;
+                                       fe0_out_deu0: endpoint {
                                                remote-endpoint = <&deu0_in_fe0>;
                                        };
                                };
                                #size-cells = <0>;
 
                                fe1_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       fe1_out_deu1: endpoint@0 {
-                                               reg = <0>;
+                                       fe1_out_deu1: endpoint {
                                                remote-endpoint = <&deu1_in_fe1>;
                                        };
                                };
                                };
 
                                be0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       be0_out_drc0: endpoint@0 {
-                                               reg = <0>;
+                                       be0_out_drc0: endpoint {
                                                remote-endpoint = <&drc0_in_be0>;
                                        };
                                };
                                };
 
                                be1_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       be1_out_drc1: endpoint@0 {
-                                               reg = <0>;
+                                       be1_out_drc1: endpoint {
                                                remote-endpoint = <&drc1_in_be1>;
                                        };
                                };
                                #size-cells = <0>;
 
                                deu0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       deu0_in_fe0: endpoint@0 {
-                                               reg = <0>;
+                                       deu0_in_fe0: endpoint {
                                                remote-endpoint = <&fe0_out_deu0>;
                                        };
                                };
                                #size-cells = <0>;
 
                                deu1_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       deu1_in_fe1: endpoint@0 {
-                                               reg = <0>;
+                                       deu1_in_fe1: endpoint {
                                                remote-endpoint = <&fe1_out_deu1>;
                                        };
                                };
                                #size-cells = <0>;
 
                                drc0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       drc0_in_be0: endpoint@0 {
-                                               reg = <0>;
+                                       drc0_in_be0: endpoint {
                                                remote-endpoint = <&be0_out_drc0>;
                                        };
                                };
 
                                drc0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       drc0_out_tcon0: endpoint@0 {
-                                               reg = <0>;
+                                       drc0_out_tcon0: endpoint {
                                                remote-endpoint = <&tcon0_in_drc0>;
                                        };
                                };
                                #size-cells = <0>;
 
                                drc1_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       drc1_in_be1: endpoint@0 {
-                                               reg = <0>;
+                                       drc1_in_be1: endpoint {
                                                remote-endpoint = <&be1_out_drc1>;
                                        };
                                };
 
                                drc1_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
 
-                                       drc1_out_tcon1: endpoint@0 {
-                                               reg = <0>;
+                                       drc1_out_tcon1: endpoint {
                                                remote-endpoint = <&tcon1_in_drc1>;
                                        };
                                };
                        resets = <&ccu RST_BUS_LCD0>, <&ccu RST_BUS_EDP>;
                        reset-names = "lcd", "edp";
                        clock-output-names = "tcon0-pixel-clock";
+                       #clock-cells = <0>;
 
                        ports {
                                #address-cells = <1>;
                                #size-cells = <0>;
 
                                tcon0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       tcon0_in_drc0: endpoint@0 {
-                                               reg = <0>;
+                                       tcon0_in_drc0: endpoint {
                                                remote-endpoint = <&drc0_out_tcon0>;
                                        };
                                };
 
                                tcon0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
                                };
                        };
                                #size-cells = <0>;
 
                                tcon1_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       tcon1_in_drc1: endpoint@0 {
-                                               reg = <0>;
+                                       tcon1_in_drc1: endpoint {
                                                remote-endpoint = <&drc1_out_tcon1>;
                                        };
                                };
 
                                tcon1_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
                                        reg = <1>;
                                };
                        };
                        gpio-controller;
                        interrupt-controller;
                        #interrupt-cells = <3>;
-                       #size-cells = <0>;
                        #gpio-cells = <3>;
 
                        gmac_rgmii_pins: gmac-rgmii-pins {
-                               allwinner,pins = "PA0", "PA1", "PA2", "PA3",
-                                                "PA4", "PA5", "PA7", "PA8",
-                                                "PA9", "PA10", "PA12", "PA13",
-                                                "PA15", "PA16", "PA17";
-                               allwinner,function = "gmac";
+                               pins = "PA0", "PA1", "PA2", "PA3", "PA4", "PA5",
+                                      "PA7", "PA8", "PA9", "PA10", "PA12",
+                                      "PA13", "PA15", "PA16", "PA17";
+                               function = "gmac";
                                /*
                                 * data lines in RGMII mode use DDR mode
                                 * and need a higher signal drive strength
index 3bed375..39263e7 100644 (file)
@@ -69,7 +69,6 @@
 
        leds {
                compatible = "gpio-leds";
-               pinctrl-names = "default";
 
                pwr_led {
                        label = "bananapi-m2-plus:red:pwr";
@@ -80,7 +79,6 @@
 
        gpio_keys {
                compatible = "gpio-keys";
-               pinctrl-names = "default";
 
                sw4 {
                        label = "power";
 
        wifi_pwrseq: wifi_pwrseq {
                compatible = "mmc-pwrseq-simple";
-               pinctrl-names = "default";
                reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */
                clocks = <&rtc 1>;
                clock-names = "ext_clock";
 
 &ir {
        pinctrl-names = "default";
-       pinctrl-0 = <&ir_pins_a>;
+       pinctrl-0 = <&r_ir_rx_pin>;
        status = "okay";
 };
 
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index d74a6cb..84977d4 100644 (file)
                        #size-cells = <0>;
                };
 
+               sid: eeprom@1c14000 {
+                       /* compatible is in per SoC .dtsi file */
+                       reg = <0x1c14000 0x400>;
+               };
+
                usb_otg: usb@1c19000 {
                        compatible = "allwinner,sun8i-h3-musb";
                        reg = <0x01c19000 0x400>;
                        phys = <&usbphy 0>;
                        phy-names = "usb";
                        extcon = <&usbphy 0>;
+                       dr_mode = "otg";
                        status = "disabled";
                };
 
                        clocks = <&ccu CLK_BUS_EHCI1>, <&ccu CLK_BUS_OHCI1>;
                        resets = <&ccu RST_BUS_EHCI1>, <&ccu RST_BUS_OHCI1>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                                 <&ccu CLK_USB_OHCI1>;
                        resets = <&ccu RST_BUS_EHCI1>, <&ccu RST_BUS_OHCI1>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        clocks = <&ccu CLK_BUS_EHCI2>, <&ccu CLK_BUS_OHCI2>;
                        resets = <&ccu RST_BUS_EHCI2>, <&ccu RST_BUS_OHCI2>;
                        phys = <&usbphy 2>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                                 <&ccu CLK_USB_OHCI2>;
                        resets = <&ccu RST_BUS_EHCI2>, <&ccu RST_BUS_OHCI2>;
                        phys = <&usbphy 2>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        clocks = <&ccu CLK_BUS_EHCI3>, <&ccu CLK_BUS_OHCI3>;
                        resets = <&ccu RST_BUS_EHCI3>, <&ccu RST_BUS_OHCI3>;
                        phys = <&usbphy 3>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                                 <&ccu CLK_USB_OHCI3>;
                        resets = <&ccu RST_BUS_EHCI3>, <&ccu RST_BUS_OHCI3>;
                        phys = <&usbphy 3>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        interrupt-controller;
                        #interrupt-cells = <3>;
 
-                       csi_pins: csi {
+                       csi_pins: csi-pins {
                                pins = "PE0", "PE2", "PE3", "PE4", "PE5",
                                       "PE6", "PE7", "PE8", "PE9", "PE10",
                                       "PE11";
                                function = "csi";
                        };
 
-                       emac_rgmii_pins: emac0 {
+                       emac_rgmii_pins: emac-rgmii-pins {
                                pins = "PD0", "PD1", "PD2", "PD3", "PD4",
                                       "PD5", "PD7", "PD8", "PD9", "PD10",
                                       "PD12", "PD13", "PD15", "PD16", "PD17";
                                drive-strength = <40>;
                        };
 
-                       i2c0_pins: i2c0 {
+                       i2c0_pins: i2c0-pins {
                                pins = "PA11", "PA12";
                                function = "i2c0";
                        };
 
-                       i2c1_pins: i2c1 {
+                       i2c1_pins: i2c1-pins {
                                pins = "PA18", "PA19";
                                function = "i2c1";
                        };
 
-                       i2c2_pins: i2c2 {
+                       i2c2_pins: i2c2-pins {
                                pins = "PE12", "PE13";
                                function = "i2c2";
                        };
 
-                       mmc0_pins: mmc0 {
+                       mmc0_pins: mmc0-pins {
                                pins = "PF0", "PF1", "PF2", "PF3",
                                       "PF4", "PF5";
                                function = "mmc0";
                                bias-pull-up;
                        };
 
-                       mmc1_pins: mmc1 {
+                       mmc1_pins: mmc1-pins {
                                pins = "PG0", "PG1", "PG2", "PG3",
                                       "PG4", "PG5";
                                function = "mmc1";
                                bias-pull-up;
                        };
 
-                       mmc2_8bit_pins: mmc2_8bit {
+                       mmc2_8bit_pins: mmc2-8bit-pins {
                                pins = "PC5", "PC6", "PC8",
                                       "PC9", "PC10", "PC11",
                                       "PC12", "PC13", "PC14",
                                bias-pull-up;
                        };
 
-                       spdif_tx_pins_a: spdif {
+                       spdif_tx_pin: spdif-tx-pin {
                                pins = "PA17";
                                function = "spdif";
                        };
 
-                       spi0_pins: spi0 {
+                       spi0_pins: spi0-pins {
                                pins = "PC0", "PC1", "PC2", "PC3";
                                function = "spi0";
                        };
 
-                       spi1_pins: spi1 {
+                       spi1_pins: spi1-pins {
                                pins = "PA15", "PA16", "PA14", "PA13";
                                function = "spi1";
                        };
 
-                       uart0_pins_a: uart0 {
+                       uart0_pa_pins: uart0-pa-pins {
                                pins = "PA4", "PA5";
                                function = "uart0";
                        };
 
-                       uart1_pins: uart1 {
+                       uart1_pins: uart1-pins {
                                pins = "PG6", "PG7";
                                function = "uart1";
                        };
 
-                       uart1_rts_cts_pins: uart1_rts_cts {
+                       uart1_rts_cts_pins: uart1-rts-cts-pins {
                                pins = "PG8", "PG9";
                                function = "uart1";
                        };
 
-                       uart2_pins: uart2 {
+                       uart2_pins: uart2-pins {
                                pins = "PA0", "PA1";
                                function = "uart2";
                        };
 
-                       uart3_pins: uart3 {
+                       uart3_pins: uart3-pins {
                                pins = "PA13", "PA14";
                                function = "uart3";
                        };
 
-                       uart3_rts_cts_pins: uart3_rts_cts {
+                       uart3_rts_cts_pins: uart3-rts-cts-pins {
                                pins = "PA15", "PA16";
                                function = "uart3";
                        };
                        interrupt-controller;
                        #interrupt-cells = <3>;
 
-                       ir_pins_a: ir {
+                       r_ir_rx_pin: r-ir-rx-pin {
                                pins = "PL11";
                                function = "s_cir_rx";
                        };
 
-                       r_i2c_pins: r-i2c {
+                       r_i2c_pins: r-i2c-pins {
                                pins = "PL0", "PL1";
                                function = "s_i2c";
                        };
index 1eadc13..19b3b23 100644 (file)
 
 &ir {
        pinctrl-names = "default";
-       pinctrl-0 = <&ir_pins_a>;
+       pinctrl-0 = <&r_ir_rx_pin>;
        status = "okay";
 };
 
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index ca2c3a5..d18eaf4 100644 (file)
@@ -1,42 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
- * Copyright 2016 Toradex AG
+ * Copyright 2016-2019 Toradex AG
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     version 2 as published by the Free Software Foundation.
- *
- *     This file is distributed in the hope that it will be useful
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , 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.
  */
 
 / {
index eaee10e..ceb3f63 100644 (file)
@@ -1,42 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
- * Copyright 2016-2018 Toradex AG
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     version 2 as published by the Free Software Foundation.
- *
- *     This file is distributed in the hope that it will be useful
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
+ * Copyright 2016-2019 Toradex AG
  */
 
 /dts-v1/;
index 7961eb4..826b776 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+// SPDX-License-Identifier: GPL-2.0 OR MIT
 /*
  * Copyright 2016-2018 Toradex AG
  */
index 367eb8c..0462ed2 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+// SPDX-License-Identifier: GPL-2.0 OR MIT
 /*
  * Copyright 2016-2018 Toradex AG
  */
@@ -17,6 +17,7 @@
 
        pcie@1003000 {
                status = "okay";
+
                avddio-pex-supply = <&reg_1v05_vdd>;
                avdd-pex-pll-supply = <&reg_1v05_vdd>;
                avdd-pll-erefe-supply = <&reg_1v05_avdd>;
                       <&{/padctl@7009f000/pads/usb2/lanes/usb2-2}>,
                       <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>;
                phy-names = "usb2-0", "usb3-1", "usb2-1", "usb2-2", "usb3-0";
+
                avddio-pex-supply = <&reg_1v05_vdd>;
                avdd-pll-erefe-supply = <&reg_1v05_avdd>;
                avdd-pll-utmip-supply = <&reg_1v8_vddio>;
        };
 
        padctl@7009f000 {
+               avdd-pll-utmip-supply = <&reg_1v8_vddio>;
+               avdd-pll-erefe-supply = <&reg_1v05_avdd>;
+               avdd-pex-pll-supply = <&reg_1v05_vdd>;
+               hvdd-pex-pll-e-supply = <&reg_module_3v3>;
+
                pads {
                        usb2 {
                                status = "okay";
index 13c93cd..d1e8593 100644 (file)
@@ -1,42 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
- * Copyright 2016-2018 Toradex AG
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     version 2 as published by the Free Software Foundation.
- *
- *     This file is distributed in the hope that it will be useful
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
+ * Copyright 2016-2019 Toradex AG
  */
 
 #include "tegra124.dtsi"
        };
 
        padctl@7009f000 {
+               avdd-pll-utmip-supply = <&reg_1v8_vddio>;
+               avdd-pll-erefe-supply = <&reg_1v05_avdd>;
+               avdd-pex-pll-supply = <&reg_1v05_vdd>;
+               hvdd-pex-pll-e-supply = <&reg_module_3v3>;
+
                pads {
                        usb2 {
                                status = "okay";
index 33bbb1c..d5fd642 100644 (file)
        padctl@7009f000 {
                status = "okay";
 
+               avdd-pll-utmip-supply = <&vddio_1v8>;
+               avdd-pll-erefe-supply = <&avdd_1v05_run>;
+               avdd-pex-pll-supply = <&vdd_1v05_run>;
+               hvdd-pex-pll-e-supply = <&vdd_3v3_lp0>;
+
                pads {
                        usb2 {
                                status = "okay";
index a1acd87..3b10f47 100644 (file)
        padctl@7009f000 {
                status = "okay";
 
+               avdd-pll-utmip-supply = <&vddio_1v8>;
+               avdd-pll-erefe-supply = <&avdd_1v05_run>;
+               avdd-pex-pll-supply = <&vdd_1v05_run>;
+               hvdd-pex-pll-e-supply = <&vdd_3v3_lp0>;
+
                pads {
                        usb2 {
                                status = "okay";
index 4882b61..5d5e6e1 100644 (file)
        };
 
        padctl@7009f000 {
+               avdd-pll-utmip-supply = <&vddio_1v8>;
+               avdd-pll-erefe-supply = <&avdd_1v05_run>;
+               avdd-pex-pll-supply = <&vdd_1v05_run>;
+               hvdd-pex-pll-e-supply = <&vdd_3v3_lp0>;
+
                pads {
                        usb2 {
                                status = "okay";
index d2b553f..e074258 100644 (file)
                reg = <0x6000c000 0x150>; /* AHB Arbitration + Gizmo Controller */
        };
 
+       actmon@6000c800 {
+               compatible = "nvidia,tegra30-actmon";
+               reg = <0x6000c800 0x400>;
+               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&tegra_car TEGRA30_CLK_ACTMON>,
+                        <&tegra_car TEGRA30_CLK_EMC>;
+               clock-names = "actmon", "emc";
+               resets = <&tegra_car TEGRA30_CLK_ACTMON>;
+               reset-names = "actmon";
+       };
+
        gpio: gpio@6000d000 {
                compatible = "nvidia,tegra30-gpio";
                reg = <0x6000d000 0x1000>;
index 445c7dc..9466913 100644 (file)
                        label = "zii:green:debug1";
                        gpios = <&gpio2 18 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "heartbeat";
-                       max-brightness = <1>;
                };
 
                led-fail {
                        label = "zii:red:fail";
                        gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
                        default-state = "off";
-                       max-brightness = <1>;
                };
 
                led-status {
                        label = "zii:green:status";
                        gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
                        default-state = "off";
-                       max-brightness = <1>;
                };
 
                led-debug-a {
                        label = "zii:green:debug_a";
                        gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>;
                        default-state = "off";
-                       max-brightness = <1>;
                };
 
                led-debug-b {
                        label = "zii:green:debug_b";
                        gpios = <&gpio3 15 GPIO_ACTIVE_HIGH>;
                        default-state = "off";
-                       max-brightness = <1>;
                };
        };
 
        bus-num = <1>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_dspi1>;
-       status = "okay";
-
-       m25p128@0 {
+       /*
+        * Some CFU1s come with SPI-NOR chip DNPed, so we leave this
+        * node disabled by default and rely on bootloader to enable
+        * it when appropriate.
+        */
+       status = "disabled";
+
+       flash@0 {
                #address-cells = <1>;
                #size-cells = <1>;
                compatible = "m25p128", "jedec,spi-nor";
        pinctrl-0 = <&pinctrl_i2c0>;
        status = "okay";
 
-       pca9554@22 {
+       io-expander@22 {
                compatible = "nxp,pca9554";
                reg = <0x22>;
                gpio-controller;
                reg = <0x48>;
        };
 
-       at24c04@52 {
+       eeprom@52 {
                compatible = "atmel,24c04";
                reg = <0x52>;
                label = "nvm";
        };
 
-       at24c04@54 {
+       eeprom@54 {
                compatible = "atmel,24c04";
                reg = <0x54>;
                label = "nameplate";
        };
 };
 
+&snvsrtc {
+       status = "disabled";
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart0>;
index bd79e00..48086c5 100644 (file)
@@ -1,45 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
 /*
  * Copyright (C) 2015, 2016 Zodiac Inflight Innovations
- *
- * Based on an original 'vf610-twr.dts' which is Copyright 2015,
- * Freescale Semiconductor, Inc.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     version 2 as published by the Free Software Foundation.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
                gpio-sck  = <&gpio1 12 GPIO_ACTIVE_HIGH>;
                gpio-mosi = <&gpio1 11 GPIO_ACTIVE_HIGH>;
                gpio-miso = <&gpio1 10 GPIO_ACTIVE_HIGH>;
-               cs-gpios  = <&gpio1  9 GPIO_ACTIVE_HIGH
+               cs-gpios  = <&gpio1  9 GPIO_ACTIVE_LOW
                             &gpio1  8 GPIO_ACTIVE_HIGH>;
                num-chipselects = <2>;
 
-               m25p128@0 {
+               flash@0 {
                        compatible = "m25p128", "jedec,spi-nor";
                        #address-cells = <1>;
                        #size-cells = <1>;
        pinctrl-0 = <&pinctrl_i2c0>;
        status = "okay";
 
-       gpio5: pca9554@20 {
+       gpio5: io-expander@20 {
                compatible = "nxp,pca9554";
                reg = <0x20>;
                gpio-controller;
 
        };
 
-       gpio6: pca9554@22 {
+       gpio6: io-expander@22 {
                compatible = "nxp,pca9554";
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_pca9554_22>;
                        #size-cells = <0>;
                        reg = <0>;
 
-                       sfp1: at24c04@50 {
+                       sfp1: eeprom@50 {
                                compatible = "atmel,24c02";
                                reg = <0x50>;
                        };
                        #size-cells = <0>;
                        reg = <1>;
 
-                       sfp2: at24c04@50 {
+                       sfp2: eeprom@50 {
                                compatible = "atmel,24c02";
                                reg = <0x50>;
                        };
                        #size-cells = <0>;
                        reg = <2>;
 
-                       sfp3: at24c04@50 {
+                       sfp3: eeprom@50 {
                                compatible = "atmel,24c02";
                                reg = <0x50>;
                        };
                        #size-cells = <0>;
                        reg = <3>;
 
-                       sfp4: at24c04@50 {
+                       sfp4: eeprom@50 {
                                compatible = "atmel,24c02";
                                reg = <0x50>;
                        };
index 6f4a560..778e02c 100644 (file)
@@ -1,45 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
 /*
  * Copyright (C) 2015, 2016 Zodiac Inflight Innovations
- *
- * Based on an original 'vf610-twr.dts' which is Copyright 2015,
- * Freescale Semiconductor, Inc.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     version 2 as published by the Free Software Foundation.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
        status = "okay";
        spi-num-chipselects = <2>;
 
-       m25p128@0 {
+       flash@0 {
                compatible = "m25p128", "jedec,spi-nor";
                #address-cells = <1>;
                #size-cells = <1>;
         *    P1 - WE2_CMD
         *    P2 - WE2_CLK
         */
-       gpio5: pca9557@18 {
+       gpio5: io-expander@18 {
                compatible = "nxp,pca9557";
                reg = <0x18>;
                gpio-controller;
         *     IO0 - WE1_CLK
         *     IO1 - WE1_CMD
         */
-       gpio7: pca9554@22 {
+       gpio7: io-expander@22 {
                compatible = "nxp,pca9554";
                reg = <0x22>;
                gpio-controller;
 };
 
 &i2c1 {
-       at24mac602@50 {
+       eeprom@50 {
                compatible = "atmel,24c02";
                reg = <0x50>;
                read-only;
index 19eb4a8..0507e6d 100644 (file)
        pinctrl-names = "default", "gpio";
        pinctrl-0 = <&pinctrl_i2c0>;
        pinctrl-1 = <&pinctrl_i2c0_gpio>;
-       scl-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+       scl-gpios = <&gpio1 4 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
        sda-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
        status = "okay";
 
                reg = <0x48>;
        };
 
-       at24c04@50 {
+       eeprom@50 {
                compatible = "atmel,24c04";
                reg = <0x50>;
        };
 
-       at24c04@52 {
+       eeprom@52 {
                compatible = "atmel,24c04";
                reg = <0x52>;
        };
index de6dfa5..d7019e8 100644 (file)
        pinctrl-0 = <&pinctrl_i2c0>;
        status = "okay";
 
-       gpio5: pca9554@20 {
+       gpio5: io-expander@20 {
                compatible = "nxp,pca9554";
                reg = <0x20>;
                gpio-controller;
                #gpio-cells = <2>;
        };
 
-       gpio6: pca9554@22 {
+       gpio6: io-expander@22 {
                compatible = "nxp,pca9554";
                reg = <0x22>;
                gpio-controller;
                reg = <0x48>;
        };
 
-       at24c04@50 {
+       eeprom@50 {
                compatible = "atmel,24c04";
                reg = <0x50>;
        };
 
-       at24c04@52 {
+       eeprom@52 {
                compatible = "atmel,24c04";
                reg = <0x52>;
        };
                reg = <0x4f>;
        };
 
-       gpio7: pca9555@23 {
+       gpio7: io-expander@23 {
                compatible = "nxp,pca9555";
                gpio-controller;
                #gpio-cells = <2>;
        };
 };
 
+&snvsrtc {
+       status = "disabled";
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart0>;
diff --git a/arch/arm/boot/dts/vf610-zii-spb4.dts b/arch/arm/boot/dts/vf610-zii-spb4.dts
new file mode 100644 (file)
index 0000000..9dde83c
--- /dev/null
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+/*
+ * Device tree file for ZII's SPB4 board
+ *
+ * SPB - Seat Power Box
+ *
+ * Copyright (C) 2019 Zodiac Inflight Innovations
+ */
+
+/dts-v1/;
+#include "vf610.dtsi"
+
+/ {
+       model = "ZII VF610 SPB4 Board";
+       compatible = "zii,vf610spb4", "zii,vf610dev", "fsl,vf610";
+
+       chosen {
+               stdout-path = &uart0;
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x80000000 0x20000000>;
+       };
+
+       gpio-leds {
+               compatible = "gpio-leds";
+               pinctrl-0 = <&pinctrl_leds_debug>;
+               pinctrl-names = "default";
+
+               led-debug {
+                       label = "zii:green:debug1";
+                       gpios = <&gpio2 18 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       reg_vcc_3v3_mcu: regulator-vcc-3v3-mcu {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_3v3_mcu";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+};
+
+&adc0 {
+       vref-supply = <&reg_vcc_3v3_mcu>;
+       status = "okay";
+};
+
+&adc1 {
+       vref-supply = <&reg_vcc_3v3_mcu>;
+       status = "okay";
+};
+
+&dspi1 {
+       bus-num = <1>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_dspi1>;
+       status = "okay";
+
+       flash@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "m25p128", "jedec,spi-nor";
+               reg = <0>;
+               spi-max-frequency = <50000000>;
+       };
+};
+
+&edma0 {
+       status = "okay";
+};
+
+&edma1 {
+       status = "okay";
+};
+
+&esdhc0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc0>;
+       bus-width = <8>;
+       non-removable;
+       no-1-8-v;
+       keep-power-in-suspend;
+       no-sdio;
+       no-sd;
+       status = "okay";
+};
+
+&esdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc1>;
+       bus-width = <4>;
+       no-sdio;
+       status = "okay";
+};
+
+&fec1 {
+       phy-mode = "rmii";
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec1>;
+       status = "okay";
+
+       fixed-link {
+               speed = <100>;
+               full-duplex;
+       };
+
+       mdio1: mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "okay";
+
+               switch0: switch0@0 {
+                       compatible = "marvell,mv88e6190";
+                       pinctrl-0 = <&pinctrl_gpio_switch0>;
+                       pinctrl-names = "default";
+                       reg = <0>;
+                       eeprom-length = <65536>;
+                       reset-gpios = <&gpio3 11 GPIO_ACTIVE_LOW>;
+                       interrupt-parent = <&gpio3>;
+                       interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       label = "cpu";
+                                       ethernet = <&fec1>;
+
+                                       fixed-link {
+                                               speed = <100>;
+                                               full-duplex;
+                                       };
+                               };
+
+                               port@1 {
+                                       reg = <1>;
+                                       label = "eth_cu_1000_1";
+                               };
+
+                               port@2 {
+                                       reg = <2>;
+                                       label = "eth_cu_1000_2";
+                               };
+
+                               port@3 {
+                                       reg = <3>;
+                                       label = "eth_cu_1000_3";
+                               };
+
+                               port@4 {
+                                       reg = <4>;
+                                       label = "eth_cu_1000_4";
+                               };
+
+                               port@5 {
+                                       reg = <5>;
+                                       label = "eth_cu_1000_5";
+                               };
+
+                               port@6 {
+                                       reg = <6>;
+                                       label = "eth_cu_1000_6";
+                               };
+                       };
+               };
+       };
+};
+
+&i2c0 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c0>;
+       status = "okay";
+
+       io-expander@22 {
+               compatible = "nxp,pca9554";
+               reg = <0x22>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       eeprom@50 {
+               compatible = "atmel,24c04";
+               reg = <0x50>;
+               label = "nameplate";
+       };
+
+       eeprom@52 {
+               compatible = "atmel,24c04";
+               reg = <0x52>;
+       };
+};
+
+&snvsrtc {
+       status = "disabled";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart0>;
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+
+       rave-sp {
+               compatible = "zii,rave-sp-rdu2";
+               current-speed = <1000000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               watchdog {
+                       compatible = "zii,rave-sp-watchdog";
+               };
+
+               eeprom@a3 {
+                       compatible = "zii,rave-sp-eeprom";
+                       reg = <0xa3 0x4000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       zii,eeprom-name = "main-eeprom";
+               };
+       };
+};
+
+&uart3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart3>;
+       status = "okay";
+};
+
+&wdoga5 {
+       status = "disabled";
+};
+
+&iomuxc {
+       pinctrl_dspi1: dspi1grp {
+               fsl,pins = <
+                       VF610_PAD_PTD5__DSPI1_CS0               0x1182
+                       VF610_PAD_PTD4__DSPI1_CS1               0x1182
+                       VF610_PAD_PTC6__DSPI1_SIN               0x1181
+                       VF610_PAD_PTC7__DSPI1_SOUT              0x1182
+                       VF610_PAD_PTC8__DSPI1_SCK               0x1182
+               >;
+       };
+
+       pinctrl_esdhc0: esdhc0grp {
+               fsl,pins = <
+                       VF610_PAD_PTC0__ESDHC0_CLK              0x31ef
+                       VF610_PAD_PTC1__ESDHC0_CMD              0x31ef
+                       VF610_PAD_PTC2__ESDHC0_DAT0             0x31ef
+                       VF610_PAD_PTC3__ESDHC0_DAT1             0x31ef
+                       VF610_PAD_PTC4__ESDHC0_DAT2             0x31ef
+                       VF610_PAD_PTC5__ESDHC0_DAT3             0x31ef
+                       VF610_PAD_PTD23__ESDHC0_DAT4            0x31ef
+                       VF610_PAD_PTD22__ESDHC0_DAT5            0x31ef
+                       VF610_PAD_PTD21__ESDHC0_DAT6            0x31ef
+                       VF610_PAD_PTD20__ESDHC0_DAT7            0x31ef
+               >;
+       };
+
+       pinctrl_esdhc1: esdhc1grp {
+               fsl,pins = <
+                       VF610_PAD_PTA24__ESDHC1_CLK             0x31ef
+                       VF610_PAD_PTA25__ESDHC1_CMD             0x31ef
+                       VF610_PAD_PTA26__ESDHC1_DAT0            0x31ef
+                       VF610_PAD_PTA27__ESDHC1_DAT1            0x31ef
+                       VF610_PAD_PTA28__ESDHC1_DATA2           0x31ef
+                       VF610_PAD_PTA29__ESDHC1_DAT3            0x31ef
+               >;
+       };
+
+       pinctrl_fec1: fec1grp {
+               fsl,pins = <
+                       VF610_PAD_PTA6__RMII_CLKIN              0x30d1
+                       VF610_PAD_PTC9__ENET_RMII1_MDC          0x30d2
+                       VF610_PAD_PTC10__ENET_RMII1_MDIO        0x30d3
+                       VF610_PAD_PTC11__ENET_RMII1_CRS         0x30d1
+                       VF610_PAD_PTC12__ENET_RMII1_RXD1        0x30d1
+                       VF610_PAD_PTC13__ENET_RMII1_RXD0        0x30d1
+                       VF610_PAD_PTC14__ENET_RMII1_RXER        0x30d1
+                       VF610_PAD_PTC15__ENET_RMII1_TXD1        0x30d2
+                       VF610_PAD_PTC16__ENET_RMII1_TXD0        0x30d2
+                       VF610_PAD_PTC17__ENET_RMII1_TXEN        0x30d2
+               >;
+       };
+
+       pinctrl_gpio_switch0: pinctrl-gpio-switch0 {
+               fsl,pins = <
+                       VF610_PAD_PTE2__GPIO_107                0x31c2
+                       VF610_PAD_PTB28__GPIO_98                0x219d
+               >;
+       };
+
+       pinctrl_i2c0: i2c0grp {
+               fsl,pins = <
+                       VF610_PAD_PTB14__I2C0_SCL               0x37ff
+                       VF610_PAD_PTB15__I2C0_SDA               0x37ff
+               >;
+       };
+
+       pinctrl_i2c1: i2c1grp {
+               fsl,pins = <
+                       VF610_PAD_PTB16__I2C1_SCL               0x37ff
+                       VF610_PAD_PTB17__I2C1_SDA               0x37ff
+               >;
+       };
+
+       pinctrl_leds_debug: pinctrl-leds-debug {
+               fsl,pins = <
+                       VF610_PAD_PTD3__GPIO_82                 0x31c2
+               >;
+       };
+
+       pinctrl_uart0: uart0grp {
+               fsl,pins = <
+                       VF610_PAD_PTB10__UART0_TX               0x21a2
+                       VF610_PAD_PTB11__UART0_RX               0x21a1
+               >;
+       };
+
+       pinctrl_uart1: uart1grp {
+               fsl,pins = <
+                       VF610_PAD_PTB23__UART1_TX               0x21a2
+                       VF610_PAD_PTB24__UART1_RX               0x21a1
+               >;
+       };
+
+       pinctrl_uart2: uart2grp {
+               fsl,pins = <
+                       VF610_PAD_PTD0__UART2_TX                0x21a2
+                       VF610_PAD_PTD1__UART2_RX                0x21a1
+               >;
+       };
+
+       pinctrl_uart3: uart3grp {
+               fsl,pins = <
+                       VF610_PAD_PTA30__UART3_TX               0x21a2
+                       VF610_PAD_PTA31__UART3_RX               0x21a1
+               >;
+       };
+};
index 2b10672..847c585 100644 (file)
@@ -37,7 +37,6 @@
                        label = "zii:green:debug1";
                        gpios = <&gpio2 18 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "heartbeat";
-                       max-brightness = <1>;
                };
        };
 
        };
 };
 
+&snvsrtc {
+       status = "disabled";
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart0>;
index 0d9fe5a..453fce8 100644 (file)
@@ -37,7 +37,6 @@
                        label = "zii:green:debug1";
                        gpios = <&gpio2 18 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "heartbeat";
-                       max-brightness = <1>;
                };
        };
 
@@ -70,7 +69,7 @@
         */
        status = "disabled";
 
-       m25p128@0 {
+       flash@0 {
                #address-cells = <1>;
                #size-cells = <1>;
                compatible = "m25p128", "jedec,spi-nor";
        pinctrl-0 = <&pinctrl_i2c0>;
        status = "okay";
 
-       gpio6: pca9505@22 {
+       gpio6: io-expander@22 {
                compatible = "nxp,pca9554";
                reg = <0x22>;
                gpio-controller;
                reg = <0x48>;
        };
 
-       at24c04@50 {
+       eeprom@50 {
                compatible = "atmel,24c04";
                reg = <0x50>;
                label = "nameplate";
        };
 
-       at24c04@52 {
+       eeprom@52 {
                compatible = "atmel,24c04";
                reg = <0x52>;
        };
 };
 
+&snvsrtc {
+       status = "disabled";
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart0>;
        };
 };
 
+&wdoga5 {
+       status = "disabled";
+};
+
 &iomuxc {
        pinctrl_dspi1: dspi1grp {
                fsl,pins = <
index 45412d2..179ca87 100644 (file)
@@ -32,7 +32,7 @@
 #include <mach/hardware.h>
 #include <asm/mach/irq.h>
 #include <asm/mach-types.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <asm/hardware/sa1111.h>
 
index d635edf..c95c542 100644 (file)
@@ -9,7 +9,6 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_EXYNOS=y
 CONFIG_ARCH_EXYNOS3=y
-CONFIG_EXYNOS5420_MCPM=y
 CONFIG_SMP=y
 CONFIG_BIG_LITTLE=y
 CONFIG_NR_CPUS=8
index 8b0f7c4..7d26ca0 100644 (file)
@@ -152,7 +152,7 @@ CONFIG_SPI_S3C24XX=y
 CONFIG_SPI_SPIDEV=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_SENSORS_LM75=y
-CONFIG_THERMAL=m
+CONFIG_THERMAL=y
 CONFIG_WATCHDOG=y
 CONFIG_S3C2410_WATCHDOG=y
 CONFIG_FB=y
index b7b1cd0..6b748f2 100644 (file)
@@ -5,10 +5,6 @@ CONFIG_CGROUPS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_CMDLINE_PARTITION=y
 CONFIG_ARCH_VIRT=y
 CONFIG_ARCH_ALPINE=y
 CONFIG_ARCH_ARTPEC=y
@@ -33,7 +29,6 @@ CONFIG_MACH_BERLIN_BG2CD=y
 CONFIG_MACH_BERLIN_BG2Q=y
 CONFIG_ARCH_DIGICOLOR=y
 CONFIG_ARCH_EXYNOS=y
-CONFIG_EXYNOS5420_MCPM=y
 CONFIG_ARCH_HIGHBANK=y
 CONFIG_ARCH_HISI=y
 CONFIG_ARCH_HI3xxx=y
@@ -48,8 +43,8 @@ CONFIG_SOC_IMX6Q=y
 CONFIG_SOC_IMX6SL=y
 CONFIG_SOC_IMX6SX=y
 CONFIG_SOC_IMX6UL=y
-CONFIG_SOC_IMX7D=y
 CONFIG_SOC_LS1021A=y
+CONFIG_SOC_IMX7D=y
 CONFIG_SOC_VF610=y
 CONFIG_ARCH_KEYSTONE=y
 CONFIG_ARCH_MEDIATEK=y
@@ -76,24 +71,6 @@ CONFIG_ARCH_MSM8960=y
 CONFIG_ARCH_MSM8974=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_ARCH_RENESAS=y
-CONFIG_ARCH_EMEV2=y
-CONFIG_ARCH_R7S72100=y
-CONFIG_ARCH_R7S9210=y
-CONFIG_ARCH_R8A73A4=y
-CONFIG_ARCH_R8A7740=y
-CONFIG_ARCH_R8A7743=y
-CONFIG_ARCH_R8A7744=y
-CONFIG_ARCH_R8A7745=y
-CONFIG_ARCH_R8A77470=y
-CONFIG_ARCH_R8A7778=y
-CONFIG_ARCH_R8A7779=y
-CONFIG_ARCH_R8A7790=y
-CONFIG_ARCH_R8A7791=y
-CONFIG_ARCH_R8A7792=y
-CONFIG_ARCH_R8A7793=y
-CONFIG_ARCH_R8A7794=y
-CONFIG_ARCH_R9A06G032=y
-CONFIG_ARCH_SH73A0=y
 CONFIG_ARCH_SOCFPGA=y
 CONFIG_PLAT_SPEAR=y
 CONFIG_ARCH_SPEAR13XX=y
@@ -109,16 +86,6 @@ CONFIG_ARCH_VEXPRESS=y
 CONFIG_ARCH_VEXPRESS_TC2_PM=y
 CONFIG_ARCH_WM8850=y
 CONFIG_ARCH_ZYNQ=y
-CONFIG_PCIEPORTBUS=y
-CONFIG_PCI_MVEBU=y
-CONFIG_PCI_TEGRA=y
-CONFIG_PCI_RCAR_GEN2=y
-CONFIG_PCIE_RCAR=y
-CONFIG_PCI_DRA7XX_EP=y
-CONFIG_PCI_KEYSTONE=y
-CONFIG_PCI_ENDPOINT=y
-CONFIG_PCI_ENDPOINT_CONFIGFS=y
-CONFIG_PCI_EPF_TEST=m
 CONFIG_SMP=y
 CONFIG_NR_CPUS=16
 CONFIG_SECCOMP=y
@@ -141,6 +108,29 @@ CONFIG_ARM_CPUIDLE=y
 CONFIG_ARM_ZYNQ_CPUIDLE=y
 CONFIG_ARM_EXYNOS_CPUIDLE=y
 CONFIG_KERNEL_MODE_NEON=y
+CONFIG_RASPBERRYPI_FIRMWARE=y
+CONFIG_TRUSTED_FOUNDATIONS=y
+CONFIG_BCM47XX_NVRAM=y
+CONFIG_BCM47XX_SPROM=y
+CONFIG_EFI_VARS=m
+CONFIG_EFI_CAPSULE_LOADER=m
+CONFIG_ARM_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM_NEON=m
+CONFIG_CRYPTO_SHA1_ARM_CE=m
+CONFIG_CRYPTO_SHA2_ARM_CE=m
+CONFIG_CRYPTO_SHA512_ARM=m
+CONFIG_CRYPTO_AES_ARM=m
+CONFIG_CRYPTO_AES_ARM_BS=m
+CONFIG_CRYPTO_AES_ARM_CE=m
+CONFIG_CRYPTO_GHASH_ARM_CE=m
+CONFIG_CRYPTO_CRC32_ARM_CE=m
+CONFIG_CRYPTO_CHACHA20_NEON=m
+CONFIG_GCC_PLUGINS=y
+CONFIG_GCC_PLUGIN_STRUCTLEAK=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_CMDLINE_PARTITION=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -175,14 +165,27 @@ CONFIG_MAC80211=m
 CONFIG_RFKILL=y
 CONFIG_RFKILL_INPUT=y
 CONFIG_RFKILL_GPIO=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCI_MVEBU=y
+CONFIG_PCI_TEGRA=y
+CONFIG_PCI_RCAR_GEN2=y
+CONFIG_PCIE_RCAR=y
+CONFIG_PCI_DRA7XX_EP=y
+CONFIG_PCI_KEYSTONE=y
+CONFIG_PCI_ENDPOINT=y
+CONFIG_PCI_ENDPOINT_CONFIGFS=y
+CONFIG_PCI_EPF_TEST=m
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_OMAP_OCP2SCP=y
 CONFIG_SIMPLE_PM_BUS=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_M25P80=y
 CONFIG_MTD_RAW_NAND=y
 CONFIG_MTD_NAND_DENALI_DT=y
@@ -195,7 +198,6 @@ CONFIG_MTD_NAND_BRCMNAND=y
 CONFIG_MTD_NAND_VF610_NFC=y
 CONFIG_MTD_NAND_DAVINCI=y
 CONFIG_MTD_SPI_NOR=y
-CONFIG_SPI_FSL_QUADSPI=m
 CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
@@ -230,7 +232,6 @@ CONFIG_VIRTIO_NET=y
 CONFIG_B53_SPI_DRIVER=m
 CONFIG_B53_MDIO_DRIVER=m
 CONFIG_B53_MMAP_DRIVER=m
-CONFIG_B53_SRAB_DRIVER=m
 CONFIG_NET_DSA_BCM_SF2=m
 CONFIG_SUN4I_EMAC=y
 CONFIG_BCMGENET=m
@@ -259,7 +260,6 @@ CONFIG_BROADCOM_PHY=y
 CONFIG_ICPLUS_PHY=y
 CONFIG_MARVELL_PHY=y
 CONFIG_MICREL_PHY=y
-CONFIG_REALTEK_PHY=y
 CONFIG_ROCKCHIP_PHY=y
 CONFIG_SMSC_PHY=y
 CONFIG_USB_PEGASUS=y
@@ -288,6 +288,7 @@ CONFIG_MOUSE_ELAN_I2C=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ADC=m
 CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_ELAN=m
 CONFIG_TOUCHSCREEN_MMS114=m
 CONFIG_TOUCHSCREEN_WM97XX=m
 CONFIG_TOUCHSCREEN_ST1232=m
@@ -299,6 +300,7 @@ CONFIG_INPUT_MAX8997_HAPTIC=m
 CONFIG_INPUT_CPCAP_PWRBUTTON=m
 CONFIG_INPUT_AXP20X_PEK=m
 CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_STPMIC1_ONKEY=y
 CONFIG_SERIO_AMBAKMI=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
@@ -349,6 +351,8 @@ CONFIG_SERIAL_DEV_BUS=y
 CONFIG_VIRTIO_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_ST=y
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS_I2C_INFINEON=m
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_ARB_GPIO_CHALLENGE=m
 CONFIG_I2C_MUX_PCA954x=y
@@ -386,6 +390,7 @@ CONFIG_SPI_BCM2835=y
 CONFIG_SPI_BCM2835AUX=y
 CONFIG_SPI_CADENCE=y
 CONFIG_SPI_DAVINCI=y
+CONFIG_SPI_FSL_QUADSPI=m
 CONFIG_SPI_GPIO=m
 CONFIG_SPI_FSL_DSPI=m
 CONFIG_SPI_OMAP24XX=y
@@ -444,9 +449,11 @@ CONFIG_POWER_RESET_RMOBILE=y
 CONFIG_BATTERY_ACT8945A=y
 CONFIG_BATTERY_CPCAP=m
 CONFIG_BATTERY_SBS=y
+CONFIG_BATTERY_BQ27XXX=m
 CONFIG_AXP20X_POWER=m
 CONFIG_BATTERY_MAX17040=m
 CONFIG_BATTERY_MAX17042=m
+CONFIG_CHARGER_GPIO=m
 CONFIG_CHARGER_CPCAP=m
 CONFIG_CHARGER_MAX14577=m
 CONFIG_CHARGER_MAX77693=m
@@ -486,6 +493,7 @@ CONFIG_TEGRA_WATCHDOG=m
 CONFIG_MESON_WATCHDOG=y
 CONFIG_DIGICOLOR_WATCHDOG=y
 CONFIG_RENESAS_WDT=m
+CONFIG_STPMIC1_WATCHDOG=y
 CONFIG_BCM47XX_WDT=y
 CONFIG_BCM2835_WDT=y
 CONFIG_BCM_KONA_WDT=y
@@ -505,6 +513,7 @@ CONFIG_MFD_AXP20X_RSB=y
 CONFIG_MFD_CROS_EC=m
 CONFIG_CROS_EC_I2C=m
 CONFIG_CROS_EC_SPI=m
+CONFIG_MFD_CROS_EC_CHARDEV=m
 CONFIG_MFD_DA9063=m
 CONFIG_MFD_MAX14577=y
 CONFIG_MFD_MAX77686=y
@@ -527,6 +536,7 @@ CONFIG_MFD_TPS65218=y
 CONFIG_MFD_TPS6586X=y
 CONFIG_MFD_TPS65910=y
 CONFIG_MFD_STM32_LPTIMER=m
+CONFIG_MFD_STPMIC1=y
 CONFIG_REGULATOR_ACT8865=y
 CONFIG_REGULATOR_ACT8945A=y
 CONFIG_REGULATOR_ANATOP=y
@@ -559,6 +569,7 @@ CONFIG_REGULATOR_RN5T618=y
 CONFIG_REGULATOR_S2MPS11=y
 CONFIG_REGULATOR_S5M8767=y
 CONFIG_REGULATOR_STM32_VREFBUF=m
+CONFIG_REGULATOR_STPMIC1=y
 CONFIG_REGULATOR_TI_ABB=y
 CONFIG_REGULATOR_TPS51632=y
 CONFIG_REGULATOR_TPS62360=y
@@ -579,8 +590,6 @@ CONFIG_MEDIA_USB_SUPPORT=y
 CONFIG_USB_VIDEO_CLASS=m
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_VIDEO_STM32_DCMI=m
-CONFIG_SOC_CAMERA=m
-CONFIG_SOC_CAMERA_PLATFORM=m
 CONFIG_VIDEO_SAMSUNG_EXYNOS4_IS=m
 CONFIG_VIDEO_S5P_FIMC=m
 CONFIG_VIDEO_S5P_MIPI_CSIS=m
@@ -626,10 +635,12 @@ CONFIG_DRM_RCAR_LVDS=y
 CONFIG_DRM_SUN4I=m
 CONFIG_DRM_FSL_DCU=m
 CONFIG_DRM_TEGRA=y
-CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m
-CONFIG_DRM_PANEL_RAYDIUM_RM68200=m
+CONFIG_DRM_STM=m
+CONFIG_DRM_STM_DSI=m
 CONFIG_DRM_PANEL_SIMPLE=y
 CONFIG_DRM_PANEL_SAMSUNG_LD9040=m
+CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m
+CONFIG_DRM_PANEL_RAYDIUM_RM68200=m
 CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=m
 CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=m
 CONFIG_DRM_DUMB_VGA_DAC=m
@@ -641,8 +652,6 @@ CONFIG_DRM_TOSHIBA_TC358764=m
 CONFIG_DRM_I2C_ADV7511=m
 CONFIG_DRM_I2C_ADV7511_AUDIO=y
 CONFIG_DRM_STI=m
-CONFIG_DRM_STM=m
-CONFIG_DRM_STM_DSI=m
 CONFIG_DRM_VC4=m
 CONFIG_DRM_ETNAVIV=m
 CONFIG_DRM_MXSFB=m
@@ -701,7 +710,6 @@ CONFIG_SND_SOC_SGTL5000=m
 CONFIG_SND_SOC_SPDIF=m
 CONFIG_SND_SOC_STI_SAS=m
 CONFIG_SND_SOC_WM8978=m
-CONFIG_SND_SIMPLE_SCU_CARD=m
 CONFIG_USB=y
 CONFIG_USB_OTG=y
 CONFIG_USB_XHCI_HCD=y
@@ -877,7 +885,6 @@ CONFIG_UNIPHIER_MDMAC=y
 CONFIG_XILINX_DMA=y
 CONFIG_QCOM_BAM_DMA=y
 CONFIG_DW_DMAC=y
-CONFIG_SH_DMAE=y
 CONFIG_RCAR_DMAC=y
 CONFIG_RENESAS_USB_DMAC=m
 CONFIG_VIRTIO_PCI=y
@@ -910,6 +917,24 @@ CONFIG_QCOM_GSBI=y
 CONFIG_QCOM_PM=y
 CONFIG_QCOM_SMD_RPM=m
 CONFIG_QCOM_WCNSS_CTRL=m
+CONFIG_ARCH_EMEV2=y
+CONFIG_ARCH_R7S72100=y
+CONFIG_ARCH_R7S9210=y
+CONFIG_ARCH_R8A73A4=y
+CONFIG_ARCH_R8A7740=y
+CONFIG_ARCH_R8A7743=y
+CONFIG_ARCH_R8A7744=y
+CONFIG_ARCH_R8A7745=y
+CONFIG_ARCH_R8A77470=y
+CONFIG_ARCH_R8A7778=y
+CONFIG_ARCH_R8A7779=y
+CONFIG_ARCH_R8A7790=y
+CONFIG_ARCH_R8A7791=y
+CONFIG_ARCH_R8A7792=y
+CONFIG_ARCH_R8A7793=y
+CONFIG_ARCH_R8A7794=y
+CONFIG_ARCH_R9A06G032=y
+CONFIG_ARCH_SH73A0=y
 CONFIG_ROCKCHIP_PM_DOMAINS=y
 CONFIG_ARCH_TEGRA_2x_SOC=y
 CONFIG_ARCH_TEGRA_3x_SOC=y
@@ -925,6 +950,7 @@ CONFIG_AT91_SAMA5D2_ADC=m
 CONFIG_BERLIN2_ADC=m
 CONFIG_CPCAP_ADC=m
 CONFIG_EXYNOS_ADC=m
+CONFIG_MESON_SARADC=m
 CONFIG_STM32_ADC_CORE=m
 CONFIG_STM32_ADC=m
 CONFIG_STM32_DFSDM_ADC=m
@@ -932,8 +958,12 @@ CONFIG_VF610_ADC=m
 CONFIG_XILINX_XADC=y
 CONFIG_STM32_LPTIMER_CNT=m
 CONFIG_STM32_DAC=m
+CONFIG_ROCKCHIP_SARADC=m
+CONFIG_IIO_CROS_EC_SENSORS_CORE=m
+CONFIG_IIO_CROS_EC_SENSORS=m
 CONFIG_MPU3050_I2C=y
 CONFIG_CM36651=m
+CONFIG_IIO_CROS_EC_LIGHT_PROX=m
 CONFIG_SENSORS_ISL29018=y
 CONFIG_SENSORS_ISL29028=y
 CONFIG_AK8975=y
@@ -969,24 +999,21 @@ CONFIG_PHY_RCAR_GEN2=m
 CONFIG_PHY_ROCKCHIP_DP=m
 CONFIG_PHY_ROCKCHIP_USB=y
 CONFIG_PHY_SAMSUNG_USB2=m
+CONFIG_PHY_UNIPHIER_USB2=y
+CONFIG_PHY_UNIPHIER_USB3=y
 CONFIG_PHY_MIPHY28LP=y
 CONFIG_PHY_STIH407_USB=y
 CONFIG_PHY_STM32_USBPHYC=y
 CONFIG_PHY_TEGRA_XUSB=y
 CONFIG_PHY_DM816X_USB=m
-CONFIG_PHY_UNIPHIER_USB3=y
-CONFIG_PHY_UNIPHIER_USB2=y
 CONFIG_OMAP_USB2=y
 CONFIG_TI_PIPE3=y
 CONFIG_TWL4030_USB=m
+CONFIG_MESON_MX_EFUSE=m
+CONFIG_ROCKCHIP_EFUSE=m
 CONFIG_NVMEM_IMX_OCOTP=y
 CONFIG_NVMEM_SUNXI_SID=y
 CONFIG_NVMEM_VF610_OCOTP=y
-CONFIG_RASPBERRYPI_FIRMWARE=y
-CONFIG_BCM47XX_NVRAM=y
-CONFIG_BCM47XX_SPROM=y
-CONFIG_EFI_VARS=m
-CONFIG_EFI_CAPSULE_LOADER=m
 CONFIG_EXT4_FS=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_MSDOS_FS=y
@@ -1008,8 +1035,6 @@ CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=y
-CONFIG_PRINTK_TIME=y
-CONFIG_MAGIC_SYSRQ=y
 CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
@@ -1023,16 +1048,6 @@ CONFIG_CRYPTO_DEV_ATMEL_TDES=m
 CONFIG_CRYPTO_DEV_ATMEL_SHA=m
 CONFIG_CRYPTO_DEV_SUN4I_SS=m
 CONFIG_CRYPTO_DEV_ROCKCHIP=m
-CONFIG_ARM_CRYPTO=y
-CONFIG_CRYPTO_SHA1_ARM_NEON=m
-CONFIG_CRYPTO_SHA1_ARM_CE=m
-CONFIG_CRYPTO_SHA2_ARM_CE=m
-CONFIG_CRYPTO_SHA512_ARM=m
-CONFIG_CRYPTO_AES_ARM=m
-CONFIG_CRYPTO_AES_ARM_BS=m
-CONFIG_CRYPTO_AES_ARM_CE=m
-CONFIG_CRYPTO_GHASH_ARM_CE=m
-CONFIG_CRYPTO_CRC32_ARM_CE=m
-CONFIG_CRYPTO_CHACHA20_NEON=m
-CONFIG_GCC_PLUGINS=y
-CONFIG_GCC_PLUGIN_STRUCTLEAK=y
+CONFIG_CMA_SIZE_MBYTES=64
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
index f6d24d7..07ebbdc 100644 (file)
@@ -387,7 +387,7 @@ CONFIG_SENSORS_LM75=m
 CONFIG_SENSORS_LM90=m
 CONFIG_SENSORS_LM95245=m
 CONFIG_SENSORS_NTC_THERMISTOR=m
-CONFIG_THERMAL=m
+CONFIG_THERMAL=y
 CONFIG_WATCHDOG=y
 CONFIG_XILINX_WATCHDOG=m
 CONFIG_SA1100_WATCHDOG=m
index 4c50b53..c185475 100644 (file)
@@ -50,7 +50,8 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_IPV6 is not set
-CONFIG_CFG80211=y
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
 CONFIG_RFKILL=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
@@ -72,6 +73,8 @@ CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_ATA=y
 CONFIG_SATA_AHCI=y
 CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_ATL1C=y
@@ -85,6 +88,7 @@ CONFIG_SLIP_MODE_SLIP6=y
 CONFIG_USB_USBNET=y
 # CONFIG_USB_NET_AX8817X is not set
 # CONFIG_USB_NET_ZAURUS is not set
+CONFIG_WCN36XX=m
 CONFIG_BRCMFMAC=m
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
@@ -94,6 +98,8 @@ CONFIG_KEYBOARD_PMIC8XXX=y
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MSM_VIBRATOR=m
+CONFIG_INPUT_PM8941_PWRKEY=m
 CONFIG_INPUT_PM8XXX_VIBRATOR=y
 CONFIG_INPUT_PMIC8XXX_PWRKEY=y
 CONFIG_INPUT_UINPUT=y
@@ -127,6 +133,7 @@ CONFIG_GPIO_SYSFS=y
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_MSM=y
 CONFIG_CHARGER_QCOM_SMBB=y
+CONFIG_CHARGER_BQ24190=m
 CONFIG_THERMAL=y
 CONFIG_QCOM_TSENS=y
 CONFIG_MFD_PM8XXX=y
@@ -226,7 +233,11 @@ CONFIG_IIO=y
 CONFIG_IIO_BUFFER_CB=y
 CONFIG_IIO_SW_TRIGGER=y
 CONFIG_KXSD9=y
+CONFIG_QCOM_SPMI_IADC=m
+CONFIG_QCOM_SPMI_VADC=m
 CONFIG_MPU3050_I2C=y
+CONFIG_INV_MPU6050_I2C=m
+CONFIG_TSL2772=m
 CONFIG_AK8975=y
 CONFIG_IIO_HRTIMER_TRIGGER=y
 CONFIG_BMP280=y
index 9b0efac..eb02ba9 100644 (file)
@@ -43,11 +43,13 @@ CONFIG_PCI_RCAR_GEN2=y
 CONFIG_PCIE_RCAR=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_DMA_CMA=y
-CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_SIMPLE_PM_BUS=y
 CONFIG_MTD=y
 CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_M25P80=y
 CONFIG_MTD_SPI_NOR=y
 CONFIG_EEPROM_AT24=y
@@ -123,7 +125,6 @@ CONFIG_VIDEO_ADV7604=y
 CONFIG_VIDEO_ML86V7667=y
 CONFIG_DRM=y
 CONFIG_DRM_RCAR_DU=y
-CONFIG_DRM_RCAR_LVDS=y
 CONFIG_DRM_DUMB_VGA_DAC=y
 CONFIG_DRM_SII902X=y
 CONFIG_DRM_I2C_ADV7511=y
@@ -141,12 +142,13 @@ CONFIG_SND_SOC_RCAR=y
 CONFIG_SND_SOC_AK4642=y
 CONFIG_SND_SOC_SGTL5000=y
 CONFIG_SND_SOC_WM8978=y
-CONFIG_SND_SIMPLE_SCU_CARD=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_PLATFORM=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_R8A66597_HCD=y
 CONFIG_USB_RENESAS_USBHS=y
 CONFIG_USB_GADGET=y
@@ -197,6 +199,7 @@ CONFIG_PWM_RENESAS_TPU=y
 CONFIG_RESET_CONTROLLER=y
 CONFIG_GENERIC_PHY=y
 CONFIG_PHY_RCAR_GEN2=y
+CONFIG_PHY_RCAR_GEN3_USB2=y
 # CONFIG_DNOTIFY is not set
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
@@ -209,6 +212,8 @@ CONFIG_NFS_V4_1=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_PRINTK_TIME=y
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
index 3b42e0d..9d42cfe 100644 (file)
@@ -106,6 +106,7 @@ CONFIG_SENSORS_LTC2978_REGULATOR=y
 CONFIG_WATCHDOG=y
 CONFIG_DW_WATCHDOG=y
 CONFIG_MFD_ALTERA_A10SR=y
+CONFIG_MFD_ALTERA_SYSMGR=y
 CONFIG_MFD_STMPE=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
index c7b99eb..8f5c6a5 100644 (file)
@@ -1,6 +1,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CGROUPS=y
@@ -14,23 +15,9 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_TEGRA=y
-CONFIG_PCI=y
-CONFIG_PCIEPORTBUS=y
-CONFIG_PCI_MSI=y
-CONFIG_PCI_TEGRA=y
 CONFIG_SMP=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_CMA=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_KEXEC=y
@@ -40,6 +27,13 @@ CONFIG_CPUFREQ_DT=y
 CONFIG_CPU_IDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
+CONFIG_TRUSTED_FOUNDATIONS=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_CMA=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -73,10 +67,12 @@ CONFIG_MAC80211=y
 CONFIG_RFKILL=y
 CONFIG_RFKILL_INPUT=y
 CONFIG_RFKILL_GPIO=y
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_TEGRA=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_DMA_CMA=y
-CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_TEGRA_GMI=y
 CONFIG_MTD=y
 CONFIG_MTD_M25P80=y
@@ -152,7 +148,6 @@ CONFIG_WATCHDOG=y
 CONFIG_TEGRA_WATCHDOG=y
 CONFIG_MFD_AS3722=y
 CONFIG_MFD_CROS_EC=y
-CONFIG_MFD_CROS_EC_SPI=y
 CONFIG_MFD_MAX8907=y
 CONFIG_MFD_STMPE=y
 CONFIG_MFD_PALMAS=y
@@ -180,6 +175,7 @@ CONFIG_DRM_NOUVEAU=m
 CONFIG_DRM_TEGRA=y
 CONFIG_DRM_PANEL_SIMPLE=y
 # CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
 # CONFIG_BACKLIGHT_GENERIC is not set
 CONFIG_BACKLIGHT_PWM=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -288,6 +284,10 @@ CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRC_CCITT=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
 CONFIG_MAGIC_SYSRQ=y
@@ -300,5 +300,3 @@ CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRC_CCITT=y
diff --git a/arch/arm/firmware/Kconfig b/arch/arm/firmware/Kconfig
deleted file mode 100644 (file)
index ad396af..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-config ARCH_SUPPORTS_FIRMWARE
-       bool
-
-config ARCH_SUPPORTS_TRUSTED_FOUNDATIONS
-       bool
-       select ARCH_SUPPORTS_FIRMWARE
-
-menu "Firmware options"
-       depends on ARCH_SUPPORTS_FIRMWARE
-
-config TRUSTED_FOUNDATIONS
-       bool "Trusted Foundations secure monitor support"
-       depends on ARCH_SUPPORTS_TRUSTED_FOUNDATIONS
-       default y
-       help
-         Some devices (including most Tegra-based consumer devices on the
-         market) are booted with the Trusted Foundations secure monitor
-         active, requiring some core operations to be performed by the secure
-         monitor instead of the kernel.
-
-         This option allows the kernel to invoke the secure monitor whenever
-         required on devices using Trusted Foundations. See
-         arch/arm/include/asm/trusted_foundations.h or the
-         tlm,trusted-foundations device tree binding documentation for details
-         on how to use it.
-
-         Say n if you don't know what this is about.
-
-endmenu
diff --git a/arch/arm/firmware/Makefile b/arch/arm/firmware/Makefile
deleted file mode 100644 (file)
index 6e41336..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-obj-$(CONFIG_TRUSTED_FOUNDATIONS)      += trusted_foundations.o
-
-# tf_generic_smc() fails to build with -fsanitize-coverage=trace-pc
-KCOV_INSTRUMENT                := n
diff --git a/arch/arm/firmware/trusted_foundations.c b/arch/arm/firmware/trusted_foundations.c
deleted file mode 100644 (file)
index 689e656..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Trusted Foundations support for ARM CPUs
- *
- * Copyright (c) 2013, NVIDIA 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/of.h>
-#include <asm/firmware.h>
-#include <asm/trusted_foundations.h>
-
-#define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200
-
-#define TF_CPU_PM              0xfffffffc
-#define TF_CPU_PM_S3           0xffffffe3
-#define TF_CPU_PM_S2           0xffffffe6
-#define TF_CPU_PM_S2_NO_MC_CLK 0xffffffe5
-#define TF_CPU_PM_S1           0xffffffe4
-#define TF_CPU_PM_S1_NOFLUSH_L2        0xffffffe7
-
-static unsigned long cpu_boot_addr;
-
-static void tf_generic_smc(u32 type, u32 arg1, u32 arg2)
-{
-       register u32 r0 asm("r0") = type;
-       register u32 r1 asm("r1") = arg1;
-       register u32 r2 asm("r2") = arg2;
-
-       asm volatile(
-               ".arch_extension        sec\n\t"
-               "stmfd  sp!, {r4 - r11}\n\t"
-               __asmeq("%0", "r0")
-               __asmeq("%1", "r1")
-               __asmeq("%2", "r2")
-               "mov    r3, #0\n\t"
-               "mov    r4, #0\n\t"
-               "smc    #0\n\t"
-               "ldmfd  sp!, {r4 - r11}\n\t"
-               :
-               : "r" (r0), "r" (r1), "r" (r2)
-               : "memory", "r3", "r12", "lr");
-}
-
-static int tf_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
-{
-       cpu_boot_addr = boot_addr;
-       tf_generic_smc(TF_SET_CPU_BOOT_ADDR_SMC, cpu_boot_addr, 0);
-
-       return 0;
-}
-
-static int tf_prepare_idle(void)
-{
-       tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1_NOFLUSH_L2, cpu_boot_addr);
-
-       return 0;
-}
-
-static const struct firmware_ops trusted_foundations_ops = {
-       .set_cpu_boot_addr = tf_set_cpu_boot_addr,
-       .prepare_idle = tf_prepare_idle,
-};
-
-void register_trusted_foundations(struct trusted_foundations_platform_data *pd)
-{
-       /*
-        * we are not using version information for now since currently
-        * supported SMCs are compatible with all TF releases
-        */
-       register_firmware_ops(&trusted_foundations_ops);
-}
-
-void of_register_trusted_foundations(void)
-{
-       struct device_node *node;
-       struct trusted_foundations_platform_data pdata;
-       int err;
-
-       node = of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations");
-       if (!node)
-               return;
-
-       err = of_property_read_u32(node, "tlm,version-major",
-                                  &pdata.version_major);
-       if (err != 0)
-               panic("Trusted Foundation: missing version-major property\n");
-       err = of_property_read_u32(node, "tlm,version-minor",
-                                  &pdata.version_minor);
-       if (err != 0)
-               panic("Trusted Foundation: missing version-minor property\n");
-       register_trusted_foundations(&pdata);
-}
index 41deac2..60de9d1 100644 (file)
@@ -14,10 +14,8 @@ generic-y += msi.h
 generic-y += parport.h
 generic-y += preempt.h
 generic-y += seccomp.h
-generic-y += segment.h
 generic-y += serial.h
 generic-y += simd.h
-generic-y += sizes.h
 generic-y += trace_clock.h
 
 generated-y += mach-types.h
index 99d9f63..1888c2d 100644 (file)
@@ -133,9 +133,11 @@ static inline void modify_domain(unsigned dom, unsigned type)      { }
  * instructions (inline assembly)
  */
 #ifdef CONFIG_CPU_USE_DOMAINS
-#define TUSER(instr)   #instr "t"
+#define TUSER(instr)           TUSERCOND(instr, )
+#define TUSERCOND(instr, cond) #instr "t" #cond
 #else
-#define TUSER(instr)   #instr
+#define TUSER(instr)           TUSERCOND(instr, )
+#define TUSERCOND(instr, cond) #instr #cond
 #endif
 
 #else /* __ASSEMBLY__ */
index 34c1d96..6698272 100644 (file)
@@ -24,7 +24,7 @@ struct firmware_ops {
        /*
         * Inform the firmware we intend to enter CPU idle mode
         */
-       int (*prepare_idle)(void);
+       int (*prepare_idle)(unsigned long mode);
        /*
         * Enters CPU idle mode
         */
index 0a46676..83c391b 100644 (file)
@@ -110,10 +110,11 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
        preempt_disable();
        __ua_flags = uaccess_save_and_enable();
        __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
+       "       .syntax unified\n"
        "1:     " TUSER(ldr) "  %1, [%4]\n"
        "       teq     %1, %2\n"
        "       it      eq      @ explicit IT needed for the 2b label\n"
-       "2:     " TUSER(streq) "        %3, [%4]\n"
+       "2:     " TUSERCOND(str, eq) "  %3, [%4]\n"
        __futex_atomic_ex_table("%5")
        : "+r" (ret), "=&r" (val)
        : "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
index cba23ea..7a88f16 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/threads.h>
 #include <asm/irq.h>
 
+/* number of IPIS _not_ including IPI_CPU_BACKTRACE */
 #define NR_IPI 7
 
 typedef struct {
diff --git a/arch/arm/include/asm/limits.h b/arch/arm/include/asm/limits.h
deleted file mode 100644 (file)
index ab15937..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_PIPE_H
-#define __ASM_PIPE_H
-
-#ifndef PAGE_SIZE
-#include <asm/page.h>
-#endif
-
-#define PIPE_BUF       PAGE_SIZE
-
-#endif
-
index 57fe73e..5d06f75 100644 (file)
@@ -135,8 +135,8 @@ static inline void prefetchw(const void *ptr)
        __asm__ __volatile__(
                ".arch_extension        mp\n"
                __ALT_SMP_ASM(
-                       WASM(pldw)              "\t%a0",
-                       WASM(pld)               "\t%a0"
+                       "pldw\t%a0",
+                       "pld\t%a0"
                )
                :: "p" (ptr));
 }
diff --git a/arch/arm/include/asm/trusted_foundations.h b/arch/arm/include/asm/trusted_foundations.h
deleted file mode 100644 (file)
index 0074835..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2013, NVIDIA 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.
- */
-
-/*
- * Support for the Trusted Foundations secure monitor.
- *
- * Trusted Foundation comes active on some ARM consumer devices (most
- * Tegra-based devices sold on the market are concerned). Such devices can only
- * perform some basic operations, like setting the CPU reset vector, through
- * SMC calls to the secure monitor. The calls are completely specific to
- * Trusted Foundations, and do *not* follow the SMC calling convention or the
- * PSCI standard.
- */
-
-#ifndef __ASM_ARM_TRUSTED_FOUNDATIONS_H
-#define __ASM_ARM_TRUSTED_FOUNDATIONS_H
-
-#include <linux/printk.h>
-#include <linux/bug.h>
-#include <linux/of.h>
-#include <linux/cpu.h>
-#include <linux/smp.h>
-
-struct trusted_foundations_platform_data {
-       unsigned int version_major;
-       unsigned int version_minor;
-};
-
-#if IS_ENABLED(CONFIG_TRUSTED_FOUNDATIONS)
-
-void register_trusted_foundations(struct trusted_foundations_platform_data *pd);
-void of_register_trusted_foundations(void);
-
-#else /* CONFIG_TRUSTED_FOUNDATIONS */
-
-static inline void register_trusted_foundations(
-                                  struct trusted_foundations_platform_data *pd)
-{
-       /*
-        * If the system requires TF and we cannot provide it, continue booting
-        * but disable features that cannot be provided.
-        */
-       pr_err("No support for Trusted Foundations, continuing in degraded mode.\n");
-       pr_err("Secondary processors as well as CPU PM will be disabled.\n");
-#if IS_ENABLED(CONFIG_SMP)
-       setup_max_cpus = 0;
-#endif
-       cpu_idle_poll_ctrl(true);
-}
-
-static inline void of_register_trusted_foundations(void)
-{
-       /*
-        * If we find the target should enable TF but does not support it,
-        * fail as the system won't be able to do much anyway
-        */
-       if (of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations"))
-               register_trusted_foundations(NULL);
-}
-#endif /* CONFIG_TRUSTED_FOUNDATIONS */
-
-#endif
index dff4984..d49ce8f 100644 (file)
@@ -112,10 +112,11 @@ static inline void __user *__uaccess_mask_range_ptr(const void __user *ptr,
        unsigned long tmp;
 
        asm volatile(
+       "       .syntax unified\n"
        "       sub     %1, %3, #1\n"
        "       subs    %1, %1, %0\n"
        "       addhs   %1, %1, #1\n"
-       "       subhss  %1, %1, %2\n"
+       "       subshs  %1, %1, %2\n"
        "       movlo   %0, #0\n"
        : "+r" (safe_ptr), "=&r" (tmp)
        : "r" (size), "r" (current_thread_info()->addr_limit)
index 2011002..067e12e 100644 (file)
@@ -5,7 +5,7 @@ void convert_to_tag_list(struct tag *tags);
 const struct machine_desc *setup_machine_tags(phys_addr_t __atags_pointer,
        unsigned int machine_nr);
 #else
-static inline const struct machine_desc *
+static inline const struct machine_desc * __init __noreturn
 setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
 {
        early_print("no ATAGS support: can't continue\n");
index facd424..ebc5380 100644 (file)
@@ -70,6 +70,10 @@ enum ipi_msg_type {
        IPI_CPU_STOP,
        IPI_IRQ_WORK,
        IPI_COMPLETION,
+       /*
+        * CPU_BACKTRACE is special and not included in NR_IPI
+        * or tracable with trace_ipi_*
+        */
        IPI_CPU_BACKTRACE,
        /*
         * SGI8-15 can be reserved by secure firmware, and thus may
@@ -754,15 +758,20 @@ static int cpufreq_callback(struct notifier_block *nb,
                                        unsigned long val, void *data)
 {
        struct cpufreq_freqs *freq = data;
-       int cpu = freq->cpu;
+       struct cpumask *cpus = freq->policy->cpus;
+       int cpu, first = cpumask_first(cpus);
+       unsigned int lpj;
 
        if (freq->flags & CPUFREQ_CONST_LOOPS)
                return NOTIFY_OK;
 
-       if (!per_cpu(l_p_j_ref, cpu)) {
-               per_cpu(l_p_j_ref, cpu) =
-                       per_cpu(cpu_data, cpu).loops_per_jiffy;
-               per_cpu(l_p_j_ref_freq, cpu) = freq->old;
+       if (!per_cpu(l_p_j_ref, first)) {
+               for_each_cpu(cpu, cpus) {
+                       per_cpu(l_p_j_ref, cpu) =
+                               per_cpu(cpu_data, cpu).loops_per_jiffy;
+                       per_cpu(l_p_j_ref_freq, cpu) = freq->old;
+               }
+
                if (!global_l_p_j_ref) {
                        global_l_p_j_ref = loops_per_jiffy;
                        global_l_p_j_ref_freq = freq->old;
@@ -774,10 +783,11 @@ static int cpufreq_callback(struct notifier_block *nb,
                loops_per_jiffy = cpufreq_scale(global_l_p_j_ref,
                                                global_l_p_j_ref_freq,
                                                freq->new);
-               per_cpu(cpu_data, cpu).loops_per_jiffy =
-                       cpufreq_scale(per_cpu(l_p_j_ref, cpu),
-                                       per_cpu(l_p_j_ref_freq, cpu),
-                                       freq->new);
+
+               lpj = cpufreq_scale(per_cpu(l_p_j_ref, first),
+                                   per_cpu(l_p_j_ref_freq, first), freq->new);
+               for_each_cpu(cpu, cpus)
+                       per_cpu(cpu_data, cpu).loops_per_jiffy = lpj;
        }
        return NOTIFY_OK;
 }
@@ -797,7 +807,7 @@ core_initcall(register_cpufreq_notifier);
 
 static void raise_nmi(cpumask_t *mask)
 {
-       smp_cross_call(mask, IPI_CPU_BACKTRACE);
+       __smp_cross_call(mask, IPI_CPU_BACKTRACE);
 }
 
 void arch_trigger_cpumask_backtrace(const cpumask_t *mask, bool exclude_self)
index ff097ec..51a8927 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/platform_data/spi-davinci.h>
 #include <linux/platform_data/usb-davinci.h>
 #include <linux/platform_data/ti-aemif.h>
+#include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/nvmem-provider.h>
 
@@ -53,14 +54,50 @@ static const short da830_evm_usb11_pins[] = {
        -1
 };
 
-static struct gpiod_lookup_table da830_evm_usb_gpio_lookup = {
+static struct regulator_consumer_supply da830_evm_usb_supplies[] = {
+       REGULATOR_SUPPLY("vbus", NULL),
+};
+
+static struct regulator_init_data da830_evm_usb_vbus_data = {
+       .consumer_supplies      = da830_evm_usb_supplies,
+       .num_consumer_supplies  = ARRAY_SIZE(da830_evm_usb_supplies),
+};
+
+static struct fixed_voltage_config da830_evm_usb_vbus = {
+       .supply_name            = "vbus",
+       .microvolts             = 33000000,
+       .init_data              = &da830_evm_usb_vbus_data,
+};
+
+static struct platform_device da830_evm_usb_vbus_device = {
+       .name           = "reg-fixed-voltage",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &da830_evm_usb_vbus,
+       },
+};
+
+static struct gpiod_lookup_table da830_evm_usb_oc_gpio_lookup = {
        .dev_id         = "ohci-da8xx",
        .table = {
-               GPIO_LOOKUP("davinci_gpio", ON_BD_USB_DRV, "vbus", 0),
                GPIO_LOOKUP("davinci_gpio", ON_BD_USB_OVC, "oc", 0),
+               { }
        },
 };
 
+static struct gpiod_lookup_table da830_evm_usb_vbus_gpio_lookup = {
+       .dev_id         = "reg-fixed-voltage.0",
+       .table = {
+               GPIO_LOOKUP("davinci_gpio", ON_BD_USB_DRV, "vbus", 0),
+               { }
+       },
+};
+
+static struct gpiod_lookup_table *da830_evm_usb_gpio_lookups[] = {
+       &da830_evm_usb_oc_gpio_lookup,
+       &da830_evm_usb_vbus_gpio_lookup,
+};
+
 static struct da8xx_ohci_root_hub da830_evm_usb11_pdata = {
        /* TPS2065 switch @ 5V */
        .potpgt         = (3 + 1) / 2,  /* 3 ms max */
@@ -75,6 +112,9 @@ static __init void da830_evm_usb_init(void)
                pr_warn("%s: USB PHY CLK registration failed: %d\n",
                        __func__, ret);
 
+       gpiod_add_lookup_tables(da830_evm_usb_gpio_lookups,
+                               ARRAY_SIZE(da830_evm_usb_gpio_lookups));
+
        ret = da8xx_register_usb_phy();
        if (ret)
                pr_warn("%s: USB PHY registration failed: %d\n",
@@ -100,7 +140,11 @@ static __init void da830_evm_usb_init(void)
                return;
        }
 
-       gpiod_add_lookup_table(&da830_evm_usb_gpio_lookup);
+       ret = platform_device_register(&da830_evm_usb_vbus_device);
+       if (ret) {
+               pr_warn("%s: Unable to register the vbus supply\n", __func__);
+               return;
+       }
 
        ret = da8xx_register_usb11(&da830_evm_usb11_pdata);
        if (ret)
@@ -156,6 +200,7 @@ static struct gpiod_lookup_table mmc_gpios_table = {
                            GPIO_ACTIVE_LOW),
                GPIO_LOOKUP("davinci_gpio", DA830_MMCSD_WP_PIN, "wp",
                            GPIO_ACTIVE_LOW),
+               { }
        },
 };
 
index 1fdc928..4ee65a8 100644 (file)
@@ -784,6 +784,7 @@ static struct gpiod_lookup_table mmc_gpios_table = {
                            GPIO_ACTIVE_LOW),
                GPIO_LOOKUP("davinci_gpio", DA850_MMCSD_WP_PIN, "wp",
                            GPIO_ACTIVE_HIGH),
+               { }
        },
 };
 
index 64d81fc..5113273 100644 (file)
@@ -121,6 +121,7 @@ static struct gpiod_lookup_table i2c_recovery_gpiod_table = {
                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
                GPIO_LOOKUP("davinci_gpio", DM355_I2C_SCL_PIN, "scl",
                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               { }
        },
 };
 
index de15f78..9d87d4e 100644 (file)
@@ -663,6 +663,7 @@ static struct gpiod_lookup_table i2c_recovery_gpiod_table = {
                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
                GPIO_LOOKUP("davinci_gpio", DM644X_I2C_SCL_PIN, "scl",
                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+               { }
        },
 };
 
index 0896af2..db177a6 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/platform_data/mtd-davinci.h>
 #include <linux/platform_data/mtd-davinci-aemif.h>
 #include <linux/platform_data/ti-aemif.h>
+#include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 
 #include <asm/mach-types.h>
@@ -298,14 +299,50 @@ static const short da850_hawk_usb11_pins[] = {
        -1
 };
 
-static struct gpiod_lookup_table hawk_usb_gpio_lookup = {
+static struct regulator_consumer_supply hawk_usb_supplies[] = {
+       REGULATOR_SUPPLY("vbus", NULL),
+};
+
+static struct regulator_init_data hawk_usb_vbus_data = {
+       .consumer_supplies      = hawk_usb_supplies,
+       .num_consumer_supplies  = ARRAY_SIZE(hawk_usb_supplies),
+};
+
+static struct fixed_voltage_config hawk_usb_vbus = {
+       .supply_name            = "vbus",
+       .microvolts             = 3300000,
+       .init_data              = &hawk_usb_vbus_data,
+};
+
+static struct platform_device hawk_usb_vbus_device = {
+       .name           = "reg-fixed-voltage",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &hawk_usb_vbus,
+       },
+};
+
+static struct gpiod_lookup_table hawk_usb_oc_gpio_lookup = {
        .dev_id         = "ohci-da8xx",
        .table = {
-               GPIO_LOOKUP("davinci_gpio", DA850_USB1_VBUS_PIN, "vbus", 0),
                GPIO_LOOKUP("davinci_gpio", DA850_USB1_OC_PIN, "oc", 0),
+               { }
        },
 };
 
+static struct gpiod_lookup_table hawk_usb_vbus_gpio_lookup = {
+       .dev_id         = "reg-fixed-voltage.0",
+       .table = {
+               GPIO_LOOKUP("davinci_gpio", DA850_USB1_VBUS_PIN, NULL, 0),
+               { }
+       },
+};
+
+static struct gpiod_lookup_table *hawk_usb_gpio_lookups[] = {
+       &hawk_usb_oc_gpio_lookup,
+       &hawk_usb_vbus_gpio_lookup,
+};
+
 static struct da8xx_ohci_root_hub omapl138_hawk_usb11_pdata = {
        /* TPS2087 switch @ 5V */
        .potpgt         = (3 + 1) / 2,  /* 3 ms max */
@@ -326,12 +363,19 @@ static __init void omapl138_hawk_usb_init(void)
                pr_warn("%s: USB PHY CLK registration failed: %d\n",
                        __func__, ret);
 
+       gpiod_add_lookup_tables(hawk_usb_gpio_lookups,
+                               ARRAY_SIZE(hawk_usb_gpio_lookups));
+
        ret = da8xx_register_usb_phy();
        if (ret)
                pr_warn("%s: USB PHY registration failed: %d\n",
                        __func__, ret);
 
-       gpiod_add_lookup_table(&hawk_usb_gpio_lookup);
+       ret = platform_device_register(&hawk_usb_vbus_device);
+       if (ret) {
+               pr_warn("%s: Unable to register the vbus supply\n", __func__);
+               return;
+       }
 
        ret = da8xx_register_usb11(&omapl138_hawk_usb11_pdata);
        if (ret)
index 63511f6..e6b8ffd 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/clk/davinci.h>
 #include <linux/gpio.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/irqchip/irq-davinci-cp-intc.h>
 #include <linux/platform_data/gpio-davinci.h>
 
index 67ab71b..77bc64d 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/cpufreq.h>
 #include <linux/gpio.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/irqchip/irq-davinci-cp-intc.h>
 #include <linux/mfd/da8xx-cfgchip.h>
 #include <linux/platform_data/clk-da8xx-cfgchip.h>
index b8dc674..036139f 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/dma-contiguous.h>
 #include <linux/dmaengine.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/reboot.h>
 #include <linux/serial_8250.h>
index 4a48244..c607332 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/irqchip/irq-davinci-aintc.h>
 #include <linux/platform_data/edma.h>
 #include <linux/platform_data/gpio-davinci.h>
index 8e0a773..2f9ae64 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/irqchip/irq-davinci-aintc.h>
 #include <linux/platform_data/edma.h>
 #include <linux/platform_data/gpio-davinci.h>
index cecc7ce..1b9e9a6 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/clkdev.h>
 #include <linux/dmaengine.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/irqchip/irq-davinci-aintc.h>
 #include <linux/platform_data/edma.h>
 #include <linux/platform_data/gpio-davinci.h>
index f33392f..62ca952 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/irqchip/irq-davinci-aintc.h>
 #include <linux/platform_data/edma.h>
 #include <linux/platform_data/gpio-davinci.h>
index 0d420a2..d7b826d 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/clk-provider.h>
 #include <linux/dma-mapping.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/platform_data/dma-mv_xor.h>
index bda6c3a..5d3a3e3 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/sizes.h>
 
-#include <mach/hardware.h>
+#include "hardware.h"
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
index d2eee70..b9f523d 100644 (file)
@@ -20,8 +20,9 @@
 #include <linux/io.h>
 #include <linux/spinlock.h>
 #include <linux/clkdev.h>
+#include <linux/soc/cirrus/ep93xx.h>
 
-#include <mach/hardware.h>
+#include "hardware.h"
 
 #include <asm/div64.h>
 
index 706515f..cc1382f 100644 (file)
 #include <linux/usb/ohci_pdriver.h>
 #include <linux/random.h>
 
-#include <mach/hardware.h>
+#include "hardware.h"
 #include <linux/platform_data/video-ep93xx.h>
 #include <linux/platform_data/keypad-ep93xx.h>
 #include <linux/platform_data/spi-ep93xx.h>
-#include <mach/gpio-ep93xx.h>
+#include <linux/soc/cirrus/ep93xx.h>
+
+#include "gpio-ep93xx.h"
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -123,7 +125,7 @@ void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits)
 /**
  * ep93xx_chip_revision() - returns the EP93xx chip revision
  *
- * See <mach/platform.h> for more information.
+ * See "platform.h" for more information.
  */
 unsigned int ep93xx_chip_revision(void)
 {
index 88a4c9b..8214271 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/platform_device.h>
 
 #include <linux/platform_data/dma-ep93xx.h>
-#include <mach/hardware.h>
+#include "hardware.h"
 
 #include "soc.h"
 
index 34e18e9..c8c4712 100644 (file)
 
 #include <sound/cs4271.h>
 
-#include <mach/hardware.h>
+#include "hardware.h"
 #include <linux/platform_data/video-ep93xx.h>
 #include <linux/platform_data/spi-ep93xx.h>
-#include <mach/gpio-ep93xx.h>
+#include "gpio-ep93xx.h"
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
index 0cca5b1..ac48e34 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/sizes.h>
 
-#include <mach/hardware.h>
+#include "hardware.h"
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
diff --git a/arch/arm/mach-ep93xx/gpio-ep93xx.h b/arch/arm/mach-ep93xx/gpio-ep93xx.h
new file mode 100644 (file)
index 0000000..242af4a
--- /dev/null
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Include file for the EP93XX GPIO controller machine specifics */
+
+#ifndef __GPIO_EP93XX_H
+#define __GPIO_EP93XX_H
+
+#include <mach/ep93xx-regs.h>
+
+#define EP93XX_GPIO_PHYS_BASE          EP93XX_APB_PHYS(0x00040000)
+#define EP93XX_GPIO_BASE               EP93XX_APB_IOMEM(0x00040000)
+#define EP93XX_GPIO_REG(x)             (EP93XX_GPIO_BASE + (x))
+#define EP93XX_GPIO_F_INT_STATUS       EP93XX_GPIO_REG(0x5c)
+#define EP93XX_GPIO_A_INT_STATUS       EP93XX_GPIO_REG(0xa0)
+#define EP93XX_GPIO_B_INT_STATUS       EP93XX_GPIO_REG(0xbc)
+#define EP93XX_GPIO_EEDRIVE            EP93XX_GPIO_REG(0xc8)
+
+/* GPIO port A.  */
+#define EP93XX_GPIO_LINE_A(x)          ((x) + 0)
+#define EP93XX_GPIO_LINE_EGPIO0                EP93XX_GPIO_LINE_A(0)
+#define EP93XX_GPIO_LINE_EGPIO1                EP93XX_GPIO_LINE_A(1)
+#define EP93XX_GPIO_LINE_EGPIO2                EP93XX_GPIO_LINE_A(2)
+#define EP93XX_GPIO_LINE_EGPIO3                EP93XX_GPIO_LINE_A(3)
+#define EP93XX_GPIO_LINE_EGPIO4                EP93XX_GPIO_LINE_A(4)
+#define EP93XX_GPIO_LINE_EGPIO5                EP93XX_GPIO_LINE_A(5)
+#define EP93XX_GPIO_LINE_EGPIO6                EP93XX_GPIO_LINE_A(6)
+#define EP93XX_GPIO_LINE_EGPIO7                EP93XX_GPIO_LINE_A(7)
+
+/* GPIO port B.  */
+#define EP93XX_GPIO_LINE_B(x)          ((x) + 8)
+#define EP93XX_GPIO_LINE_EGPIO8                EP93XX_GPIO_LINE_B(0)
+#define EP93XX_GPIO_LINE_EGPIO9                EP93XX_GPIO_LINE_B(1)
+#define EP93XX_GPIO_LINE_EGPIO10       EP93XX_GPIO_LINE_B(2)
+#define EP93XX_GPIO_LINE_EGPIO11       EP93XX_GPIO_LINE_B(3)
+#define EP93XX_GPIO_LINE_EGPIO12       EP93XX_GPIO_LINE_B(4)
+#define EP93XX_GPIO_LINE_EGPIO13       EP93XX_GPIO_LINE_B(5)
+#define EP93XX_GPIO_LINE_EGPIO14       EP93XX_GPIO_LINE_B(6)
+#define EP93XX_GPIO_LINE_EGPIO15       EP93XX_GPIO_LINE_B(7)
+
+/* GPIO port C.  */
+#define EP93XX_GPIO_LINE_C(x)          ((x) + 40)
+#define EP93XX_GPIO_LINE_ROW0          EP93XX_GPIO_LINE_C(0)
+#define EP93XX_GPIO_LINE_ROW1          EP93XX_GPIO_LINE_C(1)
+#define EP93XX_GPIO_LINE_ROW2          EP93XX_GPIO_LINE_C(2)
+#define EP93XX_GPIO_LINE_ROW3          EP93XX_GPIO_LINE_C(3)
+#define EP93XX_GPIO_LINE_ROW4          EP93XX_GPIO_LINE_C(4)
+#define EP93XX_GPIO_LINE_ROW5          EP93XX_GPIO_LINE_C(5)
+#define EP93XX_GPIO_LINE_ROW6          EP93XX_GPIO_LINE_C(6)
+#define EP93XX_GPIO_LINE_ROW7          EP93XX_GPIO_LINE_C(7)
+
+/* GPIO port D.  */
+#define EP93XX_GPIO_LINE_D(x)          ((x) + 24)
+#define EP93XX_GPIO_LINE_COL0          EP93XX_GPIO_LINE_D(0)
+#define EP93XX_GPIO_LINE_COL1          EP93XX_GPIO_LINE_D(1)
+#define EP93XX_GPIO_LINE_COL2          EP93XX_GPIO_LINE_D(2)
+#define EP93XX_GPIO_LINE_COL3          EP93XX_GPIO_LINE_D(3)
+#define EP93XX_GPIO_LINE_COL4          EP93XX_GPIO_LINE_D(4)
+#define EP93XX_GPIO_LINE_COL5          EP93XX_GPIO_LINE_D(5)
+#define EP93XX_GPIO_LINE_COL6          EP93XX_GPIO_LINE_D(6)
+#define EP93XX_GPIO_LINE_COL7          EP93XX_GPIO_LINE_D(7)
+
+/* GPIO port E.  */
+#define EP93XX_GPIO_LINE_E(x)          ((x) + 32)
+#define EP93XX_GPIO_LINE_GRLED         EP93XX_GPIO_LINE_E(0)
+#define EP93XX_GPIO_LINE_RDLED         EP93XX_GPIO_LINE_E(1)
+#define EP93XX_GPIO_LINE_DIORn         EP93XX_GPIO_LINE_E(2)
+#define EP93XX_GPIO_LINE_IDECS1n       EP93XX_GPIO_LINE_E(3)
+#define EP93XX_GPIO_LINE_IDECS2n       EP93XX_GPIO_LINE_E(4)
+#define EP93XX_GPIO_LINE_IDEDA0                EP93XX_GPIO_LINE_E(5)
+#define EP93XX_GPIO_LINE_IDEDA1                EP93XX_GPIO_LINE_E(6)
+#define EP93XX_GPIO_LINE_IDEDA2                EP93XX_GPIO_LINE_E(7)
+
+/* GPIO port F.  */
+#define EP93XX_GPIO_LINE_F(x)          ((x) + 16)
+#define EP93XX_GPIO_LINE_WP            EP93XX_GPIO_LINE_F(0)
+#define EP93XX_GPIO_LINE_MCCD1         EP93XX_GPIO_LINE_F(1)
+#define EP93XX_GPIO_LINE_MCCD2         EP93XX_GPIO_LINE_F(2)
+#define EP93XX_GPIO_LINE_MCBVD1                EP93XX_GPIO_LINE_F(3)
+#define EP93XX_GPIO_LINE_MCBVD2                EP93XX_GPIO_LINE_F(4)
+#define EP93XX_GPIO_LINE_VS1           EP93XX_GPIO_LINE_F(5)
+#define EP93XX_GPIO_LINE_READY         EP93XX_GPIO_LINE_F(6)
+#define EP93XX_GPIO_LINE_VS2           EP93XX_GPIO_LINE_F(7)
+
+/* GPIO port G.  */
+#define EP93XX_GPIO_LINE_G(x)          ((x) + 48)
+#define EP93XX_GPIO_LINE_EECLK         EP93XX_GPIO_LINE_G(0)
+#define EP93XX_GPIO_LINE_EEDAT         EP93XX_GPIO_LINE_G(1)
+#define EP93XX_GPIO_LINE_SLA0          EP93XX_GPIO_LINE_G(2)
+#define EP93XX_GPIO_LINE_SLA1          EP93XX_GPIO_LINE_G(3)
+#define EP93XX_GPIO_LINE_DD12          EP93XX_GPIO_LINE_G(4)
+#define EP93XX_GPIO_LINE_DD13          EP93XX_GPIO_LINE_G(5)
+#define EP93XX_GPIO_LINE_DD14          EP93XX_GPIO_LINE_G(6)
+#define EP93XX_GPIO_LINE_DD15          EP93XX_GPIO_LINE_G(7)
+
+/* GPIO port H.  */
+#define EP93XX_GPIO_LINE_H(x)          ((x) + 56)
+#define EP93XX_GPIO_LINE_DD0           EP93XX_GPIO_LINE_H(0)
+#define EP93XX_GPIO_LINE_DD1           EP93XX_GPIO_LINE_H(1)
+#define EP93XX_GPIO_LINE_DD2           EP93XX_GPIO_LINE_H(2)
+#define EP93XX_GPIO_LINE_DD3           EP93XX_GPIO_LINE_H(3)
+#define EP93XX_GPIO_LINE_DD4           EP93XX_GPIO_LINE_H(4)
+#define EP93XX_GPIO_LINE_DD5           EP93XX_GPIO_LINE_H(5)
+#define EP93XX_GPIO_LINE_DD6           EP93XX_GPIO_LINE_H(6)
+#define EP93XX_GPIO_LINE_DD7           EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for gpio line identifiers */
+#define EP93XX_GPIO_LINE_MAX           EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for irq capable line identifiers */
+#define EP93XX_GPIO_LINE_MAX_IRQ       EP93XX_GPIO_LINE_F(7)
+
+#endif /* __GPIO_EP93XX_H */
diff --git a/arch/arm/mach-ep93xx/hardware.h b/arch/arm/mach-ep93xx/hardware.h
new file mode 100644 (file)
index 0000000..e7d850e
--- /dev/null
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * arch/arm/mach-ep93xx/include/mach/hardware.h
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include "platform.h"
+
+/*
+ * The EP93xx has two external crystal oscillators.  To generate the
+ * required high-frequency clocks, the processor uses two phase-locked-
+ * loops (PLLs) to multiply the incoming external clock signal to much
+ * higher frequencies that are then divided down by programmable dividers
+ * to produce the needed clocks.  The PLLs operate independently of one
+ * another.
+ */
+#define EP93XX_EXT_CLK_RATE    14745600
+#define EP93XX_EXT_RTC_RATE    32768
+
+#define EP93XX_KEYTCHCLK_DIV4  (EP93XX_EXT_CLK_RATE / 4)
+#define EP93XX_KEYTCHCLK_DIV16 (EP93XX_EXT_CLK_RATE / 16)
+
+#endif
diff --git a/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h b/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h
deleted file mode 100644 (file)
index 242af4a..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Include file for the EP93XX GPIO controller machine specifics */
-
-#ifndef __GPIO_EP93XX_H
-#define __GPIO_EP93XX_H
-
-#include <mach/ep93xx-regs.h>
-
-#define EP93XX_GPIO_PHYS_BASE          EP93XX_APB_PHYS(0x00040000)
-#define EP93XX_GPIO_BASE               EP93XX_APB_IOMEM(0x00040000)
-#define EP93XX_GPIO_REG(x)             (EP93XX_GPIO_BASE + (x))
-#define EP93XX_GPIO_F_INT_STATUS       EP93XX_GPIO_REG(0x5c)
-#define EP93XX_GPIO_A_INT_STATUS       EP93XX_GPIO_REG(0xa0)
-#define EP93XX_GPIO_B_INT_STATUS       EP93XX_GPIO_REG(0xbc)
-#define EP93XX_GPIO_EEDRIVE            EP93XX_GPIO_REG(0xc8)
-
-/* GPIO port A.  */
-#define EP93XX_GPIO_LINE_A(x)          ((x) + 0)
-#define EP93XX_GPIO_LINE_EGPIO0                EP93XX_GPIO_LINE_A(0)
-#define EP93XX_GPIO_LINE_EGPIO1                EP93XX_GPIO_LINE_A(1)
-#define EP93XX_GPIO_LINE_EGPIO2                EP93XX_GPIO_LINE_A(2)
-#define EP93XX_GPIO_LINE_EGPIO3                EP93XX_GPIO_LINE_A(3)
-#define EP93XX_GPIO_LINE_EGPIO4                EP93XX_GPIO_LINE_A(4)
-#define EP93XX_GPIO_LINE_EGPIO5                EP93XX_GPIO_LINE_A(5)
-#define EP93XX_GPIO_LINE_EGPIO6                EP93XX_GPIO_LINE_A(6)
-#define EP93XX_GPIO_LINE_EGPIO7                EP93XX_GPIO_LINE_A(7)
-
-/* GPIO port B.  */
-#define EP93XX_GPIO_LINE_B(x)          ((x) + 8)
-#define EP93XX_GPIO_LINE_EGPIO8                EP93XX_GPIO_LINE_B(0)
-#define EP93XX_GPIO_LINE_EGPIO9                EP93XX_GPIO_LINE_B(1)
-#define EP93XX_GPIO_LINE_EGPIO10       EP93XX_GPIO_LINE_B(2)
-#define EP93XX_GPIO_LINE_EGPIO11       EP93XX_GPIO_LINE_B(3)
-#define EP93XX_GPIO_LINE_EGPIO12       EP93XX_GPIO_LINE_B(4)
-#define EP93XX_GPIO_LINE_EGPIO13       EP93XX_GPIO_LINE_B(5)
-#define EP93XX_GPIO_LINE_EGPIO14       EP93XX_GPIO_LINE_B(6)
-#define EP93XX_GPIO_LINE_EGPIO15       EP93XX_GPIO_LINE_B(7)
-
-/* GPIO port C.  */
-#define EP93XX_GPIO_LINE_C(x)          ((x) + 40)
-#define EP93XX_GPIO_LINE_ROW0          EP93XX_GPIO_LINE_C(0)
-#define EP93XX_GPIO_LINE_ROW1          EP93XX_GPIO_LINE_C(1)
-#define EP93XX_GPIO_LINE_ROW2          EP93XX_GPIO_LINE_C(2)
-#define EP93XX_GPIO_LINE_ROW3          EP93XX_GPIO_LINE_C(3)
-#define EP93XX_GPIO_LINE_ROW4          EP93XX_GPIO_LINE_C(4)
-#define EP93XX_GPIO_LINE_ROW5          EP93XX_GPIO_LINE_C(5)
-#define EP93XX_GPIO_LINE_ROW6          EP93XX_GPIO_LINE_C(6)
-#define EP93XX_GPIO_LINE_ROW7          EP93XX_GPIO_LINE_C(7)
-
-/* GPIO port D.  */
-#define EP93XX_GPIO_LINE_D(x)          ((x) + 24)
-#define EP93XX_GPIO_LINE_COL0          EP93XX_GPIO_LINE_D(0)
-#define EP93XX_GPIO_LINE_COL1          EP93XX_GPIO_LINE_D(1)
-#define EP93XX_GPIO_LINE_COL2          EP93XX_GPIO_LINE_D(2)
-#define EP93XX_GPIO_LINE_COL3          EP93XX_GPIO_LINE_D(3)
-#define EP93XX_GPIO_LINE_COL4          EP93XX_GPIO_LINE_D(4)
-#define EP93XX_GPIO_LINE_COL5          EP93XX_GPIO_LINE_D(5)
-#define EP93XX_GPIO_LINE_COL6          EP93XX_GPIO_LINE_D(6)
-#define EP93XX_GPIO_LINE_COL7          EP93XX_GPIO_LINE_D(7)
-
-/* GPIO port E.  */
-#define EP93XX_GPIO_LINE_E(x)          ((x) + 32)
-#define EP93XX_GPIO_LINE_GRLED         EP93XX_GPIO_LINE_E(0)
-#define EP93XX_GPIO_LINE_RDLED         EP93XX_GPIO_LINE_E(1)
-#define EP93XX_GPIO_LINE_DIORn         EP93XX_GPIO_LINE_E(2)
-#define EP93XX_GPIO_LINE_IDECS1n       EP93XX_GPIO_LINE_E(3)
-#define EP93XX_GPIO_LINE_IDECS2n       EP93XX_GPIO_LINE_E(4)
-#define EP93XX_GPIO_LINE_IDEDA0                EP93XX_GPIO_LINE_E(5)
-#define EP93XX_GPIO_LINE_IDEDA1                EP93XX_GPIO_LINE_E(6)
-#define EP93XX_GPIO_LINE_IDEDA2                EP93XX_GPIO_LINE_E(7)
-
-/* GPIO port F.  */
-#define EP93XX_GPIO_LINE_F(x)          ((x) + 16)
-#define EP93XX_GPIO_LINE_WP            EP93XX_GPIO_LINE_F(0)
-#define EP93XX_GPIO_LINE_MCCD1         EP93XX_GPIO_LINE_F(1)
-#define EP93XX_GPIO_LINE_MCCD2         EP93XX_GPIO_LINE_F(2)
-#define EP93XX_GPIO_LINE_MCBVD1                EP93XX_GPIO_LINE_F(3)
-#define EP93XX_GPIO_LINE_MCBVD2                EP93XX_GPIO_LINE_F(4)
-#define EP93XX_GPIO_LINE_VS1           EP93XX_GPIO_LINE_F(5)
-#define EP93XX_GPIO_LINE_READY         EP93XX_GPIO_LINE_F(6)
-#define EP93XX_GPIO_LINE_VS2           EP93XX_GPIO_LINE_F(7)
-
-/* GPIO port G.  */
-#define EP93XX_GPIO_LINE_G(x)          ((x) + 48)
-#define EP93XX_GPIO_LINE_EECLK         EP93XX_GPIO_LINE_G(0)
-#define EP93XX_GPIO_LINE_EEDAT         EP93XX_GPIO_LINE_G(1)
-#define EP93XX_GPIO_LINE_SLA0          EP93XX_GPIO_LINE_G(2)
-#define EP93XX_GPIO_LINE_SLA1          EP93XX_GPIO_LINE_G(3)
-#define EP93XX_GPIO_LINE_DD12          EP93XX_GPIO_LINE_G(4)
-#define EP93XX_GPIO_LINE_DD13          EP93XX_GPIO_LINE_G(5)
-#define EP93XX_GPIO_LINE_DD14          EP93XX_GPIO_LINE_G(6)
-#define EP93XX_GPIO_LINE_DD15          EP93XX_GPIO_LINE_G(7)
-
-/* GPIO port H.  */
-#define EP93XX_GPIO_LINE_H(x)          ((x) + 56)
-#define EP93XX_GPIO_LINE_DD0           EP93XX_GPIO_LINE_H(0)
-#define EP93XX_GPIO_LINE_DD1           EP93XX_GPIO_LINE_H(1)
-#define EP93XX_GPIO_LINE_DD2           EP93XX_GPIO_LINE_H(2)
-#define EP93XX_GPIO_LINE_DD3           EP93XX_GPIO_LINE_H(3)
-#define EP93XX_GPIO_LINE_DD4           EP93XX_GPIO_LINE_H(4)
-#define EP93XX_GPIO_LINE_DD5           EP93XX_GPIO_LINE_H(5)
-#define EP93XX_GPIO_LINE_DD6           EP93XX_GPIO_LINE_H(6)
-#define EP93XX_GPIO_LINE_DD7           EP93XX_GPIO_LINE_H(7)
-
-/* maximum value for gpio line identifiers */
-#define EP93XX_GPIO_LINE_MAX           EP93XX_GPIO_LINE_H(7)
-
-/* maximum value for irq capable line identifiers */
-#define EP93XX_GPIO_LINE_MAX_IRQ       EP93XX_GPIO_LINE_F(7)
-
-#endif /* __GPIO_EP93XX_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/hardware.h b/arch/arm/mach-ep93xx/include/mach/hardware.h
deleted file mode 100644 (file)
index 8938906..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * arch/arm/mach-ep93xx/include/mach/hardware.h
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <mach/platform.h>
-
-/*
- * The EP93xx has two external crystal oscillators.  To generate the
- * required high-frequency clocks, the processor uses two phase-locked-
- * loops (PLLs) to multiply the incoming external clock signal to much
- * higher frequencies that are then divided down by programmable dividers
- * to produce the needed clocks.  The PLLs operate independently of one
- * another.
- */
-#define EP93XX_EXT_CLK_RATE    14745600
-#define EP93XX_EXT_RTC_RATE    32768
-
-#define EP93XX_KEYTCHCLK_DIV4  (EP93XX_EXT_CLK_RATE / 4)
-#define EP93XX_KEYTCHCLK_DIV16 (EP93XX_EXT_CLK_RATE / 16)
-
-#endif
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
deleted file mode 100644 (file)
index 6c41c79..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * arch/arm/mach-ep93xx/include/mach/platform.h
- */
-
-#ifndef __ASSEMBLY__
-
-#include <linux/reboot.h>
-
-struct device;
-struct i2c_board_info;
-struct spi_board_info;
-struct platform_device;
-struct ep93xxfb_mach_info;
-struct ep93xx_keypad_platform_data;
-struct ep93xx_spi_info;
-
-struct ep93xx_eth_data
-{
-       unsigned char   dev_addr[6];
-       unsigned char   phy_id;
-};
-
-void ep93xx_map_io(void);
-void ep93xx_init_irq(void);
-
-#define EP93XX_CHIP_REV_D0     3
-#define EP93XX_CHIP_REV_D1     4
-#define EP93XX_CHIP_REV_E0     5
-#define EP93XX_CHIP_REV_E1     6
-#define EP93XX_CHIP_REV_E2     7
-
-unsigned int ep93xx_chip_revision(void);
-
-void ep93xx_register_flash(unsigned int width,
-                          resource_size_t start, resource_size_t size);
-
-void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
-void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
-void ep93xx_register_spi(struct ep93xx_spi_info *info,
-                        struct spi_board_info *devices, int num);
-void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
-void ep93xx_register_pwm(int pwm0, int pwm1);
-int ep93xx_pwm_acquire_gpio(struct platform_device *pdev);
-void ep93xx_pwm_release_gpio(struct platform_device *pdev);
-void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data);
-int ep93xx_keypad_acquire_gpio(struct platform_device *pdev);
-void ep93xx_keypad_release_gpio(struct platform_device *pdev);
-void ep93xx_register_i2s(void);
-int ep93xx_i2s_acquire(void);
-void ep93xx_i2s_release(void);
-void ep93xx_register_ac97(void);
-void ep93xx_register_ide(void);
-void ep93xx_register_adc(void);
-int ep93xx_ide_acquire_gpio(struct platform_device *pdev);
-void ep93xx_ide_release_gpio(struct platform_device *pdev);
-
-struct device *ep93xx_init_devices(void);
-extern void ep93xx_timer_init(void);
-
-void ep93xx_restart(enum reboot_mode, const char *);
-void ep93xx_init_late(void);
-
-#ifdef CONFIG_CRUNCH
-int crunch_init(void);
-#else
-static inline int crunch_init(void) { return 0; }
-#endif
-
-#endif
index 373583c..c7f64e4 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-#include <mach/hardware.h>
+#include "hardware.h"
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
diff --git a/arch/arm/mach-ep93xx/platform.h b/arch/arm/mach-ep93xx/platform.h
new file mode 100644 (file)
index 0000000..b4045a1
--- /dev/null
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * arch/arm/mach-ep93xx/include/mach/platform.h
+ */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/platform_data/eth-ep93xx.h>
+#include <linux/reboot.h>
+
+struct device;
+struct i2c_board_info;
+struct spi_board_info;
+struct platform_device;
+struct ep93xxfb_mach_info;
+struct ep93xx_keypad_platform_data;
+struct ep93xx_spi_info;
+
+void ep93xx_map_io(void);
+void ep93xx_init_irq(void);
+
+void ep93xx_register_flash(unsigned int width,
+                          resource_size_t start, resource_size_t size);
+
+void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
+void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
+void ep93xx_register_spi(struct ep93xx_spi_info *info,
+                        struct spi_board_info *devices, int num);
+void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
+void ep93xx_register_pwm(int pwm0, int pwm1);
+void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data);
+void ep93xx_register_i2s(void);
+void ep93xx_register_ac97(void);
+void ep93xx_register_ide(void);
+void ep93xx_register_adc(void);
+
+struct device *ep93xx_init_devices(void);
+extern void ep93xx_timer_init(void);
+
+void ep93xx_restart(enum reboot_mode, const char *);
+void ep93xx_init_late(void);
+
+#ifdef CONFIG_CRUNCH
+int crunch_init(void);
+#else
+static inline int crunch_init(void) { return 0; }
+#endif
+
+#endif
index f0f38c0..5a3c32f 100644 (file)
@@ -27,8 +27,8 @@
 #include <linux/gpio.h>
 #include <linux/gpio/machine.h>
 
-#include <mach/hardware.h>
-#include <mach/gpio-ep93xx.h>
+#include "hardware.h"
+#include "gpio-ep93xx.h"
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
index cf0cb58..f8f8955 100644 (file)
@@ -25,9 +25,9 @@
 
 #include <linux/mtd/platnand.h>
 
-#include <mach/hardware.h>
+#include "hardware.h"
 #include <linux/platform_data/video-ep93xx.h>
-#include <mach/gpio-ep93xx.h>
+#include "gpio-ep93xx.h"
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
index a3a20c8..e9f3690 100644 (file)
@@ -24,8 +24,8 @@
 #include <linux/platform_data/spi-ep93xx.h>
 #include <linux/gpio/machine.h>
 
-#include <mach/gpio-ep93xx.h>
-#include <mach/hardware.h>
+#include "gpio-ep93xx.h"
+#include "hardware.h"
 #include <mach/irqs.h>
 
 #include <asm/mach-types.h>
index f95a644..d44db6d 100644 (file)
 
 #include <sound/cs4271.h>
 
-#include <mach/hardware.h>
+#include "hardware.h"
 #include <linux/platform_data/video-ep93xx.h>
 #include <linux/platform_data/spi-ep93xx.h>
-#include <mach/gpio-ep93xx.h>
+#include "gpio-ep93xx.h"
 
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
index b40963c..1c518b8 100644 (file)
@@ -106,21 +106,15 @@ config SOC_EXYNOS5420
        bool "SAMSUNG EXYNOS5420"
        default y
        depends on ARCH_EXYNOS5
+       select MCPM if SMP
+       select ARM_CCI400_PORT_CTRL
+       select ARM_CPU_SUSPEND
 
 config SOC_EXYNOS5800
        bool "SAMSUNG EXYNOS5800"
        default y
        depends on SOC_EXYNOS5420
 
-config EXYNOS5420_MCPM
-       bool "Exynos5420 Multi-Cluster PM support"
-       depends on MCPM && SOC_EXYNOS5420
-       select ARM_CCI400_PORT_CTRL
-       select ARM_CPU_SUSPEND
-       help
-         This is needed to provide CPU and cluster power management
-         on Exynos5420 implementing big.LITTLE.
-
 config EXYNOS_CPU_SUSPEND
        bool
        select ARM_CPU_SUSPEND
index cd00c82..264dbaa 100644 (file)
@@ -18,5 +18,5 @@ plus_sec := $(call as-instr,.arch_extension sec,+sec)
 AFLAGS_exynos-smc.o            :=-Wa,-march=armv7-a$(plus_sec)
 AFLAGS_sleep.o                 :=-Wa,-march=armv7-a$(plus_sec)
 
-obj-$(CONFIG_EXYNOS5420_MCPM)  += mcpm-exynos.o
+obj-$(CONFIG_MCPM)             += mcpm-exynos.o
 CFLAGS_mcpm-exynos.o           += -march=armv7-a
index 1b8699e..c93356a 100644 (file)
@@ -91,6 +91,7 @@ extern u32 cp15_save_power;
 
 extern void __iomem *sysram_ns_base_addr;
 extern void __iomem *sysram_base_addr;
+extern phys_addr_t sysram_base_phys;
 extern void __iomem *pmu_base_addr;
 void exynos_sysram_init(void);
 
index 865dcc4..9aa4833 100644 (file)
@@ -33,6 +33,7 @@ static struct platform_device exynos_cpuidle = {
 };
 
 void __iomem *sysram_base_addr __ro_after_init;
+phys_addr_t sysram_base_phys __ro_after_init;
 void __iomem *sysram_ns_base_addr __ro_after_init;
 
 void __init exynos_sysram_init(void)
@@ -43,6 +44,8 @@ void __init exynos_sysram_init(void)
                if (!of_device_is_available(node))
                        continue;
                sysram_base_addr = of_iomap(node, 0);
+               sysram_base_phys = of_translate_address(node,
+                                          of_get_address(node, 0, NULL, NULL));
                break;
        }
 
index d602e3b..2eaf2db 100644 (file)
@@ -196,6 +196,7 @@ bool __init exynos_secure_firmware_available(void)
                return false;
 
        addr = of_get_address(nd, 0, NULL, NULL);
+       of_node_put(nd);
        if (!addr) {
                pr_err("%s: No address specified.\n", __func__);
                return false;
index 72bc035..9a681b4 100644 (file)
@@ -75,14 +75,25 @@ static int exynos_cpu_powerup(unsigned int cpu, unsigned int cluster)
                 */
                if (cluster &&
                    cluster == MPIDR_AFFINITY_LEVEL(cpu_logical_map(0), 1)) {
+                       unsigned int timeout = 16;
+
                        /*
                         * Before we reset the Little cores, we should wait
                         * the SPARE2 register is set to 1 because the init
                         * codes of the iROM will set the register after
                         * initialization.
                         */
-                       while (!pmu_raw_readl(S5P_PMU_SPARE2))
+                       while (timeout && !pmu_raw_readl(S5P_PMU_SPARE2)) {
+                               timeout--;
                                udelay(10);
+                       }
+
+                       if (timeout == 0) {
+                               pr_err("cpu %u cluster %u powerup failed\n",
+                                      cpu, cluster);
+                               exynos_cpu_power_down(cpunr);
+                               return -ETIMEDOUT;
+                       }
 
                        pmu_raw_writel(EXYNOS5420_KFC_CORE_RESET(cpu),
                                        EXYNOS_SWRESET);
index abcac61..0cbbae8 100644 (file)
@@ -214,13 +214,20 @@ static inline void __iomem *cpu_boot_reg(int cpu)
  */
 void exynos_core_restart(u32 core_id)
 {
+       unsigned int timeout = 16;
        u32 val;
 
        if (!of_machine_is_compatible("samsung,exynos3250"))
                return;
 
-       while (!pmu_raw_readl(S5P_PMU_SPARE2))
+       while (timeout && !pmu_raw_readl(S5P_PMU_SPARE2)) {
+               timeout--;
                udelay(10);
+       }
+       if (timeout == 0) {
+               pr_err("cpu core %u restart failed\n", core_id);
+               return;
+       }
        udelay(10);
 
        val = pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(core_id));
index f355185..98832e5 100644 (file)
 #define SMC_CMD_L2X0INVALL     (-24)
 #define SMC_CMD_L2X0DEBUG      (-25)
 
+/* For Accessing CP15/SFR (General) */
+#define SMC_CMD_REG            (-101)
+
+/* defines for SMC_CMD_REG */
+#define SMC_REG_CLASS_SFR_W    (0x1 << 30)
+#define SMC_REG_ID_SFR_W(addr) (SMC_REG_CLASS_SFR_W | ((addr) >> 2))
+
 #ifndef __ASSEMBLY__
 
 extern void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3);
index 0850505..be122af 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/suspend.h>
 
 #include "common.h"
+#include "smc.h"
 
 #define REG_TABLE_END (-1U)
 
@@ -62,6 +63,8 @@ struct exynos_pm_state {
        int cpu_state;
        unsigned int pmu_spare3;
        void __iomem *sysram_base;
+       phys_addr_t sysram_phys;
+       bool secure_firmware;
 };
 
 static const struct exynos_pm_data *pm_data __ro_after_init;
@@ -265,9 +268,7 @@ static int exynos5420_cpu_suspend(unsigned long arg)
        unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
        unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
 
-       writel_relaxed(0x0, pm_state.sysram_base + EXYNOS5420_CPU_STATE);
-
-       if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) {
+       if (IS_ENABLED(CONFIG_MCPM)) {
                mcpm_set_entry_vector(cpu, cluster, exynos_cpu_resume);
                mcpm_cpu_suspend();
        }
@@ -341,11 +342,16 @@ static void exynos5420_pm_prepare(void)
         */
        pm_state.cpu_state = readl_relaxed(pm_state.sysram_base +
                                           EXYNOS5420_CPU_STATE);
+       writel_relaxed(0x0, pm_state.sysram_base + EXYNOS5420_CPU_STATE);
+       if (pm_state.secure_firmware)
+               exynos_smc(SMC_CMD_REG, SMC_REG_ID_SFR_W(pm_state.sysram_phys +
+                                                        EXYNOS5420_CPU_STATE),
+                          0, 0);
 
        exynos_pm_enter_sleep_mode();
 
        /* ensure at least INFORM0 has the resume address */
-       if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
+       if (IS_ENABLED(CONFIG_MCPM))
                pmu_raw_writel(__pa_symbol(mcpm_entry_point), S5P_INFORM0);
 
        tmp = pmu_raw_readl(EXYNOS_L2_OPTION(0));
@@ -444,8 +450,27 @@ early_wakeup:
 
 static void exynos5420_prepare_pm_resume(void)
 {
-       if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
+       unsigned int mpidr, cluster;
+
+       mpidr = read_cpuid_mpidr();
+       cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
+       if (IS_ENABLED(CONFIG_MCPM))
                WARN_ON(mcpm_cpu_powered_up());
+
+       if (IS_ENABLED(CONFIG_HW_PERF_EVENTS) && cluster != 0) {
+               /*
+                * When system is resumed on the LITTLE/KFC core (cluster 1),
+                * the DSCR is not properly updated until the power is turned
+                * on also for the cluster 0. Enable it for a while to
+                * propagate the SPNIDEN and SPIDEN signals from Secure JTAG
+                * block and avoid undefined instruction issue on CP14 reset.
+                */
+               pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
+                               EXYNOS_COMMON_CONFIGURATION(0));
+               pmu_raw_writel(0,
+                               EXYNOS_COMMON_CONFIGURATION(0));
+       }
 }
 
 static void exynos5420_pm_resume(void)
@@ -460,6 +485,11 @@ static void exynos5420_pm_resume(void)
        /* Restore the sysram cpu state register */
        writel_relaxed(pm_state.cpu_state,
                       pm_state.sysram_base + EXYNOS5420_CPU_STATE);
+       if (pm_state.secure_firmware)
+               exynos_smc(SMC_CMD_REG,
+                          SMC_REG_ID_SFR_W(pm_state.sysram_phys +
+                                           EXYNOS5420_CPU_STATE),
+                          EXYNOS_AFTR_MAGIC, 0);
 
        pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL,
                        S5P_CENTRAL_SEQ_OPTION);
@@ -639,8 +669,10 @@ void __init exynos_pm_init(void)
 
        if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) {
                pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
+               of_node_put(np);
                return;
        }
+       of_node_put(np);
 
        pm_data = (const struct exynos_pm_data *) match->data;
 
@@ -659,8 +691,11 @@ void __init exynos_pm_init(void)
         * Applicable as of now only to Exynos542x. If booted under secure
         * firmware, the non-secure region of sysram should be used.
         */
-       if (exynos_secure_firmware_available())
+       if (exynos_secure_firmware_available()) {
+               pm_state.sysram_phys = sysram_base_phys;
                pm_state.sysram_base = sysram_ns_base_addr;
-       else
+               pm_state.secure_firmware = true;
+       } else {
                pm_state.sysram_base = sysram_base_addr;
+       }
 }
index b403a4f..605c0af 100644 (file)
@@ -7,7 +7,7 @@
  * Free Software Foundation.
  */
 #include <linux/dma-mapping.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include "../hardware.h"
 #include "devices-common.h"
index 4862825..9f0a132 100644 (file)
@@ -15,7 +15,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA  02110-1301, USA.
  */
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include "../hardware.h"
 #include "devices-common.h"
index 8c134c8..0c6d3c0 100644 (file)
@@ -6,7 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include "../hardware.h"
 #include "devices-common.h"
index 676df49..046e0cc 100644 (file)
@@ -6,7 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include "../hardware.h"
 #include "devices-common.h"
index 90e10cb..b5ca8ce 100644 (file)
@@ -24,7 +24,7 @@
 #include <asm/io.h>
 #include <soc/imx/revision.h>
 #endif
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #define addr_in_module(addr, mod) \
        ((unsigned long)(addr) - mod ## _BASE_ADDR < mod ## _SIZE)
index e67e0b2..e527532 100644 (file)
@@ -354,9 +354,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;
 }
index 8dfad01..6ddbe15 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/irqchip/arm-vic.h>
 #include <linux/gpio/machine.h>
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include "lm.h"
 #include "impd1.h"
 
index 070d92a..8426ab9 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/export.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/signal.h>
 #include <asm/mach/pci.h>
 #include "pci.h"
index 116feb6..d3d8c78 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <asm/irq.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <mach/irqs.h>
 
 /* assumes CONTROLLER_ONLY# is never asserted in the ESSR register */
index fea0081..83afb80 100644 (file)
@@ -4,6 +4,20 @@ menu "Intel IXP4xx Implementation Options"
 
 comment "IXP4xx Platforms"
 
+config MACH_IXP4XX_OF
+       bool
+       prompt "Devce Tree IXP4xx boards"
+       default y
+       select ARM_APPENDED_DTB # Old Redboot bootloaders deployed
+       select I2C
+       select I2C_IOP3XX
+       select PCI
+       select SERIAL_OF_PLATFORM
+       select TIMER_OF
+       select USE_OF
+       help
+         Say 'Y' here to support Device Tree-based IXP4xx platforms.
+
 config MACH_NSLU2
        bool
        prompt "Linksys NSLU2"
@@ -222,19 +236,6 @@ config IXP4XX_INDIRECT_PCI
          need to use the indirect method instead. If you don't know
          what you need, leave this option unselected.
 
-config IXP4XX_QMGR
-       tristate "IXP4xx Queue Manager support"
-       help
-         This driver supports IXP4xx built-in hardware queue manager
-         and is automatically selected by Ethernet and HSS drivers.
-
-config IXP4XX_NPE
-       tristate "IXP4xx Network Processor Engine support"
-       select FW_LOADER
-       help
-         This driver supports IXP4xx built-in network coprocessors
-         and is automatically selected by Ethernet and HSS drivers.
-
 endmenu
 
 endif
index f099945..1fa4e66 100644 (file)
@@ -6,6 +6,9 @@
 obj-pci-y      :=
 obj-pci-n      :=
 
+# Device tree platform
+obj-pci-$(CONFIG_MACH_IXP4XX_OF)       += ixp4xx-of.o
+
 obj-pci-$(CONFIG_ARCH_IXDP4XX)         += ixdp425-pci.o
 obj-pci-$(CONFIG_MACH_AVILA)           += avila-pci.o
 obj-pci-$(CONFIG_MACH_IXDPG425)                += ixdpg425-pci.o
@@ -40,5 +43,3 @@ obj-$(CONFIG_MACH_GORAMO_MLR) += goramo_mlr.o
 obj-$(CONFIG_MACH_ARCOM_VULCAN)        += vulcan-setup.o
 
 obj-$(CONFIG_PCI)              += $(obj-pci-$(CONFIG_PCI)) common-pci.o
-obj-$(CONFIG_IXP4XX_QMGR)      += ixp4xx_qmgr.o
-obj-$(CONFIG_IXP4XX_NPE)       += ixp4xx_npe.o
index 548c7d4..9c834f0 100644 (file)
@@ -27,6 +27,8 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 #define AVILA_MAX_DEV  4
 #define LOFT_MAX_DEV   6
 #define IRQ_LINES      4
index 44cbbce..1981b33 100644 (file)
@@ -28,6 +28,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 #define AVILA_SDA_PIN  7
 #define AVILA_SCL_PIN  6
 
index 6835b17..a53104b 100644 (file)
@@ -31,7 +31,7 @@
 
 #include <asm/cputype.h>
 #include <asm/irq.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/mach/pci.h>
 #include <mach/hardware.h>
 
index 846e033..cc5f156 100644 (file)
 #include <linux/serial_core.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
-#include <linux/time.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
 #include <linux/io.h>
 #include <linux/export.h>
-#include <linux/gpio/driver.h>
 #include <linux/cpu.h>
 #include <linux/pci.h>
 #include <linux/sched_clock.h>
+#include <linux/bitops.h>
+#include <linux/irqchip/irq-ixp4xx.h>
+#include <linux/platform_data/timer-ixp4xx.h>
 #include <mach/udc.h>
 #include <mach/hardware.h>
 #include <mach/io.h>
 #include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/exception.h>
 #include <asm/irq.h>
 #include <asm/system_misc.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
-#define IXP4XX_TIMER_FREQ 66666000
-
-/*
- * The timer register doesn't allow to specify the two least significant bits of
- * the timeout value and assumes them being zero. So make sure IXP4XX_LATCH is
- * the best value with the two least significant bits unset.
- */
-#define IXP4XX_LATCH DIV_ROUND_CLOSEST(IXP4XX_TIMER_FREQ, \
-                                      (IXP4XX_OST_RELOAD_MASK + 1) * HZ) * \
-                       (IXP4XX_OST_RELOAD_MASK + 1)
+#include "irqs.h"
 
-static void __init ixp4xx_clocksource_init(void);
-static void __init ixp4xx_clockevent_init(void);
-static struct clock_event_device clockevent_ixp4xx;
+#define IXP4XX_TIMER_FREQ 66666000
 
 /*************************************************************************
  * IXP4xx chipset I/O mapping
@@ -77,11 +66,6 @@ static struct map_desc ixp4xx_io_desc[] __initdata = {
                .pfn            = __phys_to_pfn(IXP4XX_PCI_CFG_BASE_PHYS),
                .length         = IXP4XX_PCI_CFG_REGION_SIZE,
                .type           = MT_DEVICE
-       }, {    /* Queue Manager */
-               .virtual        = (unsigned long)IXP4XX_QMGR_BASE_VIRT,
-               .pfn            = __phys_to_pfn(IXP4XX_QMGR_BASE_PHYS),
-               .length         = IXP4XX_QMGR_REGION_SIZE,
-               .type           = MT_DEVICE
        },
 };
 
@@ -90,258 +74,23 @@ void __init ixp4xx_map_io(void)
        iotable_init(ixp4xx_io_desc, ARRAY_SIZE(ixp4xx_io_desc));
 }
 
-/*
- * GPIO-functions
- */
-/*
- * The following converted to the real HW bits the gpio_line_config
- */
-/* GPIO pin types */
-#define IXP4XX_GPIO_OUT                0x1
-#define IXP4XX_GPIO_IN                 0x2
-
-/* GPIO signal types */
-#define IXP4XX_GPIO_LOW                        0
-#define IXP4XX_GPIO_HIGH               1
-
-/* GPIO Clocks */
-#define IXP4XX_GPIO_CLK_0              14
-#define IXP4XX_GPIO_CLK_1              15
-
-static void gpio_line_config(u8 line, u32 direction)
-{
-       if (direction == IXP4XX_GPIO_IN)
-               *IXP4XX_GPIO_GPOER |= (1 << line);
-       else
-               *IXP4XX_GPIO_GPOER &= ~(1 << line);
-}
-
-static void gpio_line_get(u8 line, int *value)
-{
-       *value = (*IXP4XX_GPIO_GPINR >> line) & 0x1;
-}
-
-static void gpio_line_set(u8 line, int value)
-{
-       if (value == IXP4XX_GPIO_HIGH)
-           *IXP4XX_GPIO_GPOUTR |= (1 << line);
-       else if (value == IXP4XX_GPIO_LOW)
-           *IXP4XX_GPIO_GPOUTR &= ~(1 << line);
-}
-
-/*************************************************************************
- * IXP4xx chipset IRQ handling
- *
- * TODO: GPIO IRQs should be marked invalid until the user of the IRQ
- *       (be it PCI or something else) configures that GPIO line
- *       as an IRQ.
- **************************************************************************/
-enum ixp4xx_irq_type {
-       IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
-};
-
-/* Each bit represents an IRQ: 1: edge-triggered, 0: level triggered */
-static unsigned long long ixp4xx_irq_edge = 0;
-
-/*
- * IRQ -> GPIO mapping table
- */
-static signed char irq2gpio[32] = {
-       -1, -1, -1, -1, -1, -1,  0,  1,
-       -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1,  2,  3,  4,  5,  6,
-        7,  8,  9, 10, 11, 12, -1, -1,
-};
-
-static int ixp4xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
-{
-       int irq;
-
-       for (irq = 0; irq < 32; irq++) {
-               if (irq2gpio[irq] == gpio)
-                       return irq;
-       }
-       return -EINVAL;
-}
-
-static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type)
-{
-       int line = irq2gpio[d->irq];
-       u32 int_style;
-       enum ixp4xx_irq_type irq_type;
-       volatile u32 *int_reg;
-
-       /*
-        * Only for GPIO IRQs
-        */
-       if (line < 0)
-               return -EINVAL;
-
-       switch (type){
-       case IRQ_TYPE_EDGE_BOTH:
-               int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
-               irq_type = IXP4XX_IRQ_EDGE;
-               break;
-       case IRQ_TYPE_EDGE_RISING:
-               int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
-               irq_type = IXP4XX_IRQ_EDGE;
-               break;
-       case IRQ_TYPE_EDGE_FALLING:
-               int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
-               irq_type = IXP4XX_IRQ_EDGE;
-               break;
-       case IRQ_TYPE_LEVEL_HIGH:
-               int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
-               irq_type = IXP4XX_IRQ_LEVEL;
-               break;
-       case IRQ_TYPE_LEVEL_LOW:
-               int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
-               irq_type = IXP4XX_IRQ_LEVEL;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (irq_type == IXP4XX_IRQ_EDGE)
-               ixp4xx_irq_edge |= (1 << d->irq);
-       else
-               ixp4xx_irq_edge &= ~(1 << d->irq);
-
-       if (line >= 8) {        /* pins 8-15 */
-               line -= 8;
-               int_reg = IXP4XX_GPIO_GPIT2R;
-       } else {                /* pins 0-7 */
-               int_reg = IXP4XX_GPIO_GPIT1R;
-       }
-
-       /* Clear the style for the appropriate pin */
-       *int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR <<
-                       (line * IXP4XX_GPIO_STYLE_SIZE));
-
-       *IXP4XX_GPIO_GPISR = (1 << line);
-
-       /* Set the new style */
-       *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
-
-       /* Configure the line as an input */
-       gpio_line_config(irq2gpio[d->irq], IXP4XX_GPIO_IN);
-
-       return 0;
-}
-
-static void ixp4xx_irq_mask(struct irq_data *d)
-{
-       if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->irq >= 32)
-               *IXP4XX_ICMR2 &= ~(1 << (d->irq - 32));
-       else
-               *IXP4XX_ICMR &= ~(1 << d->irq);
-}
-
-static void ixp4xx_irq_ack(struct irq_data *d)
-{
-       int line = (d->irq < 32) ? irq2gpio[d->irq] : -1;
-
-       if (line >= 0)
-               *IXP4XX_GPIO_GPISR = (1 << line);
-}
-
-/*
- * Level triggered interrupts on GPIO lines can only be cleared when the
- * interrupt condition disappears.
- */
-static void ixp4xx_irq_unmask(struct irq_data *d)
-{
-       if (!(ixp4xx_irq_edge & (1 << d->irq)))
-               ixp4xx_irq_ack(d);
-
-       if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->irq >= 32)
-               *IXP4XX_ICMR2 |= (1 << (d->irq - 32));
-       else
-               *IXP4XX_ICMR |= (1 << d->irq);
-}
-
-static struct irq_chip ixp4xx_irq_chip = {
-       .name           = "IXP4xx",
-       .irq_ack        = ixp4xx_irq_ack,
-       .irq_mask       = ixp4xx_irq_mask,
-       .irq_unmask     = ixp4xx_irq_unmask,
-       .irq_set_type   = ixp4xx_set_irq_type,
-};
-
 void __init ixp4xx_init_irq(void)
 {
-       int i = 0;
-
        /*
         * ixp4xx does not implement the XScale PWRMODE register
         * so it must not call cpu_do_idle().
         */
        cpu_idle_poll_ctrl(true);
 
-       /* Route all sources to IRQ instead of FIQ */
-       *IXP4XX_ICLR = 0x0;
-
-       /* Disable all interrupt */
-       *IXP4XX_ICMR = 0x0; 
-
-       if (cpu_is_ixp46x() || cpu_is_ixp43x()) {
-               /* Route upper 32 sources to IRQ instead of FIQ */
-               *IXP4XX_ICLR2 = 0x00;
-
-               /* Disable upper 32 interrupts */
-               *IXP4XX_ICMR2 = 0x00;
-       }
-
-        /* Default to all level triggered */
-       for(i = 0; i < NR_IRQS; i++) {
-               irq_set_chip_and_handler(i, &ixp4xx_irq_chip,
-                                        handle_level_irq);
-               irq_clear_status_flags(i, IRQ_NOREQUEST);
-       }
+       ixp4xx_irq_init(IXP4XX_INTC_BASE_PHYS,
+                       (cpu_is_ixp46x() || cpu_is_ixp43x()));
 }
 
-
-/*************************************************************************
- * IXP4xx timer tick
- * We use OS timer1 on the CPU for the timer tick and the timestamp 
- * counter as a source of real clock ticks to account for missed jiffies.
- *************************************************************************/
-
-static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
-{
-       struct clock_event_device *evt = dev_id;
-
-       /* Clear Pending Interrupt by writing '1' to it */
-       *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
-
-       evt->event_handler(evt);
-
-       return IRQ_HANDLED;
-}
-
-static struct irqaction ixp4xx_timer_irq = {
-       .name           = "timer1",
-       .flags          = IRQF_TIMER | IRQF_IRQPOLL,
-       .handler        = ixp4xx_timer_interrupt,
-       .dev_id         = &clockevent_ixp4xx,
-};
-
 void __init ixp4xx_timer_init(void)
 {
-       /* Reset/disable counter */
-       *IXP4XX_OSRT1 = 0;
-
-       /* Clear Pending Interrupt by writing '1' to it */
-       *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
-
-       /* Reset time-stamp counter */
-       *IXP4XX_OSTS = 0;
-
-       /* Connect the interrupt handler and enable the interrupt */
-       setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq);
-
-       ixp4xx_clocksource_init();
-       ixp4xx_clockevent_init();
+       return ixp4xx_timer_setup(IXP4XX_TIMER_BASE_PHYS,
+                                 IRQ_IXP4XX_TIMER1,
+                                 IXP4XX_TIMER_FREQ);
 }
 
 static struct pxa2xx_udc_mach_info ixp4xx_udc_info;
@@ -364,6 +113,24 @@ static struct resource ixp4xx_udc_resources[] = {
        },
 };
 
+static struct resource ixp4xx_gpio_resource[] = {
+       {
+               .start = IXP4XX_GPIO_BASE_PHYS,
+               .end = IXP4XX_GPIO_BASE_PHYS + 0xfff,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device ixp4xx_gpio_device = {
+       .name           = "ixp4xx-gpio",
+       .id             = -1,
+       .dev = {
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .resource = ixp4xx_gpio_resource,
+       .num_resources  = ARRAY_SIZE(ixp4xx_gpio_resource),
+};
+
 /*
  * USB device controller. The IXP4xx uses the same controller as PXA25X,
  * so we just use the same device.
@@ -378,7 +145,61 @@ static struct platform_device ixp4xx_udc_device = {
        },
 };
 
+static struct resource ixp4xx_npe_resources[] = {
+       {
+               .start = IXP4XX_NPEA_BASE_PHYS,
+               .end = IXP4XX_NPEA_BASE_PHYS + 0xfff,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = IXP4XX_NPEB_BASE_PHYS,
+               .end = IXP4XX_NPEB_BASE_PHYS + 0xfff,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = IXP4XX_NPEC_BASE_PHYS,
+               .end = IXP4XX_NPEC_BASE_PHYS + 0xfff,
+               .flags = IORESOURCE_MEM,
+       },
+
+};
+
+static struct platform_device ixp4xx_npe_device = {
+       .name           = "ixp4xx-npe",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(ixp4xx_npe_resources),
+       .resource       = ixp4xx_npe_resources,
+};
+
+static struct resource ixp4xx_qmgr_resources[] = {
+       {
+               .start = IXP4XX_QMGR_BASE_PHYS,
+               .end = IXP4XX_QMGR_BASE_PHYS + 0x3fff,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = IRQ_IXP4XX_QM1,
+               .end = IRQ_IXP4XX_QM1,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = IRQ_IXP4XX_QM2,
+               .end = IRQ_IXP4XX_QM2,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device ixp4xx_qmgr_device = {
+       .name           = "ixp4xx-qmgr",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(ixp4xx_qmgr_resources),
+       .resource       = ixp4xx_qmgr_resources,
+};
+
 static struct platform_device *ixp4xx_devices[] __initdata = {
+       &ixp4xx_npe_device,
+       &ixp4xx_qmgr_device,
+       &ixp4xx_gpio_device,
        &ixp4xx_udc_device,
 };
 
@@ -413,56 +234,12 @@ static struct platform_device *ixp46x_devices[] __initdata = {
 unsigned long ixp4xx_exp_bus_size;
 EXPORT_SYMBOL(ixp4xx_exp_bus_size);
 
-static int ixp4xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
-{
-       gpio_line_config(gpio, IXP4XX_GPIO_IN);
-
-       return 0;
-}
-
-static int ixp4xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
-                                       int level)
-{
-       gpio_line_set(gpio, level);
-       gpio_line_config(gpio, IXP4XX_GPIO_OUT);
-
-       return 0;
-}
-
-static int ixp4xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
-{
-       int value;
-
-       gpio_line_get(gpio, &value);
-
-       return value;
-}
-
-static void ixp4xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
-                                 int value)
-{
-       gpio_line_set(gpio, value);
-}
-
-static struct gpio_chip ixp4xx_gpio_chip = {
-       .label                  = "IXP4XX_GPIO_CHIP",
-       .direction_input        = ixp4xx_gpio_direction_input,
-       .direction_output       = ixp4xx_gpio_direction_output,
-       .get                    = ixp4xx_gpio_get_value,
-       .set                    = ixp4xx_gpio_set_value,
-       .to_irq                 = ixp4xx_gpio_to_irq,
-       .base                   = 0,
-       .ngpio                  = 16,
-};
-
 void __init ixp4xx_sys_init(void)
 {
        ixp4xx_exp_bus_size = SZ_16M;
 
        platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices));
 
-       gpiochip_add_data(&ixp4xx_gpio_chip, NULL);
-
        if (cpu_is_ixp46x()) {
                int region;
 
@@ -481,103 +258,8 @@ void __init ixp4xx_sys_init(void)
                        ixp4xx_exp_bus_size >> 20);
 }
 
-/*
- * sched_clock()
- */
-static u64 notrace ixp4xx_read_sched_clock(void)
-{
-       return *IXP4XX_OSTS;
-}
-
-/*
- * clocksource
- */
-
-static u64 ixp4xx_clocksource_read(struct clocksource *c)
-{
-       return *IXP4XX_OSTS;
-}
-
 unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ;
 EXPORT_SYMBOL(ixp4xx_timer_freq);
-static void __init ixp4xx_clocksource_init(void)
-{
-       sched_clock_register(ixp4xx_read_sched_clock, 32, ixp4xx_timer_freq);
-
-       clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32,
-                       ixp4xx_clocksource_read);
-}
-
-/*
- * clockevents
- */
-static int ixp4xx_set_next_event(unsigned long evt,
-                                struct clock_event_device *unused)
-{
-       unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
-
-       *IXP4XX_OSRT1 = (evt & ~IXP4XX_OST_RELOAD_MASK) | opts;
-
-       return 0;
-}
-
-static int ixp4xx_shutdown(struct clock_event_device *evt)
-{
-       unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
-       unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;
-
-       opts &= ~IXP4XX_OST_ENABLE;
-       *IXP4XX_OSRT1 = osrt | opts;
-       return 0;
-}
-
-static int ixp4xx_set_oneshot(struct clock_event_device *evt)
-{
-       unsigned long opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT;
-       unsigned long osrt = 0;
-
-       /* period set by 'set next_event' */
-       *IXP4XX_OSRT1 = osrt | opts;
-       return 0;
-}
-
-static int ixp4xx_set_periodic(struct clock_event_device *evt)
-{
-       unsigned long opts = IXP4XX_OST_ENABLE;
-       unsigned long osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK;
-
-       *IXP4XX_OSRT1 = osrt | opts;
-       return 0;
-}
-
-static int ixp4xx_resume(struct clock_event_device *evt)
-{
-       unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
-       unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;
-
-       opts |= IXP4XX_OST_ENABLE;
-       *IXP4XX_OSRT1 = osrt | opts;
-       return 0;
-}
-
-static struct clock_event_device clockevent_ixp4xx = {
-       .name                   = "ixp4xx timer1",
-       .features               = CLOCK_EVT_FEAT_PERIODIC |
-                                 CLOCK_EVT_FEAT_ONESHOT,
-       .rating                 = 200,
-       .set_state_shutdown     = ixp4xx_shutdown,
-       .set_state_periodic     = ixp4xx_set_periodic,
-       .set_state_oneshot      = ixp4xx_set_oneshot,
-       .tick_resume            = ixp4xx_resume,
-       .set_next_event         = ixp4xx_set_next_event,
-};
-
-static void __init ixp4xx_clockevent_init(void)
-{
-       clockevent_ixp4xx.cpumask = cpumask_of(0);
-       clockevents_config_and_register(&clockevent_ixp4xx, IXP4XX_TIMER_FREQ,
-                                       0xf, 0xfffffffe);
-}
 
 void ixp4xx_restart(enum reboot_mode mode, const char *cmd)
 {
index 5d14ce2..a16c35d 100644 (file)
@@ -23,6 +23,8 @@
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 
+#include "irqs.h"
+
 #define SLOT0_DEVID    14
 #define SLOT1_DEVID    15
 
index 7e40fe7..7ca43ca 100644 (file)
@@ -25,6 +25,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 #define COYOTE_IDE_BASE_PHYS   IXP4XX_EXP_BUS_BASE(3)
 #define COYOTE_IDE_BASE_VIRT   0xFFFE1000
 #define COYOTE_IDE_REGION_SIZE 0x1000
index 8dca769..6899023 100644 (file)
@@ -22,6 +22,8 @@
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 #define MAX_DEV                4
 #define IRQ_LINES      3
 
index 397190f..4d4c62f 100644 (file)
@@ -35,6 +35,8 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/time.h>
 
+#include "irqs.h"
+
 #define DSMG600_SDA_PIN                5
 #define DSMG600_SCL_PIN                4
 
@@ -268,9 +270,6 @@ static void __init dsmg600_init(void)
 {
        ixp4xx_sys_init();
 
-       /* Make sure that GPIO14 and GPIO15 are not used as clocks */
-       *IXP4XX_GPIO_GPCLKR = 0;
-
        dsmg600_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
        dsmg600_flash_resource.end =
                IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
index fd4a862..6c08bb9 100644 (file)
@@ -22,6 +22,8 @@
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 #define MAX_DEV                3
 #define IRQ_LINES      3
 
index f0a152e..648932d 100644 (file)
@@ -29,6 +29,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 #define FSG_SDA_PIN            12
 #define FSG_SCL_PIN            13
 
index d9d6cc0..903c753 100644 (file)
@@ -27,6 +27,8 @@
 
 #include <asm/mach/pci.h>
 
+#include "irqs.h"
+
 void __init gateway7001_pci_preinit(void)
 {
        irq_set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW);
index 1be6faf..678e7df 100644 (file)
@@ -28,6 +28,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 static struct flash_platform_data gateway7001_flash_data = {
        .map_name       = "cfi_probe",
        .width          = 2,
index 551d114..1223d16 100644 (file)
@@ -30,6 +30,8 @@
 #include <mach/hardware.h>
 #include <asm/mach/pci.h>
 
+#include "irqs.h"
+
 #define SLOT0_DEVID    0
 #define SLOT1_DEVID    1
 #define INTA           10 /* slot 1 has INTA and INTB crossed */
index 16a1299..5dbdde8 100644 (file)
@@ -36,6 +36,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 /* GPIO 5,6,7 and 12 are hard wired to the Kendin KS8995M Switch
    and operate as an SPI type interface.  The details of the interface
    are available on Kendin/Micrel's web site. */
diff --git a/arch/arm/mach-ixp4xx/include/mach/entry-macro.S b/arch/arm/mach-ixp4xx/include/mach/entry-macro.S
deleted file mode 100644 (file)
index 79adf83..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for IXP4xx-based platforms
- *
- * 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 <mach/hardware.h>
-
-               .macro  get_irqnr_preamble, base, tmp
-               .endm
-
-               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-               ldr     \irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP_OFFSET)
-               ldr     \irqstat, [\irqstat]            @ get interrupts
-               cmp     \irqstat, #0
-               beq     1001f                           @ upper IRQ?
-               clz     \irqnr, \irqstat
-               mov     \base, #31
-               sub     \irqnr, \base, \irqnr
-               b       1002f                           @ lower IRQ being
-                                                       @ handled
-
-1001:
-               /*
-                * IXP465/IXP435 has an upper IRQ status register
-                */
-#if defined(CONFIG_CPU_IXP46X) || defined(CONFIG_CPU_IXP43X)
-               ldr     \irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP2_OFFSET)
-               ldr     \irqstat, [\irqstat]            @ get upper interrupts
-               mov     \irqnr, #63
-               clz     \irqstat, \irqstat
-               cmp     \irqstat, #32
-               subne   \irqnr, \irqnr, \irqstat
-#endif
-1002:
-               .endm
-
-
diff --git a/arch/arm/mach-ixp4xx/include/mach/irqs.h b/arch/arm/mach-ixp4xx/include/mach/irqs.h
deleted file mode 100644 (file)
index 7e6d4cc..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/include/mach/irqs.h 
- *
- * IRQ definitions for IXP4XX based systems
- *
- * Copyright (C) 2002 Intel Corporation.
- * Copyright (C) 2003 MontaVista Software, 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 _ARCH_IXP4XX_IRQS_H_
-#define _ARCH_IXP4XX_IRQS_H_
-
-#define IRQ_IXP4XX_NPEA                0
-#define IRQ_IXP4XX_NPEB                1
-#define IRQ_IXP4XX_NPEC                2
-#define IRQ_IXP4XX_QM1         3
-#define IRQ_IXP4XX_QM2         4
-#define IRQ_IXP4XX_TIMER1      5
-#define IRQ_IXP4XX_GPIO0       6
-#define IRQ_IXP4XX_GPIO1       7
-#define IRQ_IXP4XX_PCI_INT     8
-#define IRQ_IXP4XX_PCI_DMA1    9
-#define IRQ_IXP4XX_PCI_DMA2    10
-#define IRQ_IXP4XX_TIMER2      11
-#define IRQ_IXP4XX_USB         12
-#define IRQ_IXP4XX_UART2       13
-#define IRQ_IXP4XX_TIMESTAMP   14
-#define IRQ_IXP4XX_UART1       15
-#define IRQ_IXP4XX_WDOG                16
-#define IRQ_IXP4XX_AHB_PMU     17
-#define IRQ_IXP4XX_XSCALE_PMU  18
-#define IRQ_IXP4XX_GPIO2       19
-#define IRQ_IXP4XX_GPIO3       20
-#define IRQ_IXP4XX_GPIO4       21
-#define IRQ_IXP4XX_GPIO5       22
-#define IRQ_IXP4XX_GPIO6       23
-#define IRQ_IXP4XX_GPIO7       24
-#define IRQ_IXP4XX_GPIO8       25
-#define IRQ_IXP4XX_GPIO9       26
-#define IRQ_IXP4XX_GPIO10      27
-#define IRQ_IXP4XX_GPIO11      28
-#define IRQ_IXP4XX_GPIO12      29
-#define IRQ_IXP4XX_SW_INT1     30
-#define IRQ_IXP4XX_SW_INT2     31
-#define IRQ_IXP4XX_USB_HOST    32
-#define IRQ_IXP4XX_I2C         33
-#define IRQ_IXP4XX_SSP         34
-#define IRQ_IXP4XX_TSYNC       35
-#define IRQ_IXP4XX_EAU_DONE    36
-#define IRQ_IXP4XX_SHA_DONE    37
-#define IRQ_IXP4XX_SWCP_PE     58
-#define IRQ_IXP4XX_QM_PE       60
-#define IRQ_IXP4XX_MCU_ECC     61
-#define IRQ_IXP4XX_EXP_PE      62
-
-#define _IXP4XX_GPIO_IRQ(n)    (IRQ_IXP4XX_GPIO ## n)
-#define IXP4XX_GPIO_IRQ(n)     _IXP4XX_GPIO_IRQ(n)
-
-/*
- * Only first 32 sources are valid if running on IXP42x systems
- */
-#if defined(CONFIG_CPU_IXP46X) || defined(CONFIG_CPU_IXP43X)
-#define NR_IRQS                        64
-#else
-#define NR_IRQS                        32
-#endif
-
-#define        XSCALE_PMU_IRQ          (IRQ_IXP4XX_XSCALE_PMU)
-
-#endif
index b7ddd27..588b766 100644 (file)
@@ -43,8 +43,6 @@
  * Queue Manager
  */
 #define IXP4XX_QMGR_BASE_PHYS          0x60000000
-#define IXP4XX_QMGR_BASE_VIRT          IOMEM(0xFEF15000)
-#define IXP4XX_QMGR_REGION_SIZE                0x00004000
 
 /*
  * Peripheral space, including debug UART. Must be section-aligned so that
 #define IXP4XX_INTC_BASE_VIRT          (IXP4XX_PERIPHERAL_BASE_VIRT + 0x3000)
 #define IXP4XX_GPIO_BASE_VIRT          (IXP4XX_PERIPHERAL_BASE_VIRT + 0x4000)
 #define IXP4XX_TIMER_BASE_VIRT         (IXP4XX_PERIPHERAL_BASE_VIRT + 0x5000)
-#define IXP4XX_NPEA_BASE_VIRT          (IXP4XX_PERIPHERAL_BASE_VIRT + 0x6000)
-#define IXP4XX_NPEB_BASE_VIRT          (IXP4XX_PERIPHERAL_BASE_VIRT + 0x7000)
-#define IXP4XX_NPEC_BASE_VIRT          (IXP4XX_PERIPHERAL_BASE_VIRT + 0x8000)
 #define IXP4XX_EthB_BASE_VIRT          (IXP4XX_PERIPHERAL_BASE_VIRT + 0x9000)
 #define IXP4XX_EthC_BASE_VIRT          (IXP4XX_PERIPHERAL_BASE_VIRT + 0xA000)
 #define IXP4XX_USB_BASE_VIRT           (IXP4XX_PERIPHERAL_BASE_VIRT + 0xB000)
 #define IXP4XX_I2C_BASE_VIRT           (IXP4XX_PERIPHERAL_BASE_VIRT + 0x11000)
 #define IXP4XX_SSP_BASE_VIRT           (IXP4XX_PERIPHERAL_BASE_VIRT + 0x12000)
 
-/*
- * Constants to make it easy to access  Interrupt Controller registers
- */
-#define IXP4XX_ICPR_OFFSET     0x00 /* Interrupt Status */
-#define IXP4XX_ICMR_OFFSET     0x04 /* Interrupt Enable */
-#define IXP4XX_ICLR_OFFSET     0x08 /* Interrupt IRQ/FIQ Select */
-#define IXP4XX_ICIP_OFFSET      0x0C /* IRQ Status */
-#define IXP4XX_ICFP_OFFSET     0x10 /* FIQ Status */
-#define IXP4XX_ICHR_OFFSET     0x14 /* Interrupt Priority */
-#define IXP4XX_ICIH_OFFSET     0x18 /* IRQ Highest Pri Int */
-#define IXP4XX_ICFH_OFFSET     0x1C /* FIQ Highest Pri Int */
-
-/*
- * IXP465-only
- */
-#define        IXP4XX_ICPR2_OFFSET     0x20 /* Interrupt Status 2 */
-#define        IXP4XX_ICMR2_OFFSET     0x24 /* Interrupt Enable 2 */
-#define        IXP4XX_ICLR2_OFFSET     0x28 /* Interrupt IRQ/FIQ Select 2 */
-#define IXP4XX_ICIP2_OFFSET     0x2C /* IRQ Status */
-#define IXP4XX_ICFP2_OFFSET    0x30 /* FIQ Status */
-#define IXP4XX_ICEEN_OFFSET    0x34 /* Error High Pri Enable */
-
-
-/*
- * Interrupt Controller Register Definitions.
- */
-
-#define IXP4XX_INTC_REG(x) ((volatile u32 *)(IXP4XX_INTC_BASE_VIRT+(x)))
-
-#define IXP4XX_ICPR    IXP4XX_INTC_REG(IXP4XX_ICPR_OFFSET)
-#define IXP4XX_ICMR     IXP4XX_INTC_REG(IXP4XX_ICMR_OFFSET)
-#define IXP4XX_ICLR     IXP4XX_INTC_REG(IXP4XX_ICLR_OFFSET)
-#define IXP4XX_ICIP     IXP4XX_INTC_REG(IXP4XX_ICIP_OFFSET)
-#define IXP4XX_ICFP     IXP4XX_INTC_REG(IXP4XX_ICFP_OFFSET)
-#define IXP4XX_ICHR     IXP4XX_INTC_REG(IXP4XX_ICHR_OFFSET)
-#define IXP4XX_ICIH     IXP4XX_INTC_REG(IXP4XX_ICIH_OFFSET) 
-#define IXP4XX_ICFH     IXP4XX_INTC_REG(IXP4XX_ICFH_OFFSET)
-#define IXP4XX_ICPR2   IXP4XX_INTC_REG(IXP4XX_ICPR2_OFFSET)
-#define IXP4XX_ICMR2    IXP4XX_INTC_REG(IXP4XX_ICMR2_OFFSET)
-#define IXP4XX_ICLR2    IXP4XX_INTC_REG(IXP4XX_ICLR2_OFFSET)
-#define IXP4XX_ICIP2    IXP4XX_INTC_REG(IXP4XX_ICIP2_OFFSET)
-#define IXP4XX_ICFP2    IXP4XX_INTC_REG(IXP4XX_ICFP2_OFFSET)
-#define IXP4XX_ICEEN    IXP4XX_INTC_REG(IXP4XX_ICEEN_OFFSET)
-                                                                                
-/*
- * Constants to make it easy to access GPIO registers
- */
-#define IXP4XX_GPIO_GPOUTR_OFFSET       0x00
-#define IXP4XX_GPIO_GPOER_OFFSET        0x04
-#define IXP4XX_GPIO_GPINR_OFFSET        0x08
-#define IXP4XX_GPIO_GPISR_OFFSET        0x0C
-#define IXP4XX_GPIO_GPIT1R_OFFSET      0x10
-#define IXP4XX_GPIO_GPIT2R_OFFSET      0x14
-#define IXP4XX_GPIO_GPCLKR_OFFSET      0x18
-#define IXP4XX_GPIO_GPDBSELR_OFFSET    0x1C
-
-/* 
- * GPIO Register Definitions.
- * [Only perform 32bit reads/writes]
- */
-#define IXP4XX_GPIO_REG(x) ((volatile u32 *)(IXP4XX_GPIO_BASE_VIRT+(x)))
-
-#define IXP4XX_GPIO_GPOUTR     IXP4XX_GPIO_REG(IXP4XX_GPIO_GPOUTR_OFFSET)
-#define IXP4XX_GPIO_GPOER       IXP4XX_GPIO_REG(IXP4XX_GPIO_GPOER_OFFSET)
-#define IXP4XX_GPIO_GPINR       IXP4XX_GPIO_REG(IXP4XX_GPIO_GPINR_OFFSET)
-#define IXP4XX_GPIO_GPISR       IXP4XX_GPIO_REG(IXP4XX_GPIO_GPISR_OFFSET)
-#define IXP4XX_GPIO_GPIT1R      IXP4XX_GPIO_REG(IXP4XX_GPIO_GPIT1R_OFFSET)
-#define IXP4XX_GPIO_GPIT2R      IXP4XX_GPIO_REG(IXP4XX_GPIO_GPIT2R_OFFSET)
-#define IXP4XX_GPIO_GPCLKR      IXP4XX_GPIO_REG(IXP4XX_GPIO_GPCLKR_OFFSET)
-#define IXP4XX_GPIO_GPDBSELR    IXP4XX_GPIO_REG(IXP4XX_GPIO_GPDBSELR_OFFSET)
-
-/*
- * GPIO register bit definitions
- */
-
-/* Interrupt styles
- */
-#define IXP4XX_GPIO_STYLE_ACTIVE_HIGH  0x0
-#define IXP4XX_GPIO_STYLE_ACTIVE_LOW   0x1
-#define IXP4XX_GPIO_STYLE_RISING_EDGE  0x2
-#define IXP4XX_GPIO_STYLE_FALLING_EDGE 0x3
-#define IXP4XX_GPIO_STYLE_TRANSITIONAL 0x4
-
-/* 
- * Mask used to clear interrupt styles 
- */
-#define IXP4XX_GPIO_STYLE_CLEAR                0x7
-#define IXP4XX_GPIO_STYLE_SIZE         3
-
 /*
  * Constants to make it easy to access Timer Control/Status registers
  */
diff --git a/arch/arm/mach-ixp4xx/include/mach/npe.h b/arch/arm/mach-ixp4xx/include/mach/npe.h
deleted file mode 100644 (file)
index 3a98084..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __IXP4XX_NPE_H
-#define __IXP4XX_NPE_H
-
-#include <linux/kernel.h>
-
-extern const char *npe_names[];
-
-struct npe_regs {
-       u32 exec_addr, exec_data, exec_status_cmd, exec_count;
-       u32 action_points[4];
-       u32 watchpoint_fifo, watch_count;
-       u32 profile_count;
-       u32 messaging_status, messaging_control;
-       u32 mailbox_status, /*messaging_*/ in_out_fifo;
-};
-
-struct npe {
-       struct resource *mem_res;
-       struct npe_regs __iomem *regs;
-       u32 regs_phys;
-       int id;
-       int valid;
-};
-
-
-static inline const char *npe_name(struct npe *npe)
-{
-       return npe_names[npe->id];
-}
-
-int npe_running(struct npe *npe);
-int npe_send_message(struct npe *npe, const void *msg, const char *what);
-int npe_recv_message(struct npe *npe, void *msg, const char *what);
-int npe_send_recv_message(struct npe *npe, void *msg, const char *what);
-int npe_load_firmware(struct npe *npe, const char *name, struct device *dev);
-struct npe *npe_request(unsigned id);
-void npe_release(struct npe *npe);
-
-#endif /* __IXP4XX_NPE_H */
diff --git a/arch/arm/mach-ixp4xx/include/mach/qmgr.h b/arch/arm/mach-ixp4xx/include/mach/qmgr.h
deleted file mode 100644 (file)
index 4de8da5..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- */
-
-#ifndef IXP4XX_QMGR_H
-#define IXP4XX_QMGR_H
-
-#include <linux/io.h>
-#include <linux/kernel.h>
-
-#define DEBUG_QMGR     0
-
-#define HALF_QUEUES    32
-#define QUEUES         64
-#define MAX_QUEUE_LENGTH 4     /* in dwords */
-
-#define QUEUE_STAT1_EMPTY              1 /* queue status bits */
-#define QUEUE_STAT1_NEARLY_EMPTY       2
-#define QUEUE_STAT1_NEARLY_FULL                4
-#define QUEUE_STAT1_FULL               8
-#define QUEUE_STAT2_UNDERFLOW          1
-#define QUEUE_STAT2_OVERFLOW           2
-
-#define QUEUE_WATERMARK_0_ENTRIES      0
-#define QUEUE_WATERMARK_1_ENTRY                1
-#define QUEUE_WATERMARK_2_ENTRIES      2
-#define QUEUE_WATERMARK_4_ENTRIES      3
-#define QUEUE_WATERMARK_8_ENTRIES      4
-#define QUEUE_WATERMARK_16_ENTRIES     5
-#define QUEUE_WATERMARK_32_ENTRIES     6
-#define QUEUE_WATERMARK_64_ENTRIES     7
-
-/* queue interrupt request conditions */
-#define QUEUE_IRQ_SRC_EMPTY            0
-#define QUEUE_IRQ_SRC_NEARLY_EMPTY     1
-#define QUEUE_IRQ_SRC_NEARLY_FULL      2
-#define QUEUE_IRQ_SRC_FULL             3
-#define QUEUE_IRQ_SRC_NOT_EMPTY                4
-#define QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY 5
-#define QUEUE_IRQ_SRC_NOT_NEARLY_FULL  6
-#define QUEUE_IRQ_SRC_NOT_FULL         7
-
-struct qmgr_regs {
-       u32 acc[QUEUES][MAX_QUEUE_LENGTH]; /* 0x000 - 0x3FF */
-       u32 stat1[4];           /* 0x400 - 0x40F */
-       u32 stat2[2];           /* 0x410 - 0x417 */
-       u32 statne_h;           /* 0x418 - queue nearly empty */
-       u32 statf_h;            /* 0x41C - queue full */
-       u32 irqsrc[4];          /* 0x420 - 0x42F IRC source */
-       u32 irqen[2];           /* 0x430 - 0x437 IRQ enabled */
-       u32 irqstat[2];         /* 0x438 - 0x43F - IRQ access only */
-       u32 reserved[1776];
-       u32 sram[2048];         /* 0x2000 - 0x3FFF - config and buffer */
-};
-
-void qmgr_set_irq(unsigned int queue, int src,
-                 void (*handler)(void *pdev), void *pdev);
-void qmgr_enable_irq(unsigned int queue);
-void qmgr_disable_irq(unsigned int queue);
-
-/* request_ and release_queue() must be called from non-IRQ context */
-
-#if DEBUG_QMGR
-extern char qmgr_queue_descs[QUEUES][32];
-
-int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
-                      unsigned int nearly_empty_watermark,
-                      unsigned int nearly_full_watermark,
-                      const char *desc_format, const char* name);
-#else
-int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
-                        unsigned int nearly_empty_watermark,
-                        unsigned int nearly_full_watermark);
-#define qmgr_request_queue(queue, len, nearly_empty_watermark,         \
-                          nearly_full_watermark, desc_format, name)    \
-       __qmgr_request_queue(queue, len, nearly_empty_watermark,        \
-                            nearly_full_watermark)
-#endif
-
-void qmgr_release_queue(unsigned int queue);
-
-
-static inline void qmgr_put_entry(unsigned int queue, u32 val)
-{
-       struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
-#if DEBUG_QMGR
-       BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
-
-       printk(KERN_DEBUG "Queue %s(%i) put %X\n",
-              qmgr_queue_descs[queue], queue, val);
-#endif
-       __raw_writel(val, &qmgr_regs->acc[queue][0]);
-}
-
-static inline u32 qmgr_get_entry(unsigned int queue)
-{
-       u32 val;
-       const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
-       val = __raw_readl(&qmgr_regs->acc[queue][0]);
-#if DEBUG_QMGR
-       BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
-
-       printk(KERN_DEBUG "Queue %s(%i) get %X\n",
-              qmgr_queue_descs[queue], queue, val);
-#endif
-       return val;
-}
-
-static inline int __qmgr_get_stat1(unsigned int queue)
-{
-       const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
-       return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
-               >> ((queue & 7) << 2)) & 0xF;
-}
-
-static inline int __qmgr_get_stat2(unsigned int queue)
-{
-       const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
-       BUG_ON(queue >= HALF_QUEUES);
-       return (__raw_readl(&qmgr_regs->stat2[queue >> 4])
-               >> ((queue & 0xF) << 1)) & 0x3;
-}
-
-/**
- * qmgr_stat_empty() - checks if a hardware queue is empty
- * @queue:     queue number
- *
- * Returns non-zero value if the queue is empty.
- */
-static inline int qmgr_stat_empty(unsigned int queue)
-{
-       BUG_ON(queue >= HALF_QUEUES);
-       return __qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY;
-}
-
-/**
- * qmgr_stat_below_low_watermark() - checks if a queue is below low watermark
- * @queue:     queue number
- *
- * Returns non-zero value if the queue is below low watermark.
- */
-static inline int qmgr_stat_below_low_watermark(unsigned int queue)
-{
-       const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
-       if (queue >= HALF_QUEUES)
-               return (__raw_readl(&qmgr_regs->statne_h) >>
-                       (queue - HALF_QUEUES)) & 0x01;
-       return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY;
-}
-
-/**
- * qmgr_stat_above_high_watermark() - checks if a queue is above high watermark
- * @queue:     queue number
- *
- * Returns non-zero value if the queue is above high watermark
- */
-static inline int qmgr_stat_above_high_watermark(unsigned int queue)
-{
-       BUG_ON(queue >= HALF_QUEUES);
-       return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL;
-}
-
-/**
- * qmgr_stat_full() - checks if a hardware queue is full
- * @queue:     queue number
- *
- * Returns non-zero value if the queue is full.
- */
-static inline int qmgr_stat_full(unsigned int queue)
-{
-       const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
-       if (queue >= HALF_QUEUES)
-               return (__raw_readl(&qmgr_regs->statf_h) >>
-                       (queue - HALF_QUEUES)) & 0x01;
-       return __qmgr_get_stat1(queue) & QUEUE_STAT1_FULL;
-}
-
-/**
- * qmgr_stat_underflow() - checks if a hardware queue experienced underflow
- * @queue:     queue number
- *
- * Returns non-zero value if the queue experienced underflow.
- */
-static inline int qmgr_stat_underflow(unsigned int queue)
-{
-       return __qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW;
-}
-
-/**
- * qmgr_stat_overflow() - checks if a hardware queue experienced overflow
- * @queue:     queue number
- *
- * Returns non-zero value if the queue experienced overflow.
- */
-static inline int qmgr_stat_overflow(unsigned int queue)
-{
-       return __qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW;
-}
-
-#endif
diff --git a/arch/arm/mach-ixp4xx/irqs.h b/arch/arm/mach-ixp4xx/irqs.h
new file mode 100644 (file)
index 0000000..6b7f220
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * arch/arm/mach-ixp4xx/include/mach/irqs.h 
+ *
+ * IRQ definitions for IXP4XX based systems
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003 MontaVista Software, 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 _ARCH_IXP4XX_IRQS_H_
+#define _ARCH_IXP4XX_IRQS_H_
+
+#define IRQ_IXP4XX_BASE                16
+
+#define IRQ_IXP4XX_NPEA                (IRQ_IXP4XX_BASE + 0)
+#define IRQ_IXP4XX_NPEB                (IRQ_IXP4XX_BASE + 1)
+#define IRQ_IXP4XX_NPEC                (IRQ_IXP4XX_BASE + 2)
+#define IRQ_IXP4XX_QM1         (IRQ_IXP4XX_BASE + 3)
+#define IRQ_IXP4XX_QM2         (IRQ_IXP4XX_BASE + 4)
+#define IRQ_IXP4XX_TIMER1      (IRQ_IXP4XX_BASE + 5)
+#define IRQ_IXP4XX_GPIO0       (IRQ_IXP4XX_BASE + 6)
+#define IRQ_IXP4XX_GPIO1       (IRQ_IXP4XX_BASE + 7)
+#define IRQ_IXP4XX_PCI_INT     (IRQ_IXP4XX_BASE + 8)
+#define IRQ_IXP4XX_PCI_DMA1    (IRQ_IXP4XX_BASE + 9)
+#define IRQ_IXP4XX_PCI_DMA2    (IRQ_IXP4XX_BASE + 10)
+#define IRQ_IXP4XX_TIMER2      (IRQ_IXP4XX_BASE + 11)
+#define IRQ_IXP4XX_USB         (IRQ_IXP4XX_BASE + 12)
+#define IRQ_IXP4XX_UART2       (IRQ_IXP4XX_BASE + 13)
+#define IRQ_IXP4XX_TIMESTAMP   (IRQ_IXP4XX_BASE + 14)
+#define IRQ_IXP4XX_UART1       (IRQ_IXP4XX_BASE + 15)
+#define IRQ_IXP4XX_WDOG                (IRQ_IXP4XX_BASE + 16)
+#define IRQ_IXP4XX_AHB_PMU     (IRQ_IXP4XX_BASE + 17)
+#define IRQ_IXP4XX_XSCALE_PMU  (IRQ_IXP4XX_BASE + 18)
+#define IRQ_IXP4XX_GPIO2       (IRQ_IXP4XX_BASE + 19)
+#define IRQ_IXP4XX_GPIO3       (IRQ_IXP4XX_BASE + 20)
+#define IRQ_IXP4XX_GPIO4       (IRQ_IXP4XX_BASE + 21)
+#define IRQ_IXP4XX_GPIO5       (IRQ_IXP4XX_BASE + 22)
+#define IRQ_IXP4XX_GPIO6       (IRQ_IXP4XX_BASE + 23)
+#define IRQ_IXP4XX_GPIO7       (IRQ_IXP4XX_BASE + 24)
+#define IRQ_IXP4XX_GPIO8       (IRQ_IXP4XX_BASE + 25)
+#define IRQ_IXP4XX_GPIO9       (IRQ_IXP4XX_BASE + 26)
+#define IRQ_IXP4XX_GPIO10      (IRQ_IXP4XX_BASE + 27)
+#define IRQ_IXP4XX_GPIO11      (IRQ_IXP4XX_BASE + 28)
+#define IRQ_IXP4XX_GPIO12      (IRQ_IXP4XX_BASE + 29)
+#define IRQ_IXP4XX_SW_INT1     (IRQ_IXP4XX_BASE + 30)
+#define IRQ_IXP4XX_SW_INT2     (IRQ_IXP4XX_BASE + 31)
+#define IRQ_IXP4XX_USB_HOST    (IRQ_IXP4XX_BASE + 32)
+#define IRQ_IXP4XX_I2C         (IRQ_IXP4XX_BASE + 33)
+#define IRQ_IXP4XX_SSP         (IRQ_IXP4XX_BASE + 34)
+#define IRQ_IXP4XX_TSYNC       (IRQ_IXP4XX_BASE + 35)
+#define IRQ_IXP4XX_EAU_DONE    (IRQ_IXP4XX_BASE + 36)
+#define IRQ_IXP4XX_SHA_DONE    (IRQ_IXP4XX_BASE + 37)
+#define IRQ_IXP4XX_SWCP_PE     (IRQ_IXP4XX_BASE + 58)
+#define IRQ_IXP4XX_QM_PE       (IRQ_IXP4XX_BASE + 60)
+#define IRQ_IXP4XX_MCU_ECC     (IRQ_IXP4XX_BASE + 61)
+#define IRQ_IXP4XX_EXP_PE      (IRQ_IXP4XX_BASE + 62)
+
+#define _IXP4XX_GPIO_IRQ(n)    (IRQ_IXP4XX_GPIO ## n)
+#define IXP4XX_GPIO_IRQ(n)     _IXP4XX_GPIO_IRQ(n)
+
+#define        XSCALE_PMU_IRQ          (IRQ_IXP4XX_XSCALE_PMU)
+
+#endif
index 318424d..c134046 100644 (file)
@@ -24,6 +24,8 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 #define MAX_DEV                4
 #define IRQ_LINES      4
 
index 57d7df7..6f0f7ed 100644 (file)
@@ -32,6 +32,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 #define IXDP425_SDA_PIN                7
 #define IXDP425_SCL_PIN                6
 
index 1f8717b..ac0e9bc 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <asm/mach/pci.h>
 
+#include "irqs.h"
+
 void __init ixdpg425_pci_preinit(void)
 {
        irq_set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW);
diff --git a/arch/arm/mach-ixp4xx/ixp4xx-of.c b/arch/arm/mach-ixp4xx/ixp4xx-of.c
new file mode 100644 (file)
index 0000000..7449b83
--- /dev/null
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IXP4xx Device Tree boot support
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/ixp4xx-regs.h>
+
+static struct map_desc ixp4xx_of_io_desc[] __initdata = {
+       /*
+        * This is needed for runtime system configuration checks,
+        * such as reading if hardware so-and-so is present. This
+        * could eventually be converted into a syscon once all boards
+        * are converted to device tree.
+        */
+       {
+               .virtual = IXP4XX_EXP_CFG_BASE_VIRT,
+               .pfn = __phys_to_pfn(IXP4XX_EXP_CFG_BASE_PHYS),
+               .length = SZ_4K,
+               .type = MT_DEVICE,
+       },
+#ifdef CONFIG_DEBUG_UART_8250
+       /* This is needed for LL-debug/earlyprintk/debug-macro.S */
+       {
+               .virtual = CONFIG_DEBUG_UART_VIRT,
+               .pfn = __phys_to_pfn(CONFIG_DEBUG_UART_PHYS),
+               .length = SZ_4K,
+               .type = MT_DEVICE,
+       },
+#endif
+};
+
+static void __init ixp4xx_of_map_io(void)
+{
+       iotable_init(ixp4xx_of_io_desc, ARRAY_SIZE(ixp4xx_of_io_desc));
+}
+
+/*
+ * We handle 4 differen SoC families. These compatible strings are enough
+ * to provide the core so that different boards can add their more detailed
+ * specifics.
+ */
+static const char *ixp4xx_of_board_compat[] = {
+       "intel,ixp42x",
+       "intel,ixp43x",
+       "intel,ixp45x",
+       "intel,ixp46x",
+       NULL,
+};
+
+DT_MACHINE_START(IXP4XX_DT, "IXP4xx (Device Tree)")
+       .map_io         = ixp4xx_of_map_io,
+       .dt_compat      = ixp4xx_of_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
deleted file mode 100644 (file)
index d4eb09a..0000000
+++ /dev/null
@@ -1,742 +0,0 @@
-/*
- * Intel IXP4xx Network Processor Engine driver for Linux
- *
- * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- *
- * The code is based on publicly available information:
- * - Intel IXP4xx Developer's Manual and other e-papers
- * - Intel IXP400 Access Library Software (BSD license)
- * - previous works by Christian Hohnstaedt <chohnstaedt@innominate.com>
- *   Thanks, Christian.
- */
-
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/firmware.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <mach/npe.h>
-
-#define DEBUG_MSG                      0
-#define DEBUG_FW                       0
-
-#define NPE_COUNT                      3
-#define MAX_RETRIES                    1000    /* microseconds */
-#define NPE_42X_DATA_SIZE              0x800   /* in dwords */
-#define NPE_46X_DATA_SIZE              0x1000
-#define NPE_A_42X_INSTR_SIZE           0x1000
-#define NPE_B_AND_C_42X_INSTR_SIZE     0x800
-#define NPE_46X_INSTR_SIZE             0x1000
-#define REGS_SIZE                      0x1000
-
-#define NPE_PHYS_REG                   32
-
-#define FW_MAGIC                       0xFEEDF00D
-#define FW_BLOCK_TYPE_INSTR            0x0
-#define FW_BLOCK_TYPE_DATA             0x1
-#define FW_BLOCK_TYPE_EOF              0xF
-
-/* NPE exec status (read) and command (write) */
-#define CMD_NPE_STEP                   0x01
-#define CMD_NPE_START                  0x02
-#define CMD_NPE_STOP                   0x03
-#define CMD_NPE_CLR_PIPE               0x04
-#define CMD_CLR_PROFILE_CNT            0x0C
-#define CMD_RD_INS_MEM                 0x10 /* instruction memory */
-#define CMD_WR_INS_MEM                 0x11
-#define CMD_RD_DATA_MEM                        0x12 /* data memory */
-#define CMD_WR_DATA_MEM                        0x13
-#define CMD_RD_ECS_REG                 0x14 /* exec access register */
-#define CMD_WR_ECS_REG                 0x15
-
-#define STAT_RUN                       0x80000000
-#define STAT_STOP                      0x40000000
-#define STAT_CLEAR                     0x20000000
-#define STAT_ECS_K                     0x00800000 /* pipeline clean */
-
-#define NPE_STEVT                      0x1B
-#define NPE_STARTPC                    0x1C
-#define NPE_REGMAP                     0x1E
-#define NPE_CINDEX                     0x1F
-
-#define INSTR_WR_REG_SHORT             0x0000C000
-#define INSTR_WR_REG_BYTE              0x00004000
-#define INSTR_RD_FIFO                  0x0F888220
-#define INSTR_RESET_MBOX               0x0FAC8210
-
-#define ECS_BG_CTXT_REG_0              0x00 /* Background Executing Context */
-#define ECS_BG_CTXT_REG_1              0x01 /*         Stack level */
-#define ECS_BG_CTXT_REG_2              0x02
-#define ECS_PRI_1_CTXT_REG_0           0x04 /* Priority 1 Executing Context */
-#define ECS_PRI_1_CTXT_REG_1           0x05 /*         Stack level */
-#define ECS_PRI_1_CTXT_REG_2           0x06
-#define ECS_PRI_2_CTXT_REG_0           0x08 /* Priority 2 Executing Context */
-#define ECS_PRI_2_CTXT_REG_1           0x09 /*         Stack level */
-#define ECS_PRI_2_CTXT_REG_2           0x0A
-#define ECS_DBG_CTXT_REG_0             0x0C /* Debug Executing Context */
-#define ECS_DBG_CTXT_REG_1             0x0D /*         Stack level */
-#define ECS_DBG_CTXT_REG_2             0x0E
-#define ECS_INSTRUCT_REG               0x11 /* NPE Instruction Register */
-
-#define ECS_REG_0_ACTIVE               0x80000000 /* all levels */
-#define ECS_REG_0_NEXTPC_MASK          0x1FFF0000 /* BG/PRI1/PRI2 levels */
-#define ECS_REG_0_LDUR_BITS            8
-#define ECS_REG_0_LDUR_MASK            0x00000700 /* all levels */
-#define ECS_REG_1_CCTXT_BITS           16
-#define ECS_REG_1_CCTXT_MASK           0x000F0000 /* all levels */
-#define ECS_REG_1_SELCTXT_BITS         0
-#define ECS_REG_1_SELCTXT_MASK         0x0000000F /* all levels */
-#define ECS_DBG_REG_2_IF               0x00100000 /* debug level */
-#define ECS_DBG_REG_2_IE               0x00080000 /* debug level */
-
-/* NPE watchpoint_fifo register bit */
-#define WFIFO_VALID                    0x80000000
-
-/* NPE messaging_status register bit definitions */
-#define MSGSTAT_OFNE   0x00010000 /* OutFifoNotEmpty */
-#define MSGSTAT_IFNF   0x00020000 /* InFifoNotFull */
-#define MSGSTAT_OFNF   0x00040000 /* OutFifoNotFull */
-#define MSGSTAT_IFNE   0x00080000 /* InFifoNotEmpty */
-#define MSGSTAT_MBINT  0x00100000 /* Mailbox interrupt */
-#define MSGSTAT_IFINT  0x00200000 /* InFifo interrupt */
-#define MSGSTAT_OFINT  0x00400000 /* OutFifo interrupt */
-#define MSGSTAT_WFINT  0x00800000 /* WatchFifo interrupt */
-
-/* NPE messaging_control register bit definitions */
-#define MSGCTL_OUT_FIFO                        0x00010000 /* enable output FIFO */
-#define MSGCTL_IN_FIFO                 0x00020000 /* enable input FIFO */
-#define MSGCTL_OUT_FIFO_WRITE          0x01000000 /* enable FIFO + WRITE */
-#define MSGCTL_IN_FIFO_WRITE           0x02000000
-
-/* NPE mailbox_status value for reset */
-#define RESET_MBOX_STAT                        0x0000F0F0
-
-#define NPE_A_FIRMWARE "NPE-A"
-#define NPE_B_FIRMWARE "NPE-B"
-#define NPE_C_FIRMWARE "NPE-C"
-
-const char *npe_names[] = { NPE_A_FIRMWARE, NPE_B_FIRMWARE, NPE_C_FIRMWARE };
-
-#define print_npe(pri, npe, fmt, ...)                                  \
-       printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__)
-
-#if DEBUG_MSG
-#define debug_msg(npe, fmt, ...)                                       \
-       print_npe(KERN_DEBUG, npe, fmt, ## __VA_ARGS__)
-#else
-#define debug_msg(npe, fmt, ...)
-#endif
-
-static struct {
-       u32 reg, val;
-} ecs_reset[] = {
-       { ECS_BG_CTXT_REG_0,    0xA0000000 },
-       { ECS_BG_CTXT_REG_1,    0x01000000 },
-       { ECS_BG_CTXT_REG_2,    0x00008000 },
-       { ECS_PRI_1_CTXT_REG_0, 0x20000080 },
-       { ECS_PRI_1_CTXT_REG_1, 0x01000000 },
-       { ECS_PRI_1_CTXT_REG_2, 0x00008000 },
-       { ECS_PRI_2_CTXT_REG_0, 0x20000080 },
-       { ECS_PRI_2_CTXT_REG_1, 0x01000000 },
-       { ECS_PRI_2_CTXT_REG_2, 0x00008000 },
-       { ECS_DBG_CTXT_REG_0,   0x20000000 },
-       { ECS_DBG_CTXT_REG_1,   0x00000000 },
-       { ECS_DBG_CTXT_REG_2,   0x001E0000 },
-       { ECS_INSTRUCT_REG,     0x1003C00F },
-};
-
-static struct npe npe_tab[NPE_COUNT] = {
-       {
-               .id     = 0,
-               .regs   = (struct npe_regs __iomem *)IXP4XX_NPEA_BASE_VIRT,
-               .regs_phys = IXP4XX_NPEA_BASE_PHYS,
-       }, {
-               .id     = 1,
-               .regs   = (struct npe_regs __iomem *)IXP4XX_NPEB_BASE_VIRT,
-               .regs_phys = IXP4XX_NPEB_BASE_PHYS,
-       }, {
-               .id     = 2,
-               .regs   = (struct npe_regs __iomem *)IXP4XX_NPEC_BASE_VIRT,
-               .regs_phys = IXP4XX_NPEC_BASE_PHYS,
-       }
-};
-
-int npe_running(struct npe *npe)
-{
-       return (__raw_readl(&npe->regs->exec_status_cmd) & STAT_RUN) != 0;
-}
-
-static void npe_cmd_write(struct npe *npe, u32 addr, int cmd, u32 data)
-{
-       __raw_writel(data, &npe->regs->exec_data);
-       __raw_writel(addr, &npe->regs->exec_addr);
-       __raw_writel(cmd, &npe->regs->exec_status_cmd);
-}
-
-static u32 npe_cmd_read(struct npe *npe, u32 addr, int cmd)
-{
-       __raw_writel(addr, &npe->regs->exec_addr);
-       __raw_writel(cmd, &npe->regs->exec_status_cmd);
-       /* Iintroduce extra read cycles after issuing read command to NPE
-          so that we read the register after the NPE has updated it.
-          This is to overcome race condition between XScale and NPE */
-       __raw_readl(&npe->regs->exec_data);
-       __raw_readl(&npe->regs->exec_data);
-       return __raw_readl(&npe->regs->exec_data);
-}
-
-static void npe_clear_active(struct npe *npe, u32 reg)
-{
-       u32 val = npe_cmd_read(npe, reg, CMD_RD_ECS_REG);
-       npe_cmd_write(npe, reg, CMD_WR_ECS_REG, val & ~ECS_REG_0_ACTIVE);
-}
-
-static void npe_start(struct npe *npe)
-{
-       /* ensure only Background Context Stack Level is active */
-       npe_clear_active(npe, ECS_PRI_1_CTXT_REG_0);
-       npe_clear_active(npe, ECS_PRI_2_CTXT_REG_0);
-       npe_clear_active(npe, ECS_DBG_CTXT_REG_0);
-
-       __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
-       __raw_writel(CMD_NPE_START, &npe->regs->exec_status_cmd);
-}
-
-static void npe_stop(struct npe *npe)
-{
-       __raw_writel(CMD_NPE_STOP, &npe->regs->exec_status_cmd);
-       __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd); /*FIXME?*/
-}
-
-static int __must_check npe_debug_instr(struct npe *npe, u32 instr, u32 ctx,
-                                       u32 ldur)
-{
-       u32 wc;
-       int i;
-
-       /* set the Active bit, and the LDUR, in the debug level */
-       npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG,
-                     ECS_REG_0_ACTIVE | (ldur << ECS_REG_0_LDUR_BITS));
-
-       /* set CCTXT at ECS DEBUG L3 to specify in which context to execute
-          the instruction, and set SELCTXT at ECS DEBUG Level to specify
-          which context store to access.
-          Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
-       */
-       npe_cmd_write(npe, ECS_DBG_CTXT_REG_1, CMD_WR_ECS_REG,
-                     (ctx << ECS_REG_1_CCTXT_BITS) |
-                     (ctx << ECS_REG_1_SELCTXT_BITS));
-
-       /* clear the pipeline */
-       __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
-
-       /* load NPE instruction into the instruction register */
-       npe_cmd_write(npe, ECS_INSTRUCT_REG, CMD_WR_ECS_REG, instr);
-
-       /* we need this value later to wait for completion of NPE execution
-          step */
-       wc = __raw_readl(&npe->regs->watch_count);
-
-       /* issue a Step One command via the Execution Control register */
-       __raw_writel(CMD_NPE_STEP, &npe->regs->exec_status_cmd);
-
-       /* Watch Count register increments when NPE completes an instruction */
-       for (i = 0; i < MAX_RETRIES; i++) {
-               if (wc != __raw_readl(&npe->regs->watch_count))
-                       return 0;
-               udelay(1);
-       }
-
-       print_npe(KERN_ERR, npe, "reset: npe_debug_instr(): timeout\n");
-       return -ETIMEDOUT;
-}
-
-static int __must_check npe_logical_reg_write8(struct npe *npe, u32 addr,
-                                              u8 val, u32 ctx)
-{
-       /* here we build the NPE assembler instruction: mov8 d0, #0 */
-       u32 instr = INSTR_WR_REG_BYTE | /* OpCode */
-               addr << 9 |             /* base Operand */
-               (val & 0x1F) << 4 |     /* lower 5 bits to immediate data */
-               (val & ~0x1F) << (18 - 5);/* higher 3 bits to CoProc instr. */
-       return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
-}
-
-static int __must_check npe_logical_reg_write16(struct npe *npe, u32 addr,
-                                               u16 val, u32 ctx)
-{
-       /* here we build the NPE assembler instruction: mov16 d0, #0 */
-       u32 instr = INSTR_WR_REG_SHORT | /* OpCode */
-               addr << 9 |             /* base Operand */
-               (val & 0x1F) << 4 |     /* lower 5 bits to immediate data */
-               (val & ~0x1F) << (18 - 5);/* higher 11 bits to CoProc instr. */
-       return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
-}
-
-static int __must_check npe_logical_reg_write32(struct npe *npe, u32 addr,
-                                               u32 val, u32 ctx)
-{
-       /* write in 16 bit steps first the high and then the low value */
-       if (npe_logical_reg_write16(npe, addr, val >> 16, ctx))
-               return -ETIMEDOUT;
-       return npe_logical_reg_write16(npe, addr + 2, val & 0xFFFF, ctx);
-}
-
-static int npe_reset(struct npe *npe)
-{
-       u32 val, ctl, exec_count, ctx_reg2;
-       int i;
-
-       ctl = (__raw_readl(&npe->regs->messaging_control) | 0x3F000000) &
-               0x3F3FFFFF;
-
-       /* disable parity interrupt */
-       __raw_writel(ctl & 0x3F00FFFF, &npe->regs->messaging_control);
-
-       /* pre exec - debug instruction */
-       /* turn off the halt bit by clearing Execution Count register. */
-       exec_count = __raw_readl(&npe->regs->exec_count);
-       __raw_writel(0, &npe->regs->exec_count);
-       /* ensure that IF and IE are on (temporarily), so that we don't end up
-          stepping forever */
-       ctx_reg2 = npe_cmd_read(npe, ECS_DBG_CTXT_REG_2, CMD_RD_ECS_REG);
-       npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2 |
-                     ECS_DBG_REG_2_IF | ECS_DBG_REG_2_IE);
-
-       /* clear the FIFOs */
-       while (__raw_readl(&npe->regs->watchpoint_fifo) & WFIFO_VALID)
-               ;
-       while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE)
-               /* read from the outFIFO until empty */
-               print_npe(KERN_DEBUG, npe, "npe_reset: read FIFO = 0x%X\n",
-                         __raw_readl(&npe->regs->in_out_fifo));
-
-       while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)
-               /* step execution of the NPE intruction to read inFIFO using
-                  the Debug Executing Context stack */
-               if (npe_debug_instr(npe, INSTR_RD_FIFO, 0, 0))
-                       return -ETIMEDOUT;
-
-       /* reset the mailbox reg from the XScale side */
-       __raw_writel(RESET_MBOX_STAT, &npe->regs->mailbox_status);
-       /* from NPE side */
-       if (npe_debug_instr(npe, INSTR_RESET_MBOX, 0, 0))
-               return -ETIMEDOUT;
-
-       /* Reset the physical registers in the NPE register file */
-       for (val = 0; val < NPE_PHYS_REG; val++) {
-               if (npe_logical_reg_write16(npe, NPE_REGMAP, val >> 1, 0))
-                       return -ETIMEDOUT;
-               /* address is either 0 or 4 */
-               if (npe_logical_reg_write32(npe, (val & 1) * 4, 0, 0))
-                       return -ETIMEDOUT;
-       }
-
-       /* Reset the context store = each context's Context Store registers */
-
-       /* Context 0 has no STARTPC. Instead, this value is used to set NextPC
-          for Background ECS, to set where NPE starts executing code */
-       val = npe_cmd_read(npe, ECS_BG_CTXT_REG_0, CMD_RD_ECS_REG);
-       val &= ~ECS_REG_0_NEXTPC_MASK;
-       val |= (0 /* NextPC */ << 16) & ECS_REG_0_NEXTPC_MASK;
-       npe_cmd_write(npe, ECS_BG_CTXT_REG_0, CMD_WR_ECS_REG, val);
-
-       for (i = 0; i < 16; i++) {
-               if (i) {        /* Context 0 has no STEVT nor STARTPC */
-                       /* STEVT = off, 0x80 */
-                       if (npe_logical_reg_write8(npe, NPE_STEVT, 0x80, i))
-                               return -ETIMEDOUT;
-                       if (npe_logical_reg_write16(npe, NPE_STARTPC, 0, i))
-                               return -ETIMEDOUT;
-               }
-               /* REGMAP = d0->p0, d8->p2, d16->p4 */
-               if (npe_logical_reg_write16(npe, NPE_REGMAP, 0x820, i))
-                       return -ETIMEDOUT;
-               if (npe_logical_reg_write8(npe, NPE_CINDEX, 0, i))
-                       return -ETIMEDOUT;
-       }
-
-       /* post exec */
-       /* clear active bit in debug level */
-       npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG, 0);
-       /* clear the pipeline */
-       __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
-       /* restore previous values */
-       __raw_writel(exec_count, &npe->regs->exec_count);
-       npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2);
-
-       /* write reset values to Execution Context Stack registers */
-       for (val = 0; val < ARRAY_SIZE(ecs_reset); val++)
-               npe_cmd_write(npe, ecs_reset[val].reg, CMD_WR_ECS_REG,
-                             ecs_reset[val].val);
-
-       /* clear the profile counter */
-       __raw_writel(CMD_CLR_PROFILE_CNT, &npe->regs->exec_status_cmd);
-
-       __raw_writel(0, &npe->regs->exec_count);
-       __raw_writel(0, &npe->regs->action_points[0]);
-       __raw_writel(0, &npe->regs->action_points[1]);
-       __raw_writel(0, &npe->regs->action_points[2]);
-       __raw_writel(0, &npe->regs->action_points[3]);
-       __raw_writel(0, &npe->regs->watch_count);
-
-       val = ixp4xx_read_feature_bits();
-       /* reset the NPE */
-       ixp4xx_write_feature_bits(val &
-                                 ~(IXP4XX_FEATURE_RESET_NPEA << npe->id));
-       /* deassert reset */
-       ixp4xx_write_feature_bits(val |
-                                 (IXP4XX_FEATURE_RESET_NPEA << npe->id));
-       for (i = 0; i < MAX_RETRIES; i++) {
-               if (ixp4xx_read_feature_bits() &
-                   (IXP4XX_FEATURE_RESET_NPEA << npe->id))
-                       break;  /* NPE is back alive */
-               udelay(1);
-       }
-       if (i == MAX_RETRIES)
-               return -ETIMEDOUT;
-
-       npe_stop(npe);
-
-       /* restore NPE configuration bus Control Register - parity settings */
-       __raw_writel(ctl, &npe->regs->messaging_control);
-       return 0;
-}
-
-
-int npe_send_message(struct npe *npe, const void *msg, const char *what)
-{
-       const u32 *send = msg;
-       int cycles = 0;
-
-       debug_msg(npe, "Trying to send message %s [%08X:%08X]\n",
-                 what, send[0], send[1]);
-
-       if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE) {
-               debug_msg(npe, "NPE input FIFO not empty\n");
-               return -EIO;
-       }
-
-       __raw_writel(send[0], &npe->regs->in_out_fifo);
-
-       if (!(__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNF)) {
-               debug_msg(npe, "NPE input FIFO full\n");
-               return -EIO;
-       }
-
-       __raw_writel(send[1], &npe->regs->in_out_fifo);
-
-       while ((cycles < MAX_RETRIES) &&
-              (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)) {
-               udelay(1);
-               cycles++;
-       }
-
-       if (cycles == MAX_RETRIES) {
-               debug_msg(npe, "Timeout sending message\n");
-               return -ETIMEDOUT;
-       }
-
-#if DEBUG_MSG > 1
-       debug_msg(npe, "Sending a message took %i cycles\n", cycles);
-#endif
-       return 0;
-}
-
-int npe_recv_message(struct npe *npe, void *msg, const char *what)
-{
-       u32 *recv = msg;
-       int cycles = 0, cnt = 0;
-
-       debug_msg(npe, "Trying to receive message %s\n", what);
-
-       while (cycles < MAX_RETRIES) {
-               if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE) {
-                       recv[cnt++] = __raw_readl(&npe->regs->in_out_fifo);
-                       if (cnt == 2)
-                               break;
-               } else {
-                       udelay(1);
-                       cycles++;
-               }
-       }
-
-       switch(cnt) {
-       case 1:
-               debug_msg(npe, "Received [%08X]\n", recv[0]);
-               break;
-       case 2:
-               debug_msg(npe, "Received [%08X:%08X]\n", recv[0], recv[1]);
-               break;
-       }
-
-       if (cycles == MAX_RETRIES) {
-               debug_msg(npe, "Timeout waiting for message\n");
-               return -ETIMEDOUT;
-       }
-
-#if DEBUG_MSG > 1
-       debug_msg(npe, "Receiving a message took %i cycles\n", cycles);
-#endif
-       return 0;
-}
-
-int npe_send_recv_message(struct npe *npe, void *msg, const char *what)
-{
-       int result;
-       u32 *send = msg, recv[2];
-
-       if ((result = npe_send_message(npe, msg, what)) != 0)
-               return result;
-       if ((result = npe_recv_message(npe, recv, what)) != 0)
-               return result;
-
-       if ((recv[0] != send[0]) || (recv[1] != send[1])) {
-               debug_msg(npe, "Message %s: unexpected message received\n",
-                         what);
-               return -EIO;
-       }
-       return 0;
-}
-
-
-int npe_load_firmware(struct npe *npe, const char *name, struct device *dev)
-{
-       const struct firmware *fw_entry;
-
-       struct dl_block {
-               u32 type;
-               u32 offset;
-       } *blk;
-
-       struct dl_image {
-               u32 magic;
-               u32 id;
-               u32 size;
-               union {
-                       u32 data[0];
-                       struct dl_block blocks[0];
-               };
-       } *image;
-
-       struct dl_codeblock {
-               u32 npe_addr;
-               u32 size;
-               u32 data[0];
-       } *cb;
-
-       int i, j, err, data_size, instr_size, blocks, table_end;
-       u32 cmd;
-
-       if ((err = request_firmware(&fw_entry, name, dev)) != 0)
-               return err;
-
-       err = -EINVAL;
-       if (fw_entry->size < sizeof(struct dl_image)) {
-               print_npe(KERN_ERR, npe, "incomplete firmware file\n");
-               goto err;
-       }
-       image = (struct dl_image*)fw_entry->data;
-
-#if DEBUG_FW
-       print_npe(KERN_DEBUG, npe, "firmware: %08X %08X %08X (0x%X bytes)\n",
-                 image->magic, image->id, image->size, image->size * 4);
-#endif
-
-       if (image->magic == swab32(FW_MAGIC)) { /* swapped file */
-               image->id = swab32(image->id);
-               image->size = swab32(image->size);
-       } else if (image->magic != FW_MAGIC) {
-               print_npe(KERN_ERR, npe, "bad firmware file magic: 0x%X\n",
-                         image->magic);
-               goto err;
-       }
-       if ((image->size * 4 + sizeof(struct dl_image)) != fw_entry->size) {
-               print_npe(KERN_ERR, npe,
-                         "inconsistent size of firmware file\n");
-               goto err;
-       }
-       if (((image->id >> 24) & 0xF /* NPE ID */) != npe->id) {
-               print_npe(KERN_ERR, npe, "firmware file NPE ID mismatch\n");
-               goto err;
-       }
-       if (image->magic == swab32(FW_MAGIC))
-               for (i = 0; i < image->size; i++)
-                       image->data[i] = swab32(image->data[i]);
-
-       if (cpu_is_ixp42x() && ((image->id >> 28) & 0xF /* device ID */)) {
-               print_npe(KERN_INFO, npe, "IXP43x/IXP46x firmware ignored on "
-                         "IXP42x\n");
-               goto err;
-       }
-
-       if (npe_running(npe)) {
-               print_npe(KERN_INFO, npe, "unable to load firmware, NPE is "
-                         "already running\n");
-               err = -EBUSY;
-               goto err;
-       }
-#if 0
-       npe_stop(npe);
-       npe_reset(npe);
-#endif
-
-       print_npe(KERN_INFO, npe, "firmware functionality 0x%X, "
-                 "revision 0x%X:%X\n", (image->id >> 16) & 0xFF,
-                 (image->id >> 8) & 0xFF, image->id & 0xFF);
-
-       if (cpu_is_ixp42x()) {
-               if (!npe->id)
-                       instr_size = NPE_A_42X_INSTR_SIZE;
-               else
-                       instr_size = NPE_B_AND_C_42X_INSTR_SIZE;
-               data_size = NPE_42X_DATA_SIZE;
-       } else {
-               instr_size = NPE_46X_INSTR_SIZE;
-               data_size = NPE_46X_DATA_SIZE;
-       }
-
-       for (blocks = 0; blocks * sizeof(struct dl_block) / 4 < image->size;
-            blocks++)
-               if (image->blocks[blocks].type == FW_BLOCK_TYPE_EOF)
-                       break;
-       if (blocks * sizeof(struct dl_block) / 4 >= image->size) {
-               print_npe(KERN_INFO, npe, "firmware EOF block marker not "
-                         "found\n");
-               goto err;
-       }
-
-#if DEBUG_FW
-       print_npe(KERN_DEBUG, npe, "%i firmware blocks found\n", blocks);
-#endif
-
-       table_end = blocks * sizeof(struct dl_block) / 4 + 1 /* EOF marker */;
-       for (i = 0, blk = image->blocks; i < blocks; i++, blk++) {
-               if (blk->offset > image->size - sizeof(struct dl_codeblock) / 4
-                   || blk->offset < table_end) {
-                       print_npe(KERN_INFO, npe, "invalid offset 0x%X of "
-                                 "firmware block #%i\n", blk->offset, i);
-                       goto err;
-               }
-
-               cb = (struct dl_codeblock*)&image->data[blk->offset];
-               if (blk->type == FW_BLOCK_TYPE_INSTR) {
-                       if (cb->npe_addr + cb->size > instr_size)
-                               goto too_big;
-                       cmd = CMD_WR_INS_MEM;
-               } else if (blk->type == FW_BLOCK_TYPE_DATA) {
-                       if (cb->npe_addr + cb->size > data_size)
-                               goto too_big;
-                       cmd = CMD_WR_DATA_MEM;
-               } else {
-                       print_npe(KERN_INFO, npe, "invalid firmware block #%i "
-                                 "type 0x%X\n", i, blk->type);
-                       goto err;
-               }
-               if (blk->offset + sizeof(*cb) / 4 + cb->size > image->size) {
-                       print_npe(KERN_INFO, npe, "firmware block #%i doesn't "
-                                 "fit in firmware image: type %c, start 0x%X,"
-                                 " length 0x%X\n", i,
-                                 blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
-                                 cb->npe_addr, cb->size);
-                       goto err;
-               }
-
-               for (j = 0; j < cb->size; j++)
-                       npe_cmd_write(npe, cb->npe_addr + j, cmd, cb->data[j]);
-       }
-
-       npe_start(npe);
-       if (!npe_running(npe))
-               print_npe(KERN_ERR, npe, "unable to start\n");
-       release_firmware(fw_entry);
-       return 0;
-
-too_big:
-       print_npe(KERN_INFO, npe, "firmware block #%i doesn't fit in NPE "
-                 "memory: type %c, start 0x%X, length 0x%X\n", i,
-                 blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
-                 cb->npe_addr, cb->size);
-err:
-       release_firmware(fw_entry);
-       return err;
-}
-
-
-struct npe *npe_request(unsigned id)
-{
-       if (id < NPE_COUNT)
-               if (npe_tab[id].valid)
-                       if (try_module_get(THIS_MODULE))
-                               return &npe_tab[id];
-       return NULL;
-}
-
-void npe_release(struct npe *npe)
-{
-       module_put(THIS_MODULE);
-}
-
-
-static int __init npe_init_module(void)
-{
-
-       int i, found = 0;
-
-       for (i = 0; i < NPE_COUNT; i++) {
-               struct npe *npe = &npe_tab[i];
-               if (!(ixp4xx_read_feature_bits() &
-                     (IXP4XX_FEATURE_RESET_NPEA << i)))
-                       continue; /* NPE already disabled or not present */
-               if (!(npe->mem_res = request_mem_region(npe->regs_phys,
-                                                       REGS_SIZE,
-                                                       npe_name(npe)))) {
-                       print_npe(KERN_ERR, npe,
-                                 "failed to request memory region\n");
-                       continue;
-               }
-
-               if (npe_reset(npe))
-                       continue;
-               npe->valid = 1;
-               found++;
-       }
-
-       if (!found)
-               return -ENODEV;
-       return 0;
-}
-
-static void __exit npe_cleanup_module(void)
-{
-       int i;
-
-       for (i = 0; i < NPE_COUNT; i++)
-               if (npe_tab[i].mem_res) {
-                       npe_reset(&npe_tab[i]);
-                       release_resource(npe_tab[i].mem_res);
-               }
-}
-
-module_init(npe_init_module);
-module_exit(npe_cleanup_module);
-
-MODULE_AUTHOR("Krzysztof Halasa");
-MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE(NPE_A_FIRMWARE);
-MODULE_FIRMWARE(NPE_B_FIRMWARE);
-MODULE_FIRMWARE(NPE_C_FIRMWARE);
-
-EXPORT_SYMBOL(npe_names);
-EXPORT_SYMBOL(npe_running);
-EXPORT_SYMBOL(npe_request);
-EXPORT_SYMBOL(npe_release);
-EXPORT_SYMBOL(npe_load_firmware);
-EXPORT_SYMBOL(npe_send_message);
-EXPORT_SYMBOL(npe_recv_message);
-EXPORT_SYMBOL(npe_send_recv_message);
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
deleted file mode 100644 (file)
index 9d1b6b7..0000000
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Intel IXP4xx Queue Manager driver for Linux
- *
- * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- */
-
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <mach/qmgr.h>
-
-static struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
-static struct resource *mem_res;
-static spinlock_t qmgr_lock;
-static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
-static void (*irq_handlers[QUEUES])(void *pdev);
-static void *irq_pdevs[QUEUES];
-
-#if DEBUG_QMGR
-char qmgr_queue_descs[QUEUES][32];
-#endif
-
-void qmgr_set_irq(unsigned int queue, int src,
-                 void (*handler)(void *pdev), void *pdev)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&qmgr_lock, flags);
-       if (queue < HALF_QUEUES) {
-               u32 __iomem *reg;
-               int bit;
-               BUG_ON(src > QUEUE_IRQ_SRC_NOT_FULL);
-               reg = &qmgr_regs->irqsrc[queue >> 3]; /* 8 queues per u32 */
-               bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
-               __raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit),
-                            reg);
-       } else
-               /* IRQ source for queues 32-63 is fixed */
-               BUG_ON(src != QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY);
-
-       irq_handlers[queue] = handler;
-       irq_pdevs[queue] = pdev;
-       spin_unlock_irqrestore(&qmgr_lock, flags);
-}
-
-
-static irqreturn_t qmgr_irq1_a0(int irq, void *pdev)
-{
-       int i, ret = 0;
-       u32 en_bitmap, src, stat;
-
-       /* ACK - it may clear any bits so don't rely on it */
-       __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[0]);
-
-       en_bitmap = qmgr_regs->irqen[0];
-       while (en_bitmap) {
-               i = __fls(en_bitmap); /* number of the last "low" queue */
-               en_bitmap &= ~BIT(i);
-               src = qmgr_regs->irqsrc[i >> 3];
-               stat = qmgr_regs->stat1[i >> 3];
-               if (src & 4) /* the IRQ condition is inverted */
-                       stat = ~stat;
-               if (stat & BIT(src & 3)) {
-                       irq_handlers[i](irq_pdevs[i]);
-                       ret = IRQ_HANDLED;
-               }
-       }
-       return ret;
-}
-
-
-static irqreturn_t qmgr_irq2_a0(int irq, void *pdev)
-{
-       int i, ret = 0;
-       u32 req_bitmap;
-
-       /* ACK - it may clear any bits so don't rely on it */
-       __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[1]);
-
-       req_bitmap = qmgr_regs->irqen[1] & qmgr_regs->statne_h;
-       while (req_bitmap) {
-               i = __fls(req_bitmap); /* number of the last "high" queue */
-               req_bitmap &= ~BIT(i);
-               irq_handlers[HALF_QUEUES + i](irq_pdevs[HALF_QUEUES + i]);
-               ret = IRQ_HANDLED;
-       }
-       return ret;
-}
-
-
-static irqreturn_t qmgr_irq(int irq, void *pdev)
-{
-       int i, half = (irq == IRQ_IXP4XX_QM1 ? 0 : 1);
-       u32 req_bitmap = __raw_readl(&qmgr_regs->irqstat[half]);
-
-       if (!req_bitmap)
-               return 0;
-       __raw_writel(req_bitmap, &qmgr_regs->irqstat[half]); /* ACK */
-
-       while (req_bitmap) {
-               i = __fls(req_bitmap); /* number of the last queue */
-               req_bitmap &= ~BIT(i);
-               i += half * HALF_QUEUES;
-               irq_handlers[i](irq_pdevs[i]);
-       }
-       return IRQ_HANDLED;
-}
-
-
-void qmgr_enable_irq(unsigned int queue)
-{
-       unsigned long flags;
-       int half = queue / 32;
-       u32 mask = 1 << (queue & (HALF_QUEUES - 1));
-
-       spin_lock_irqsave(&qmgr_lock, flags);
-       __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) | mask,
-                    &qmgr_regs->irqen[half]);
-       spin_unlock_irqrestore(&qmgr_lock, flags);
-}
-
-void qmgr_disable_irq(unsigned int queue)
-{
-       unsigned long flags;
-       int half = queue / 32;
-       u32 mask = 1 << (queue & (HALF_QUEUES - 1));
-
-       spin_lock_irqsave(&qmgr_lock, flags);
-       __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) & ~mask,
-                    &qmgr_regs->irqen[half]);
-       __raw_writel(mask, &qmgr_regs->irqstat[half]); /* clear */
-       spin_unlock_irqrestore(&qmgr_lock, flags);
-}
-
-static inline void shift_mask(u32 *mask)
-{
-       mask[3] = mask[3] << 1 | mask[2] >> 31;
-       mask[2] = mask[2] << 1 | mask[1] >> 31;
-       mask[1] = mask[1] << 1 | mask[0] >> 31;
-       mask[0] <<= 1;
-}
-
-#if DEBUG_QMGR
-int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
-                      unsigned int nearly_empty_watermark,
-                      unsigned int nearly_full_watermark,
-                      const char *desc_format, const char* name)
-#else
-int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
-                        unsigned int nearly_empty_watermark,
-                        unsigned int nearly_full_watermark)
-#endif
-{
-       u32 cfg, addr = 0, mask[4]; /* in 16-dwords */
-       int err;
-
-       BUG_ON(queue >= QUEUES);
-
-       if ((nearly_empty_watermark | nearly_full_watermark) & ~7)
-               return -EINVAL;
-
-       switch (len) {
-       case  16:
-               cfg = 0 << 24;
-               mask[0] = 0x1;
-               break;
-       case  32:
-               cfg = 1 << 24;
-               mask[0] = 0x3;
-               break;
-       case  64:
-               cfg = 2 << 24;
-               mask[0] = 0xF;
-               break;
-       case 128:
-               cfg = 3 << 24;
-               mask[0] = 0xFF;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       cfg |= nearly_empty_watermark << 26;
-       cfg |= nearly_full_watermark << 29;
-       len /= 16;              /* in 16-dwords: 1, 2, 4 or 8 */
-       mask[1] = mask[2] = mask[3] = 0;
-
-       if (!try_module_get(THIS_MODULE))
-               return -ENODEV;
-
-       spin_lock_irq(&qmgr_lock);
-       if (__raw_readl(&qmgr_regs->sram[queue])) {
-               err = -EBUSY;
-               goto err;
-       }
-
-       while (1) {
-               if (!(used_sram_bitmap[0] & mask[0]) &&
-                   !(used_sram_bitmap[1] & mask[1]) &&
-                   !(used_sram_bitmap[2] & mask[2]) &&
-                   !(used_sram_bitmap[3] & mask[3]))
-                       break; /* found free space */
-
-               addr++;
-               shift_mask(mask);
-               if (addr + len > ARRAY_SIZE(qmgr_regs->sram)) {
-                       printk(KERN_ERR "qmgr: no free SRAM space for"
-                              " queue %i\n", queue);
-                       err = -ENOMEM;
-                       goto err;
-               }
-       }
-
-       used_sram_bitmap[0] |= mask[0];
-       used_sram_bitmap[1] |= mask[1];
-       used_sram_bitmap[2] |= mask[2];
-       used_sram_bitmap[3] |= mask[3];
-       __raw_writel(cfg | (addr << 14), &qmgr_regs->sram[queue]);
-#if DEBUG_QMGR
-       snprintf(qmgr_queue_descs[queue], sizeof(qmgr_queue_descs[0]),
-                desc_format, name);
-       printk(KERN_DEBUG "qmgr: requested queue %s(%i) addr = 0x%02X\n",
-              qmgr_queue_descs[queue], queue, addr);
-#endif
-       spin_unlock_irq(&qmgr_lock);
-       return 0;
-
-err:
-       spin_unlock_irq(&qmgr_lock);
-       module_put(THIS_MODULE);
-       return err;
-}
-
-void qmgr_release_queue(unsigned int queue)
-{
-       u32 cfg, addr, mask[4];
-
-       BUG_ON(queue >= QUEUES); /* not in valid range */
-
-       spin_lock_irq(&qmgr_lock);
-       cfg = __raw_readl(&qmgr_regs->sram[queue]);
-       addr = (cfg >> 14) & 0xFF;
-
-       BUG_ON(!addr);          /* not requested */
-
-       switch ((cfg >> 24) & 3) {
-       case 0: mask[0] = 0x1; break;
-       case 1: mask[0] = 0x3; break;
-       case 2: mask[0] = 0xF; break;
-       case 3: mask[0] = 0xFF; break;
-       }
-
-       mask[1] = mask[2] = mask[3] = 0;
-
-       while (addr--)
-               shift_mask(mask);
-
-#if DEBUG_QMGR
-       printk(KERN_DEBUG "qmgr: releasing queue %s(%i)\n",
-              qmgr_queue_descs[queue], queue);
-       qmgr_queue_descs[queue][0] = '\x0';
-#endif
-
-       while ((addr = qmgr_get_entry(queue)))
-               printk(KERN_ERR "qmgr: released queue %i not empty: 0x%08X\n",
-                      queue, addr);
-
-       __raw_writel(0, &qmgr_regs->sram[queue]);
-
-       used_sram_bitmap[0] &= ~mask[0];
-       used_sram_bitmap[1] &= ~mask[1];
-       used_sram_bitmap[2] &= ~mask[2];
-       used_sram_bitmap[3] &= ~mask[3];
-       irq_handlers[queue] = NULL; /* catch IRQ bugs */
-       spin_unlock_irq(&qmgr_lock);
-
-       module_put(THIS_MODULE);
-}
-
-static int qmgr_init(void)
-{
-       int i, err;
-       irq_handler_t handler1, handler2;
-
-       mem_res = request_mem_region(IXP4XX_QMGR_BASE_PHYS,
-                                    IXP4XX_QMGR_REGION_SIZE,
-                                    "IXP4xx Queue Manager");
-       if (mem_res == NULL)
-               return -EBUSY;
-
-       /* reset qmgr registers */
-       for (i = 0; i < 4; i++) {
-               __raw_writel(0x33333333, &qmgr_regs->stat1[i]);
-               __raw_writel(0, &qmgr_regs->irqsrc[i]);
-       }
-       for (i = 0; i < 2; i++) {
-               __raw_writel(0, &qmgr_regs->stat2[i]);
-               __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[i]); /* clear */
-               __raw_writel(0, &qmgr_regs->irqen[i]);
-       }
-
-       __raw_writel(0xFFFFFFFF, &qmgr_regs->statne_h);
-       __raw_writel(0, &qmgr_regs->statf_h);
-
-       for (i = 0; i < QUEUES; i++)
-               __raw_writel(0, &qmgr_regs->sram[i]);
-
-       if (cpu_is_ixp42x_rev_a0()) {
-               handler1 = qmgr_irq1_a0;
-               handler2 = qmgr_irq2_a0;
-       } else
-               handler1 = handler2 = qmgr_irq;
-
-       err = request_irq(IRQ_IXP4XX_QM1, handler1, 0, "IXP4xx Queue Manager",
-                         NULL);
-       if (err) {
-               printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n",
-                      IRQ_IXP4XX_QM1, err);
-               goto error_irq;
-       }
-
-       err = request_irq(IRQ_IXP4XX_QM2, handler2, 0, "IXP4xx Queue Manager",
-                         NULL);
-       if (err) {
-               printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n",
-                      IRQ_IXP4XX_QM2, err);
-               goto error_irq2;
-       }
-
-       used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */
-       spin_lock_init(&qmgr_lock);
-
-       printk(KERN_INFO "IXP4xx Queue Manager initialized.\n");
-       return 0;
-
-error_irq2:
-       free_irq(IRQ_IXP4XX_QM1, NULL);
-error_irq:
-       release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
-       return err;
-}
-
-static void qmgr_remove(void)
-{
-       free_irq(IRQ_IXP4XX_QM1, NULL);
-       free_irq(IRQ_IXP4XX_QM2, NULL);
-       synchronize_irq(IRQ_IXP4XX_QM1);
-       synchronize_irq(IRQ_IXP4XX_QM2);
-       release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
-}
-
-module_init(qmgr_init);
-module_exit(qmgr_remove);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Krzysztof Halasa");
-
-EXPORT_SYMBOL(qmgr_set_irq);
-EXPORT_SYMBOL(qmgr_enable_irq);
-EXPORT_SYMBOL(qmgr_disable_irq);
-#if DEBUG_QMGR
-EXPORT_SYMBOL(qmgr_queue_descs);
-EXPORT_SYMBOL(qmgr_request_queue);
-#else
-EXPORT_SYMBOL(__qmgr_request_queue);
-#endif
-EXPORT_SYMBOL(qmgr_release_queue);
index 8f0eba0..925ef80 100644 (file)
@@ -21,6 +21,8 @@
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 #define MAX_DEV                3
 #define IRQ_LINES      3
 
index 4138d6a..c142cfa 100644 (file)
@@ -34,6 +34,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 #define NAS100D_SDA_PIN                5
 #define NAS100D_SCL_PIN                6
 
@@ -279,9 +281,6 @@ static void __init nas100d_init(void)
 
        ixp4xx_sys_init();
 
-       /* gpio 14 and 15 are _not_ clocks */
-       *IXP4XX_GPIO_GPCLKR = 0;
-
        nas100d_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
        nas100d_flash_resource.end =
                IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
index 032defe..d69ee40 100644 (file)
@@ -21,6 +21,8 @@
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 #define MAX_DEV                3
 #define IRQ_LINES      3
 
index 341b263..ee1877f 100644 (file)
@@ -32,6 +32,8 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/time.h>
 
+#include "irqs.h"
+
 #define NSLU2_SDA_PIN          7
 #define NSLU2_SCL_PIN          6
 
@@ -125,10 +127,18 @@ static struct platform_device nslu2_i2c_gpio = {
        },
 };
 
+static struct resource nslu2_beeper_resources[] = {
+       {
+               .start  = IRQ_IXP4XX_TIMER2,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
 static struct platform_device nslu2_beeper = {
        .name                   = "ixp4xx-beeper",
        .id                     = NSLU2_GPIO_BUZZ,
-       .num_resources          = 0,
+       .resource               = nslu2_beeper_resources,
+       .num_resources          = ARRAY_SIZE(nslu2_beeper_resources),
 };
 
 static struct resource nslu2_uart_resources[] = {
index c92e5b8..cf83f7e 100644 (file)
@@ -27,6 +27,8 @@
 
 #include <asm/mach/pci.h>
 
+#include "irqs.h"
+
 void __init wg302v2_pci_preinit(void)
 {
        irq_set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
index 90b3c60..8711e29 100644 (file)
@@ -29,6 +29,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 static struct flash_platform_data wg302v2_flash_data = {
        .map_name       = "cfi_probe",
        .width          = 2,
index 959c748..877629b 100644 (file)
@@ -14,7 +14,7 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 /*
  * Clocks are derived from MCLK, which is 25MHz
index b3be60a..66701bf 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Platform support for LPC32xx SoC
  *
@@ -5,44 +6,14 @@
  *
  * Copyright (C) 2012 Roland Stigge <stigge@antcom.de>
  * Copyright (C) 2010 NXP Semiconductors
- *
- * 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/init.h>
-#include <linux/platform_device.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
 #include <linux/amba/pl08x.h>
-#include <linux/amba/mmci.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/clk.h>
-#include <linux/mtd/lpc32xx_slc.h>
 #include <linux/mtd/lpc32xx_mlc.h>
+#include <linux/mtd/lpc32xx_slc.h>
+#include <linux/of_platform.h>
 
-#include <asm/setup.h>
-#include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-
-#include <mach/hardware.h>
-#include <mach/platform.h>
-#include <mach/board.h>
 #include "common.h"
 
 static struct pl08x_channel_data pl08x_slave_channels[] = {
@@ -90,8 +61,6 @@ static struct lpc32xx_mlc_platform_data lpc32xx_mlc_data = {
 };
 
 static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = {
-       OF_DEV_AUXDATA("arm,pl022", 0x20084000, "dev:ssp0", NULL),
-       OF_DEV_AUXDATA("arm,pl022", 0x2008C000, "dev:ssp1", NULL),
        OF_DEV_AUXDATA("arm,pl080", 0x31000000, "pl08xdmac", &pl08x_pd),
        OF_DEV_AUXDATA("nxp,lpc3220-slc", 0x20020000, "20020000.flash",
                       &lpc32xx_slc_data),
@@ -104,11 +73,6 @@ static void __init lpc3250_machine_init(void)
 {
        lpc32xx_serial_init();
 
-       /* Test clock needed for UDA1380 initial init */
-       __raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC |
-               LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN,
-               LPC32XX_CLKPWR_TEST_CLK_SEL);
-
        of_platform_default_populate(NULL, lpc32xx_auxdata_lookup, NULL);
 }
 
index b6a81ba..5a9c016 100644 (file)
@@ -15,6 +15,7 @@
  * GNU General Public License for more details.
  */
 #include <linux/init.h>
+#include <linux/io.h>
 #include <asm/mach/arch.h>
 #include <linux/of.h>
 #include <linux/clk-provider.h>
index f72e1e9..dd762d1 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/ata_platform.h>
index 5875a50..e7c8ac7 100644 (file)
@@ -36,7 +36,7 @@
 #ifndef __ASM_ARCH_OMAP_HARDWARE_H
 #define __ASM_ARCH_OMAP_HARDWARE_H
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #ifndef __ASSEMBLER__
 #include <asm/types.h>
 #include <mach/soc.h>
index 129455e..6316da3 100644 (file)
@@ -336,6 +336,15 @@ static inline void omap5_secondary_hyp_startup(void)
 }
 #endif
 
+#ifdef CONFIG_SOC_DRA7XX
+extern int dra7xx_pciess_reset(struct omap_hwmod *oh);
+#else
+static inline int dra7xx_pciess_reset(struct omap_hwmod *oh)
+{
+       return 0;
+}
+#endif
+
 void pdata_quirks_init(const struct of_device_id *);
 void omap_auxdata_legacy_init(struct device *dev);
 void omap_pcs_legacy_init(int irq, void (*rearm)(void));
index 37ff25e..1d8efc3 100644 (file)
@@ -53,15 +53,10 @@ int omap_i2c_reset(struct omap_hwmod *oh)
        u16 i2c_con;
        int c = 0;
 
-       if (oh->class->rev == OMAP_I2C_IP_VERSION_2) {
-               i2c_con = OMAP4_I2C_CON_OFFSET;
-       } else if (oh->class->rev == OMAP_I2C_IP_VERSION_1) {
+       if (soc_is_omap24xx() || soc_is_omap34xx() || soc_is_am35xx())
                i2c_con = OMAP2_I2C_CON_OFFSET;
-       } else {
-               WARN(1, "Cannot reset I2C block %s: unsupported revision\n",
-                    oh->name);
-               return -EINVAL;
-       }
+       else
+               i2c_con = OMAP4_I2C_CON_OFFSET;
 
        /* Disable I2C */
        v = omap_hwmod_read(oh, i2c_con);
index bb8e0bb..5e69c8c 100644 (file)
@@ -411,14 +411,9 @@ static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data)
 
 static void __init __maybe_unused omap_hwmod_init_postsetup(void)
 {
-       u8 postsetup_state;
+       u8 postsetup_state = _HWMOD_STATE_DEFAULT;
 
        /* Set the default postsetup state for all hwmods */
-#ifdef CONFIG_PM
-       postsetup_state = _HWMOD_STATE_IDLE;
-#else
-       postsetup_state = _HWMOD_STATE_ENABLED;
-#endif
        omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state);
 }
 
index 9145a6f..7f4e053 100644 (file)
@@ -7,7 +7,15 @@
 #define OMAP4_MMC_REG_OFFSET   0x100
 
 struct omap_hwmod;
+
+#ifdef CONFIG_SOC_OMAP2420
 int omap_msdi_reset(struct omap_hwmod *oh);
+#else
+static inline int omap_msdi_reset(struct omap_hwmod *oh)
+{
+       return 0;
+}
+#endif
 
 /* called from board-specific card detection service routine */
 extern void omap_mmc_notify_cover_event(struct device *dev, int slot,
index 17558be..7dcbe17 100644 (file)
@@ -436,13 +436,13 @@ static int irq_notifier(struct notifier_block *self, unsigned long cmd,   void *v)
 {
        switch (cmd) {
        case CPU_CLUSTER_PM_ENTER:
-               if (omap_type() == OMAP2_DEVICE_TYPE_GP)
+               if (omap_type() == OMAP2_DEVICE_TYPE_GP || soc_is_am43xx())
                        irq_save_context();
                else
                        irq_save_secure_context();
                break;
        case CPU_CLUSTER_PM_EXIT:
-               if (omap_type() == OMAP2_DEVICE_TYPE_GP)
+               if (omap_type() == OMAP2_DEVICE_TYPE_GP || soc_is_am43xx())
                        irq_restore_context();
                break;
        }
index baadddf..405ac24 100644 (file)
 #include "soc.h"
 #include "common.h"
 #include "clockdomain.h"
+#include "hdq1w.h"
+#include "mmc.h"
 #include "powerdomain.h"
 #include "cm2xxx.h"
 #include "cm3xxx.h"
 #include "prm33xx.h"
 #include "prminst44xx.h"
 #include "pm.h"
+#include "wd_timer.h"
 
 /* Name of the OMAP hwmod for the MPU */
 #define MPU_INITIATOR_NAME             "mpu"
@@ -204,6 +207,20 @@ struct clkctrl_provider {
 
 static LIST_HEAD(clkctrl_providers);
 
+/**
+ * struct omap_hwmod_reset - IP specific reset functions
+ * @match: string to match against the module name
+ * @len: number of characters to match
+ * @reset: IP specific reset function
+ *
+ * Used only in cases where struct omap_hwmod is dynamically allocated.
+ */
+struct omap_hwmod_reset {
+       const char *match;
+       int len;
+       int (*reset)(struct omap_hwmod *oh);
+};
+
 /**
  * struct omap_hwmod_soc_ops - fn ptrs for some SoC-specific operations
  * @enable_module: function to enable a module (via MODULEMODE)
@@ -235,6 +252,7 @@ static struct omap_hwmod_soc_ops soc_ops;
 
 /* omap_hwmod_list contains all registered struct omap_hwmods */
 static LIST_HEAD(omap_hwmod_list);
+static DEFINE_MUTEX(list_lock);
 
 /* mpu_oh: used to add/remove MPU initiator from sleepdep list */
 static struct omap_hwmod *mpu_oh;
@@ -2465,7 +2483,7 @@ static void _setup_iclk_autoidle(struct omap_hwmod *oh)
  */
 static int _setup_reset(struct omap_hwmod *oh)
 {
-       int r;
+       int r = 0;
 
        if (oh->_state != _HWMOD_STATE_INITIALIZED)
                return -EINVAL;
@@ -2624,7 +2642,7 @@ static int _setup(struct omap_hwmod *oh, void *data)
  * that the copy process would be relatively complex due to the large number
  * of substructures.
  */
-static int __init _register(struct omap_hwmod *oh)
+static int _register(struct omap_hwmod *oh)
 {
        if (!oh || !oh->name || !oh->class || !oh->class->name ||
            (oh->_state != _HWMOD_STATE_UNKNOWN))
@@ -2663,7 +2681,7 @@ static int __init _register(struct omap_hwmod *oh)
  * locking in this code.  Changes to this assumption will require
  * additional locking.  Returns 0.
  */
-static int __init _add_link(struct omap_hwmod_ocp_if *oi)
+static int _add_link(struct omap_hwmod_ocp_if *oi)
 {
        pr_debug("omap_hwmod: %s -> %s: adding link\n", oi->master->name,
                 oi->slave->name);
@@ -3241,9 +3259,10 @@ static int omap_hwmod_init_regbits(struct device *dev,
  * @sysc_offs: sysc register offset
  * @syss_offs: syss register offset
  */
-int omap_hwmod_init_reg_offs(struct device *dev,
-                            const struct ti_sysc_module_data *data,
-                            s32 *rev_offs, s32 *sysc_offs, s32 *syss_offs)
+static int omap_hwmod_init_reg_offs(struct device *dev,
+                                   const struct ti_sysc_module_data *data,
+                                   s32 *rev_offs, s32 *sysc_offs,
+                                   s32 *syss_offs)
 {
        *rev_offs = -ENODEV;
        *sysc_offs = 0;
@@ -3267,9 +3286,9 @@ int omap_hwmod_init_reg_offs(struct device *dev,
  * @data: module data
  * @sysc_flags: module configuration
  */
-int omap_hwmod_init_sysc_flags(struct device *dev,
-                              const struct ti_sysc_module_data *data,
-                              u32 *sysc_flags)
+static int omap_hwmod_init_sysc_flags(struct device *dev,
+                                     const struct ti_sysc_module_data *data,
+                                     u32 *sysc_flags)
 {
        *sysc_flags = 0;
 
@@ -3341,9 +3360,9 @@ int omap_hwmod_init_sysc_flags(struct device *dev,
  * @data: module data
  * @idlemodes: module supported idle modes
  */
-int omap_hwmod_init_idlemodes(struct device *dev,
-                             const struct ti_sysc_module_data *data,
-                             u32 *idlemodes)
+static int omap_hwmod_init_idlemodes(struct device *dev,
+                                    const struct ti_sysc_module_data *data,
+                                    u32 *idlemodes)
 {
        *idlemodes = 0;
 
@@ -3434,14 +3453,18 @@ static int omap_hwmod_check_module(struct device *dev,
  *
  * Note that the allocations here cannot use devm as ti-sysc can rebind.
  */
-int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
-                              const struct ti_sysc_module_data *data,
-                              struct sysc_regbits *sysc_fields,
-                              s32 rev_offs, s32 sysc_offs, s32 syss_offs,
-                              u32 sysc_flags, u32 idlemodes)
+static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
+                                     const struct ti_sysc_module_data *data,
+                                     struct sysc_regbits *sysc_fields,
+                                     s32 rev_offs, s32 sysc_offs,
+                                     s32 syss_offs, u32 sysc_flags,
+                                     u32 idlemodes)
 {
        struct omap_hwmod_class_sysconfig *sysc;
-       struct omap_hwmod_class *class;
+       struct omap_hwmod_class *class = NULL;
+       struct omap_hwmod_ocp_if *oi = NULL;
+       struct clockdomain *clkdm = NULL;
+       struct clk *clk = NULL;
        void __iomem *regs = NULL;
        unsigned long flags;
 
@@ -3465,26 +3488,128 @@ int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
        }
 
        /*
-        * We need new oh->class as the other devices in the same class
+        * We may need a new oh->class as the other devices in the same class
         * may not yet have ioremapped their registers.
         */
-       class = kmemdup(oh->class, sizeof(*oh->class), GFP_KERNEL);
-       if (!class)
-               return -ENOMEM;
+       if (oh->class->name && strcmp(oh->class->name, data->name)) {
+               class = kmemdup(oh->class, sizeof(*oh->class), GFP_KERNEL);
+               if (!class)
+                       return -ENOMEM;
+       }
 
-       class->sysc = sysc;
+       if (list_empty(&oh->slave_ports)) {
+               oi = kcalloc(1, sizeof(*oi), GFP_KERNEL);
+               if (!oi)
+                       return -ENOMEM;
+
+               /*
+                * Note that we assume interconnect interface clocks will be
+                * managed by the interconnect driver for OCPIF_SWSUP_IDLE case
+                * on omap24xx and omap3.
+                */
+               oi->slave = oh;
+               oi->user = OCP_USER_MPU | OCP_USER_SDMA;
+       }
+
+       if (!oh->_clk) {
+               struct clk_hw_omap *hwclk;
+
+               clk = of_clk_get_by_name(dev->of_node, "fck");
+               if (!IS_ERR(clk))
+                       clk_prepare(clk);
+               else
+                       clk = NULL;
+
+               /*
+                * Populate clockdomain based on dts clock. It is needed for
+                * clkdm_deny_idle() and clkdm_allow_idle() until we have have
+                * interconnect driver and reset driver capable of blocking
+                * clockdomain idle during reset, enable and idle.
+                */
+               if (clk) {
+                       hwclk = to_clk_hw_omap(__clk_get_hw(clk));
+                       if (hwclk && hwclk->clkdm_name)
+                               clkdm = clkdm_lookup(hwclk->clkdm_name);
+               }
+
+               /*
+                * Note that we assume interconnect driver manages the clocks
+                * and do not need to populate oh->_clk for dynamically
+                * allocated modules.
+                */
+               clk_unprepare(clk);
+               clk_put(clk);
+       }
 
        spin_lock_irqsave(&oh->_lock, flags);
        if (regs)
                oh->_mpu_rt_va = regs;
-       oh->class = class;
+       if (class)
+               oh->class = class;
+       oh->class->sysc = sysc;
+       if (oi)
+               _add_link(oi);
+       if (clkdm)
+               oh->clkdm = clkdm;
        oh->_state = _HWMOD_STATE_INITIALIZED;
+       oh->_postsetup_state = _HWMOD_STATE_DEFAULT;
        _setup(oh, NULL);
        spin_unlock_irqrestore(&oh->_lock, flags);
 
        return 0;
 }
 
+static const struct omap_hwmod_reset omap24xx_reset_quirks[] = {
+       { .match = "msdi", .len = 4, .reset = omap_msdi_reset, },
+};
+
+static const struct omap_hwmod_reset dra7_reset_quirks[] = {
+       { .match = "pcie", .len = 4, .reset = dra7xx_pciess_reset, },
+};
+
+static const struct omap_hwmod_reset omap_reset_quirks[] = {
+       { .match = "dss", .len = 3, .reset = omap_dss_reset, },
+       { .match = "hdq1w", .len = 5, .reset = omap_hdq1w_reset, },
+       { .match = "i2c", .len = 3, .reset = omap_i2c_reset, },
+       { .match = "wd_timer", .len = 8, .reset = omap2_wd_timer_reset, },
+};
+
+static void
+omap_hwmod_init_reset_quirk(struct device *dev, struct omap_hwmod *oh,
+                           const struct ti_sysc_module_data *data,
+                           const struct omap_hwmod_reset *quirks,
+                           int quirks_sz)
+{
+       const struct omap_hwmod_reset *quirk;
+       int i;
+
+       for (i = 0; i < quirks_sz; i++) {
+               quirk = &quirks[i];
+               if (!strncmp(data->name, quirk->match, quirk->len)) {
+                       oh->class->reset = quirk->reset;
+
+                       return;
+               }
+       }
+}
+
+static void
+omap_hwmod_init_reset_quirks(struct device *dev, struct omap_hwmod *oh,
+                            const struct ti_sysc_module_data *data)
+{
+       if (soc_is_omap24xx())
+               omap_hwmod_init_reset_quirk(dev, oh, data,
+                                           omap24xx_reset_quirks,
+                                           ARRAY_SIZE(omap24xx_reset_quirks));
+
+       if (soc_is_dra7xx())
+               omap_hwmod_init_reset_quirk(dev, oh, data, dra7_reset_quirks,
+                                           ARRAY_SIZE(dra7_reset_quirks));
+
+       omap_hwmod_init_reset_quirk(dev, oh, data, omap_reset_quirks,
+                                   ARRAY_SIZE(omap_reset_quirks));
+}
+
 /**
  * omap_hwmod_init_module - initialize new module
  * @dev: struct device
@@ -3505,8 +3630,31 @@ int omap_hwmod_init_module(struct device *dev,
                return -EINVAL;
 
        oh = _lookup(data->name);
-       if (!oh)
-               return -ENODEV;
+       if (!oh) {
+               oh = kzalloc(sizeof(*oh), GFP_KERNEL);
+               if (!oh)
+                       return -ENOMEM;
+
+               oh->name = data->name;
+               oh->_state = _HWMOD_STATE_UNKNOWN;
+               lockdep_register_key(&oh->hwmod_key);
+
+               /* Unused, can be handled by PRM driver handling resets */
+               oh->prcm.omap4.flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT;
+
+               oh->class = kzalloc(sizeof(*oh->class), GFP_KERNEL);
+               if (!oh->class) {
+                       kfree(oh);
+                       return -ENOMEM;
+               }
+
+               omap_hwmod_init_reset_quirks(dev, oh, data);
+
+               oh->class->name = data->name;
+               mutex_lock(&list_lock);
+               error = _register(oh);
+               mutex_unlock(&list_lock);
+       }
 
        cookie->data = oh;
 
@@ -3527,10 +3675,20 @@ int omap_hwmod_init_module(struct device *dev,
        if (error)
                return error;
 
+       if (data->cfg->quirks & SYSC_QUIRK_NO_IDLE)
+               oh->flags |= HWMOD_NO_IDLE;
        if (data->cfg->quirks & SYSC_QUIRK_NO_IDLE_ON_INIT)
                oh->flags |= HWMOD_INIT_NO_IDLE;
        if (data->cfg->quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
                oh->flags |= HWMOD_INIT_NO_RESET;
+       if (data->cfg->quirks & SYSC_QUIRK_USE_CLOCKACT)
+               oh->flags |= HWMOD_SET_DEFAULT_CLOCKACT;
+       if (data->cfg->quirks & SYSC_QUIRK_SWSUP_SIDLE)
+               oh->flags |= HWMOD_SWSUP_SIDLE;
+       if (data->cfg->quirks & SYSC_QUIRK_SWSUP_SIDLE_ACT)
+               oh->flags |= HWMOD_SWSUP_SIDLE_ACT;
+       if (data->cfg->quirks & SYSC_QUIRK_SWSUP_MSTANDBY)
+               oh->flags |= HWMOD_SWSUP_MSTANDBY;
 
        error = omap_hwmod_check_module(dev, oh, data, sysc_fields,
                                        rev_offs, sysc_offs, syss_offs,
index b70cdc2..fca9e07 100644 (file)
@@ -493,11 +493,16 @@ struct omap_hwmod_omap4_prcm {
 #define _HWMOD_STATE_IDLE                      5
 #define _HWMOD_STATE_DISABLED                  6
 
+#ifdef CONFIG_PM
+#define _HWMOD_STATE_DEFAULT                   _HWMOD_STATE_IDLE
+#else
+#define _HWMOD_STATE_DEFAULT                   _HWMOD_STATE_ENABLED
+#endif
+
 /**
  * struct omap_hwmod_class - the type of an IP block
  * @name: name of the hwmod_class
  * @sysc: device SYSCONFIG/SYSSTATUS register data
- * @rev: revision of the IP class
  * @pre_shutdown: ptr to fn to be executed immediately prior to device shutdown
  * @reset: ptr to fn to be executed in place of the standard hwmod reset fn
  * @enable_preprogram:  ptr to fn to be executed during device enable
@@ -523,7 +528,6 @@ struct omap_hwmod_omap4_prcm {
 struct omap_hwmod_class {
        const char                              *name;
        struct omap_hwmod_class_sysconfig       *sysc;
-       u32                                     rev;
        int                                     (*pre_shutdown)(struct omap_hwmod *oh);
        int                                     (*reset)(struct omap_hwmod *oh);
        int                                     (*enable_preprogram)(struct omap_hwmod *oh);
index d684fac..8122c8d 100644 (file)
@@ -91,7 +91,6 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
 static struct omap_hwmod_class i2c_class = {
        .name           = "i2c",
        .sysc           = &i2c_sysc,
-       .rev            = OMAP_I2C_IP_VERSION_1,
        .reset          = &omap_i2c_reset,
 };
 
index abef9f6..f27cb60 100644 (file)
@@ -68,7 +68,6 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
 static struct omap_hwmod_class i2c_class = {
        .name           = "i2c",
        .sysc           = &i2c_sysc,
-       .rev            = OMAP_I2C_IP_VERSION_1,
        .reset          = &omap_i2c_reset,
 };
 
index 9b30b6b..e19f620 100644 (file)
@@ -11,7 +11,7 @@
  * XXX handle crossbar/shared link difference for L3?
  * XXX these should be marked initdata for multi-OMAP kernels
  */
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include "omap_hwmod.h"
 #include "l3_2xxx.h"
index 5345919..ed5f39d 100644 (file)
@@ -96,7 +96,6 @@ static struct omap_hwmod_class_sysconfig omap2xxx_gpio_sysc = {
 struct omap_hwmod_class omap2xxx_gpio_hwmod_class = {
        .name = "gpio",
        .sysc = &omap2xxx_gpio_sysc,
-       .rev = 0,
 };
 
 /* system dma */
index 6f81d7a..aaa6092 100644 (file)
@@ -30,24 +30,16 @@ extern struct omap_hwmod_ocp_if am33xx_l3_main__gfx;
 extern struct omap_hwmod_ocp_if am33xx_l4_wkup__rtc;
 extern struct omap_hwmod_ocp_if am33xx_l4_per__dcan0;
 extern struct omap_hwmod_ocp_if am33xx_l4_per__dcan1;
-extern struct omap_hwmod_ocp_if am33xx_l4_per__gpio1;
-extern struct omap_hwmod_ocp_if am33xx_l4_per__gpio2;
-extern struct omap_hwmod_ocp_if am33xx_l4_per__gpio3;
 extern struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__elm;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss0;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss1;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss2;
 extern struct omap_hwmod_ocp_if am33xx_l3_s__gpmc;
-extern struct omap_hwmod_ocp_if am33xx_l4_per__i2c2;
-extern struct omap_hwmod_ocp_if am33xx_l4_per__i2c3;
 extern struct omap_hwmod_ocp_if am33xx_l4_per__mailbox;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__spinlock;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp0;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp1;
-extern struct omap_hwmod_ocp_if am33xx_l4_ls__mmc0;
-extern struct omap_hwmod_ocp_if am33xx_l4_ls__mmc1;
-extern struct omap_hwmod_ocp_if am33xx_l3_s__mmc2;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__mcspi0;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__mcspi1;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__timer2;
@@ -60,11 +52,6 @@ extern struct omap_hwmod_ocp_if am33xx_l3_main__tpcc;
 extern struct omap_hwmod_ocp_if am33xx_l3_main__tptc0;
 extern struct omap_hwmod_ocp_if am33xx_l3_main__tptc1;
 extern struct omap_hwmod_ocp_if am33xx_l3_main__tptc2;
-extern struct omap_hwmod_ocp_if am33xx_l4_ls__uart2;
-extern struct omap_hwmod_ocp_if am33xx_l4_ls__uart3;
-extern struct omap_hwmod_ocp_if am33xx_l4_ls__uart4;
-extern struct omap_hwmod_ocp_if am33xx_l4_ls__uart5;
-extern struct omap_hwmod_ocp_if am33xx_l4_ls__uart6;
 extern struct omap_hwmod_ocp_if am33xx_l3_main__ocmc;
 extern struct omap_hwmod_ocp_if am33xx_l3_main__sha0;
 extern struct omap_hwmod_ocp_if am33xx_l3_main__aes0;
@@ -93,19 +80,10 @@ extern struct omap_hwmod am33xx_elm_hwmod;
 extern struct omap_hwmod am33xx_epwmss0_hwmod;
 extern struct omap_hwmod am33xx_epwmss1_hwmod;
 extern struct omap_hwmod am33xx_epwmss2_hwmod;
-extern struct omap_hwmod am33xx_gpio1_hwmod;
-extern struct omap_hwmod am33xx_gpio2_hwmod;
-extern struct omap_hwmod am33xx_gpio3_hwmod;
 extern struct omap_hwmod am33xx_gpmc_hwmod;
-extern struct omap_hwmod am33xx_i2c1_hwmod;
-extern struct omap_hwmod am33xx_i2c2_hwmod;
-extern struct omap_hwmod am33xx_i2c3_hwmod;
 extern struct omap_hwmod am33xx_mailbox_hwmod;
 extern struct omap_hwmod am33xx_mcasp0_hwmod;
 extern struct omap_hwmod am33xx_mcasp1_hwmod;
-extern struct omap_hwmod am33xx_mmc0_hwmod;
-extern struct omap_hwmod am33xx_mmc1_hwmod;
-extern struct omap_hwmod am33xx_mmc2_hwmod;
 extern struct omap_hwmod am33xx_rtc_hwmod;
 extern struct omap_hwmod am33xx_spi0_hwmod;
 extern struct omap_hwmod am33xx_spi1_hwmod;
@@ -121,19 +99,12 @@ extern struct omap_hwmod am33xx_tpcc_hwmod;
 extern struct omap_hwmod am33xx_tptc0_hwmod;
 extern struct omap_hwmod am33xx_tptc1_hwmod;
 extern struct omap_hwmod am33xx_tptc2_hwmod;
-extern struct omap_hwmod am33xx_uart1_hwmod;
-extern struct omap_hwmod am33xx_uart2_hwmod;
-extern struct omap_hwmod am33xx_uart3_hwmod;
-extern struct omap_hwmod am33xx_uart4_hwmod;
-extern struct omap_hwmod am33xx_uart5_hwmod;
-extern struct omap_hwmod am33xx_uart6_hwmod;
 extern struct omap_hwmod am33xx_wd_timer1_hwmod;
 
 extern struct omap_hwmod_class am33xx_emif_hwmod_class;
 extern struct omap_hwmod_class am33xx_l4_hwmod_class;
 extern struct omap_hwmod_class am33xx_wkup_m3_hwmod_class;
 extern struct omap_hwmod_class am33xx_control_hwmod_class;
-extern struct omap_hwmod_class am33xx_gpio_hwmod_class;
 extern struct omap_hwmod_class am33xx_timer_hwmod_class;
 extern struct omap_hwmod_class am33xx_epwmss_hwmod_class;
 extern struct omap_hwmod_class am33xx_ehrpwm_hwmod_class;
index e000123..47a0e30 100644 (file)
@@ -122,30 +122,6 @@ struct omap_hwmod_ocp_if am33xx_l4_per__dcan1 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4 per/ls -> GPIO2 */
-struct omap_hwmod_ocp_if am33xx_l4_per__gpio1 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am33xx_gpio1_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4 per/ls -> gpio3 */
-struct omap_hwmod_ocp_if am33xx_l4_per__gpio2 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am33xx_gpio2_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4 per/ls -> gpio4 */
-struct omap_hwmod_ocp_if am33xx_l4_per__gpio3 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am33xx_gpio3_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio = {
        .master         = &am33xx_cpgmac0_hwmod,
        .slave          = &am33xx_mdio_hwmod,
@@ -188,21 +164,6 @@ struct omap_hwmod_ocp_if am33xx_l3_s__gpmc = {
        .user           = OCP_USER_MPU,
 };
 
-/* i2c2 */
-struct omap_hwmod_ocp_if am33xx_l4_per__i2c2 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am33xx_i2c2_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU,
-};
-
-struct omap_hwmod_ocp_if am33xx_l4_per__i2c3 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am33xx_i2c3_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU,
-};
-
 /* l4 ls -> mailbox */
 struct omap_hwmod_ocp_if am33xx_l4_per__mailbox = {
        .master         = &am33xx_l4_ls_hwmod,
@@ -235,30 +196,6 @@ struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp1 = {
        .user           = OCP_USER_MPU,
 };
 
-/* l4 ls -> mmc0 */
-struct omap_hwmod_ocp_if am33xx_l4_ls__mmc0 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am33xx_mmc0_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU,
-};
-
-/* l4 ls -> mmc1 */
-struct omap_hwmod_ocp_if am33xx_l4_ls__mmc1 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am33xx_mmc1_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU,
-};
-
-/* l3 s -> mmc2 */
-struct omap_hwmod_ocp_if am33xx_l3_s__mmc2 = {
-       .master         = &am33xx_l3_s_hwmod,
-       .slave          = &am33xx_mmc2_hwmod,
-       .clk            = "l3s_gclk",
-       .user           = OCP_USER_MPU,
-};
-
 /* l4 ls -> mcspi0 */
 struct omap_hwmod_ocp_if am33xx_l4_ls__mcspi0 = {
        .master         = &am33xx_l4_ls_hwmod,
@@ -355,46 +292,6 @@ struct omap_hwmod_ocp_if am33xx_l3_main__tptc2 = {
        .user           = OCP_USER_MPU,
 };
 
-/* l4 ls -> uart2 */
-struct omap_hwmod_ocp_if am33xx_l4_ls__uart2 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am33xx_uart2_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU,
-};
-
-/* l4 ls -> uart3 */
-struct omap_hwmod_ocp_if am33xx_l4_ls__uart3 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am33xx_uart3_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU,
-};
-
-/* l4 ls -> uart4 */
-struct omap_hwmod_ocp_if am33xx_l4_ls__uart4 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am33xx_uart4_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU,
-};
-
-/* l4 ls -> uart5 */
-struct omap_hwmod_ocp_if am33xx_l4_ls__uart5 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am33xx_uart5_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU,
-};
-
-/* l4 ls -> uart6 */
-struct omap_hwmod_ocp_if am33xx_l4_ls__uart6 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am33xx_uart6_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU,
-};
-
 /* l3 main -> ocmc */
 struct omap_hwmod_ocp_if am33xx_l3_main__ocmc = {
        .master         = &am33xx_l3_main_hwmod,
index 9ded7bf..4c3543b 100644 (file)
@@ -16,9 +16,7 @@
 
 #include <linux/types.h>
 
-#include <linux/platform_data/hsmmc-omap.h>
 #include "omap_hwmod.h"
-#include "i2c.h"
 #include "wd_timer.h"
 #include "cm33xx.h"
 #include "prm33xx.h"
@@ -534,7 +532,6 @@ static struct omap_hwmod_class_sysconfig am33xx_gpio_sysc = {
 struct omap_hwmod_class am33xx_gpio_hwmod_class = {
        .name           = "gpio",
        .sysc           = &am33xx_gpio_sysc,
-       .rev            = 2,
 };
 
 /* gpio1 */
@@ -627,68 +624,6 @@ struct omap_hwmod am33xx_gpmc_hwmod = {
        },
 };
 
-/* 'i2c' class */
-static struct omap_hwmod_class_sysconfig am33xx_i2c_sysc = {
-       .rev_offs       = 0,
-       .sysc_offs      = 0x0010,
-       .syss_offs      = 0x0090,
-       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
-                         SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-                         SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                         SIDLE_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class i2c_class = {
-       .name           = "i2c",
-       .sysc           = &am33xx_i2c_sysc,
-       .rev            = OMAP_I2C_IP_VERSION_2,
-       .reset          = &omap_i2c_reset,
-};
-
-/* i2c1 */
-struct omap_hwmod am33xx_i2c1_hwmod = {
-       .name           = "i2c1",
-       .class          = &i2c_class,
-       .clkdm_name     = "l4_wkup_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "dpll_per_m2_div4_wkupdm_ck",
-       .prcm           = {
-               .omap4  = {
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* i2c1 */
-struct omap_hwmod am33xx_i2c2_hwmod = {
-       .name           = "i2c2",
-       .class          = &i2c_class,
-       .clkdm_name     = "l4ls_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "dpll_per_m2_div4_ck",
-       .prcm           = {
-               .omap4 = {
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* i2c3 */
-struct omap_hwmod am33xx_i2c3_hwmod = {
-       .name           = "i2c3",
-       .class          = &i2c_class,
-       .clkdm_name     = "l4ls_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "dpll_per_m2_div4_ck",
-       .prcm           = {
-               .omap4  = {
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
 /*
  * 'mailbox' class
  * mailbox module allowing communication between the on-chip processors using a
@@ -762,76 +697,6 @@ struct omap_hwmod am33xx_mcasp1_hwmod = {
        },
 };
 
-/* 'mmc' class */
-static struct omap_hwmod_class_sysconfig am33xx_mmc_sysc = {
-       .rev_offs       = 0x2fc,
-       .sysc_offs      = 0x110,
-       .syss_offs      = 0x114,
-       .sysc_flags     = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
-                         SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-                         SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class am33xx_mmc_hwmod_class = {
-       .name           = "mmc",
-       .sysc           = &am33xx_mmc_sysc,
-};
-
-/* mmc0 */
-static struct omap_hsmmc_dev_attr am33xx_mmc0_dev_attr = {
-       .flags          = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
-};
-
-struct omap_hwmod am33xx_mmc0_hwmod = {
-       .name           = "mmc1",
-       .class          = &am33xx_mmc_hwmod_class,
-       .clkdm_name     = "l4ls_clkdm",
-       .main_clk       = "mmc_clk",
-       .prcm           = {
-               .omap4  = {
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-       .dev_attr       = &am33xx_mmc0_dev_attr,
-};
-
-/* mmc1 */
-static struct omap_hsmmc_dev_attr am33xx_mmc1_dev_attr = {
-       .flags          = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
-};
-
-struct omap_hwmod am33xx_mmc1_hwmod = {
-       .name           = "mmc2",
-       .class          = &am33xx_mmc_hwmod_class,
-       .clkdm_name     = "l4ls_clkdm",
-       .main_clk       = "mmc_clk",
-       .prcm           = {
-               .omap4  = {
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-       .dev_attr       = &am33xx_mmc1_dev_attr,
-};
-
-/* mmc2 */
-static struct omap_hsmmc_dev_attr am33xx_mmc2_dev_attr = {
-       .flags          = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
-};
-struct omap_hwmod am33xx_mmc2_hwmod = {
-       .name           = "mmc3",
-       .class          = &am33xx_mmc_hwmod_class,
-       .clkdm_name     = "l3s_clkdm",
-       .main_clk       = "mmc_clk",
-       .prcm           = {
-               .omap4  = {
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-       .dev_attr       = &am33xx_mmc2_dev_attr,
-};
-
 /*
  * 'rtc' class
  * rtc subsystem
@@ -1132,102 +997,6 @@ struct omap_hwmod am33xx_tptc2_hwmod = {
        },
 };
 
-/* 'uart' class */
-static struct omap_hwmod_class_sysconfig uart_sysc = {
-       .rev_offs       = 0x50,
-       .sysc_offs      = 0x54,
-       .syss_offs      = 0x58,
-       .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
-                         SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                         SIDLE_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class uart_class = {
-       .name           = "uart",
-       .sysc           = &uart_sysc,
-};
-
-struct omap_hwmod am33xx_uart1_hwmod = {
-       .name           = "uart1",
-       .class          = &uart_class,
-       .clkdm_name     = "l4_wkup_clkdm",
-       .flags          = DEBUG_AM33XXUART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "dpll_per_m2_div4_wkupdm_ck",
-       .prcm           = {
-               .omap4  = {
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-struct omap_hwmod am33xx_uart2_hwmod = {
-       .name           = "uart2",
-       .class          = &uart_class,
-       .clkdm_name     = "l4ls_clkdm",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "dpll_per_m2_div4_ck",
-       .prcm           = {
-               .omap4  = {
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart3 */
-struct omap_hwmod am33xx_uart3_hwmod = {
-       .name           = "uart3",
-       .class          = &uart_class,
-       .clkdm_name     = "l4ls_clkdm",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "dpll_per_m2_div4_ck",
-       .prcm           = {
-               .omap4  = {
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-struct omap_hwmod am33xx_uart4_hwmod = {
-       .name           = "uart4",
-       .class          = &uart_class,
-       .clkdm_name     = "l4ls_clkdm",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "dpll_per_m2_div4_ck",
-       .prcm           = {
-               .omap4  = {
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-struct omap_hwmod am33xx_uart5_hwmod = {
-       .name           = "uart5",
-       .class          = &uart_class,
-       .clkdm_name     = "l4ls_clkdm",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "dpll_per_m2_div4_ck",
-       .prcm           = {
-               .omap4  = {
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-struct omap_hwmod am33xx_uart6_hwmod = {
-       .name           = "uart6",
-       .class          = &uart_class,
-       .clkdm_name     = "l4ls_clkdm",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "dpll_per_m2_div4_ck",
-       .prcm           = {
-               .omap4  = {
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
 /* 'wd_timer' class */
 static struct omap_hwmod_class_sysconfig wdt_sysc = {
        .rev_offs       = 0x0,
@@ -1265,11 +1034,6 @@ struct omap_hwmod am33xx_wd_timer1_hwmod = {
 
 static void omap_hwmod_am33xx_clkctrl(void)
 {
-       CLKCTRL(am33xx_uart2_hwmod, AM33XX_CM_PER_UART1_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_uart3_hwmod, AM33XX_CM_PER_UART2_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_uart4_hwmod, AM33XX_CM_PER_UART3_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_uart5_hwmod, AM33XX_CM_PER_UART4_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_uart6_hwmod, AM33XX_CM_PER_UART5_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_dcan0_hwmod, AM33XX_CM_PER_DCAN0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_dcan1_hwmod, AM33XX_CM_PER_DCAN1_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_elm_hwmod, AM33XX_CM_PER_ELM_CLKCTRL_OFFSET);
@@ -1279,13 +1043,9 @@ static void omap_hwmod_am33xx_clkctrl(void)
        CLKCTRL(am33xx_gpio1_hwmod, AM33XX_CM_PER_GPIO1_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_gpio2_hwmod, AM33XX_CM_PER_GPIO2_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_gpio3_hwmod, AM33XX_CM_PER_GPIO3_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_i2c2_hwmod, AM33XX_CM_PER_I2C1_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_i2c3_hwmod, AM33XX_CM_PER_I2C2_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_mailbox_hwmod, AM33XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_mcasp0_hwmod, AM33XX_CM_PER_MCASP0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_mcasp1_hwmod, AM33XX_CM_PER_MCASP1_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_mmc0_hwmod, AM33XX_CM_PER_MMC0_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_mmc1_hwmod, AM33XX_CM_PER_MMC1_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_spi0_hwmod, AM33XX_CM_PER_SPI0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_spi1_hwmod, AM33XX_CM_PER_SPI1_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_spinlock_hwmod, AM33XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET);
@@ -1299,13 +1059,10 @@ static void omap_hwmod_am33xx_clkctrl(void)
                AM33XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_smartreflex1_hwmod,
                AM33XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_uart1_hwmod, AM33XX_CM_WKUP_UART0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_timer1_hwmod, AM33XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_i2c1_hwmod, AM33XX_CM_WKUP_I2C0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_wd_timer1_hwmod, AM33XX_CM_WKUP_WDT1_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_rtc_hwmod, AM33XX_CM_RTC_RTC_CLKCTRL_OFFSET);
        PRCM_FLAGS(am33xx_rtc_hwmod, HWMOD_OMAP4_ZERO_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_mmc2_hwmod, AM33XX_CM_PER_MMC2_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_gpmc_hwmod, AM33XX_CM_PER_GPMC_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_l4_ls_hwmod, AM33XX_CM_PER_L4LS_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_l4_wkup_hwmod, AM33XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET);
@@ -1340,11 +1097,6 @@ void omap_hwmod_am33xx_reg(void)
 
 static void omap_hwmod_am43xx_clkctrl(void)
 {
-       CLKCTRL(am33xx_uart2_hwmod, AM43XX_CM_PER_UART1_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_uart3_hwmod, AM43XX_CM_PER_UART2_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_uart4_hwmod, AM43XX_CM_PER_UART3_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_uart5_hwmod, AM43XX_CM_PER_UART4_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_uart6_hwmod, AM43XX_CM_PER_UART5_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_dcan0_hwmod, AM43XX_CM_PER_DCAN0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_dcan1_hwmod, AM43XX_CM_PER_DCAN1_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_elm_hwmod, AM43XX_CM_PER_ELM_CLKCTRL_OFFSET);
@@ -1354,13 +1106,9 @@ static void omap_hwmod_am43xx_clkctrl(void)
        CLKCTRL(am33xx_gpio1_hwmod, AM43XX_CM_PER_GPIO1_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_gpio2_hwmod, AM43XX_CM_PER_GPIO2_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_gpio3_hwmod, AM43XX_CM_PER_GPIO3_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_i2c2_hwmod, AM43XX_CM_PER_I2C1_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_i2c3_hwmod, AM43XX_CM_PER_I2C2_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_mailbox_hwmod, AM43XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_mcasp0_hwmod, AM43XX_CM_PER_MCASP0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_mcasp1_hwmod, AM43XX_CM_PER_MCASP1_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_mmc0_hwmod, AM43XX_CM_PER_MMC0_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_mmc1_hwmod, AM43XX_CM_PER_MMC1_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_spi0_hwmod, AM43XX_CM_PER_SPI0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_spi1_hwmod, AM43XX_CM_PER_SPI1_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_spinlock_hwmod, AM43XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET);
@@ -1374,12 +1122,9 @@ static void omap_hwmod_am43xx_clkctrl(void)
                AM43XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_smartreflex1_hwmod,
                AM43XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_uart1_hwmod, AM43XX_CM_WKUP_UART0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_timer1_hwmod, AM43XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_i2c1_hwmod, AM43XX_CM_WKUP_I2C0_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_wd_timer1_hwmod, AM43XX_CM_WKUP_WDT1_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_rtc_hwmod, AM43XX_CM_RTC_RTC_CLKCTRL_OFFSET);
-       CLKCTRL(am33xx_mmc2_hwmod, AM43XX_CM_PER_MMC2_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_gpmc_hwmod, AM43XX_CM_PER_GPMC_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_l4_ls_hwmod, AM43XX_CM_PER_L4LS_CLKCTRL_OFFSET);
        CLKCTRL(am33xx_l4_wkup_hwmod, AM43XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET);
index c9483bc..c965af2 100644 (file)
@@ -14,8 +14,6 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/platform_data/i2c-omap.h>
-
 #include "omap_hwmod.h"
 #include "omap_hwmod_common_data.h"
 
@@ -23,7 +21,6 @@
 #include "cm33xx.h"
 #include "prm33xx.h"
 #include "prm-regbits-33xx.h"
-#include "i2c.h"
 #include "wd_timer.h"
 #include "omap_hwmod_33xx_43xx_common_data.h"
 
@@ -230,27 +227,6 @@ static struct omap_hwmod am33xx_control_hwmod = {
        },
 };
 
-/* gpio0 */
-static struct omap_hwmod_opt_clk gpio0_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio0_dbclk" },
-};
-
-static struct omap_hwmod am33xx_gpio0_hwmod = {
-       .name           = "gpio1",
-       .class          = &am33xx_gpio_hwmod_class,
-       .clkdm_name     = "l4_wkup_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "dpll_core_m4_div2_ck",
-       .prcm           = {
-               .omap4  = {
-                       .clkctrl_offs   = AM33XX_CM_WKUP_GPIO0_CLKCTRL_OFFSET,
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-       .opt_clks       = gpio0_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio0_opt_clks),
-};
-
 /* lcdc */
 static struct omap_hwmod_class_sysconfig lcdc_sysc = {
        .rev_offs       = 0x0,
@@ -388,22 +364,6 @@ static struct omap_hwmod_ocp_if am33xx_l4_wkup__control = {
        .user           = OCP_USER_MPU,
 };
 
-/* L4 WKUP -> I2C1 */
-static struct omap_hwmod_ocp_if am33xx_l4_wkup__i2c1 = {
-       .master         = &am33xx_l4_wkup_hwmod,
-       .slave          = &am33xx_i2c1_hwmod,
-       .clk            = "dpll_core_m4_div2_ck",
-       .user           = OCP_USER_MPU,
-};
-
-/* L4 WKUP -> GPIO1 */
-static struct omap_hwmod_ocp_if am33xx_l4_wkup__gpio0 = {
-       .master         = &am33xx_l4_wkup_hwmod,
-       .slave          = &am33xx_gpio0_hwmod,
-       .clk            = "dpll_core_m4_div2_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* L4 WKUP -> ADC_TSC */
 static struct omap_hwmod_ocp_if am33xx_l4_wkup__adc_tsc = {
        .master         = &am33xx_l4_wkup_hwmod,
@@ -434,14 +394,6 @@ static struct omap_hwmod_ocp_if am33xx_l4_wkup__timer1 = {
        .user           = OCP_USER_MPU,
 };
 
-/* l4 wkup -> uart1 */
-static struct omap_hwmod_ocp_if am33xx_l4_wkup__uart1 = {
-       .master         = &am33xx_l4_wkup_hwmod,
-       .slave          = &am33xx_uart1_hwmod,
-       .clk            = "dpll_core_m4_div2_ck",
-       .user           = OCP_USER_MPU,
-};
-
 /* l4 wkup -> wd_timer1 */
 static struct omap_hwmod_ocp_if am33xx_l4_wkup__wd_timer1 = {
        .master         = &am33xx_l4_wkup_hwmod,
@@ -479,27 +431,16 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
        &am33xx_l4_wkup__control,
        &am33xx_l4_wkup__smartreflex0,
        &am33xx_l4_wkup__smartreflex1,
-       &am33xx_l4_wkup__uart1,
        &am33xx_l4_wkup__timer1,
        &am33xx_l4_wkup__rtc,
-       &am33xx_l4_wkup__i2c1,
-       &am33xx_l4_wkup__gpio0,
        &am33xx_l4_wkup__adc_tsc,
        &am33xx_l4_wkup__wd_timer1,
        &am33xx_l4_hs__pruss,
        &am33xx_l4_per__dcan0,
        &am33xx_l4_per__dcan1,
-       &am33xx_l4_per__gpio1,
-       &am33xx_l4_per__gpio2,
-       &am33xx_l4_per__gpio3,
-       &am33xx_l4_per__i2c2,
-       &am33xx_l4_per__i2c3,
        &am33xx_l4_per__mailbox,
        &am33xx_l4_ls__mcasp0,
        &am33xx_l4_ls__mcasp1,
-       &am33xx_l4_ls__mmc0,
-       &am33xx_l4_ls__mmc1,
-       &am33xx_l3_s__mmc2,
        &am33xx_l4_ls__timer2,
        &am33xx_l4_ls__timer3,
        &am33xx_l4_ls__timer4,
@@ -507,11 +448,6 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
        &am33xx_l4_ls__timer6,
        &am33xx_l4_ls__timer7,
        &am33xx_l3_main__tpcc,
-       &am33xx_l4_ls__uart2,
-       &am33xx_l4_ls__uart3,
-       &am33xx_l4_ls__uart4,
-       &am33xx_l4_ls__uart5,
-       &am33xx_l4_ls__uart6,
        &am33xx_l4_ls__spinlock,
        &am33xx_l4_ls__elm,
        &am33xx_l4_ls__epwmss0,
index 23e6a41..edff399 100644 (file)
@@ -484,7 +484,6 @@ static struct omap_hwmod am35xx_uart4_hwmod = {
 static struct omap_hwmod_class i2c_class = {
        .name   = "i2c",
        .sysc   = &i2c_sysc,
-       .rev    = OMAP_I2C_IP_VERSION_1,
        .reset  = &omap_i2c_reset,
 };
 
@@ -707,7 +706,6 @@ static struct omap_hwmod_class_sysconfig omap3xxx_gpio_sysc = {
 static struct omap_hwmod_class omap3xxx_gpio_hwmod_class = {
        .name = "gpio",
        .sysc = &omap3xxx_gpio_sysc,
-       .rev = 1,
 };
 
 /* gpio1 */
@@ -1029,7 +1027,6 @@ static struct omap_hwmod_class_sysconfig omap34xx_sr_sysc = {
 static struct omap_hwmod_class omap34xx_smartreflex_hwmod_class = {
        .name = "smartreflex",
        .sysc = &omap34xx_sr_sysc,
-       .rev  = 1,
 };
 
 static struct omap_hwmod_class_sysconfig omap36xx_sr_sysc = {
@@ -1044,7 +1041,6 @@ static struct omap_hwmod_class_sysconfig omap36xx_sr_sysc = {
 static struct omap_hwmod_class omap36xx_smartreflex_hwmod_class = {
        .name = "smartreflex",
        .sysc = &omap36xx_sr_sysc,
-       .rev  = 2,
 };
 
 /* SR1 */
index aa271ac..69571ab 100644 (file)
@@ -87,26 +87,6 @@ static struct omap_hwmod am43xx_control_hwmod = {
        },
 };
 
-static struct omap_hwmod_opt_clk gpio0_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio0_dbclk" },
-};
-
-static struct omap_hwmod am43xx_gpio0_hwmod = {
-       .name           = "gpio1",
-       .class          = &am33xx_gpio_hwmod_class,
-       .clkdm_name     = "l4_wkup_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "sys_clkin_ck",
-       .prcm           = {
-               .omap4  = {
-                       .clkctrl_offs   = AM43XX_CM_WKUP_GPIO0_CLKCTRL_OFFSET,
-                       .modulemode     = MODULEMODE_SWCTRL,
-               },
-       },
-       .opt_clks       = gpio0_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio0_opt_clks),
-};
-
 static struct omap_hwmod_class_sysconfig am43xx_synctimer_sysc = {
        .rev_offs       = 0x0,
        .sysc_offs      = 0x4,
@@ -264,46 +244,6 @@ static struct omap_hwmod am43xx_spi4_hwmod = {
        },
 };
 
-static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio4_dbclk" },
-};
-
-static struct omap_hwmod am43xx_gpio4_hwmod = {
-       .name           = "gpio5",
-       .class          = &am33xx_gpio_hwmod_class,
-       .clkdm_name     = "l4ls_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4ls_gclk",
-       .prcm           = {
-               .omap4  = {
-                       .clkctrl_offs = AM43XX_CM_PER_GPIO4_CLKCTRL_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-       .opt_clks       = gpio4_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio4_opt_clks),
-};
-
-static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio5_dbclk" },
-};
-
-static struct omap_hwmod am43xx_gpio5_hwmod = {
-       .name           = "gpio6",
-       .class          = &am33xx_gpio_hwmod_class,
-       .clkdm_name     = "l4ls_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4ls_gclk",
-       .prcm           = {
-               .omap4  = {
-                       .clkctrl_offs = AM43XX_CM_PER_GPIO5_CLKCTRL_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-       .opt_clks       = gpio5_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio5_opt_clks),
-};
-
 static struct omap_hwmod_class am43xx_ocp2scp_hwmod_class = {
        .name   = "ocp2scp",
 };
@@ -650,20 +590,6 @@ static struct omap_hwmod_ocp_if am43xx_l4_wkup__control = {
        .user           = OCP_USER_MPU,
 };
 
-static struct omap_hwmod_ocp_if am43xx_l4_wkup__i2c1 = {
-       .master         = &am33xx_l4_wkup_hwmod,
-       .slave          = &am33xx_i2c1_hwmod,
-       .clk            = "sys_clkin_ck",
-       .user           = OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if am43xx_l4_wkup__gpio0 = {
-       .master         = &am33xx_l4_wkup_hwmod,
-       .slave          = &am43xx_gpio0_hwmod,
-       .clk            = "sys_clkin_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 static struct omap_hwmod_ocp_if am43xx_l4_wkup__adc_tsc = {
        .master         = &am33xx_l4_wkup_hwmod,
        .slave          = &am43xx_adc_tsc_hwmod,
@@ -685,13 +611,6 @@ static struct omap_hwmod_ocp_if am43xx_l4_wkup__timer1 = {
        .user           = OCP_USER_MPU,
 };
 
-static struct omap_hwmod_ocp_if am43xx_l4_wkup__uart1 = {
-       .master         = &am33xx_l4_wkup_hwmod,
-       .slave          = &am33xx_uart1_hwmod,
-       .clk            = "sys_clkin_ck",
-       .user           = OCP_USER_MPU,
-};
-
 static struct omap_hwmod_ocp_if am43xx_l4_wkup__wd_timer1 = {
        .master         = &am33xx_l4_wkup_hwmod,
        .slave          = &am33xx_wd_timer1_hwmod,
@@ -776,20 +695,6 @@ static struct omap_hwmod_ocp_if am43xx_l4_ls__mcspi4 = {
        .user           = OCP_USER_MPU,
 };
 
-static struct omap_hwmod_ocp_if am43xx_l4_ls__gpio4 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am43xx_gpio4_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-static struct omap_hwmod_ocp_if am43xx_l4_ls__gpio5 = {
-       .master         = &am33xx_l4_ls_hwmod,
-       .slave          = &am43xx_gpio5_hwmod,
-       .clk            = "l4ls_gclk",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 static struct omap_hwmod_ocp_if am43xx_l4_ls__ocp2scp0 = {
        .master         = &am33xx_l4_ls_hwmod,
        .slave          = &am43xx_ocp2scp0_hwmod,
@@ -907,8 +812,6 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
        &am43xx_l4_ls__mcspi2,
        &am43xx_l4_ls__mcspi3,
        &am43xx_l4_ls__mcspi4,
-       &am43xx_l4_ls__gpio4,
-       &am43xx_l4_ls__gpio5,
        &am43xx_l3_main__pruss,
        &am33xx_mpu__l3_main,
        &am33xx_mpu__prcm,
@@ -927,27 +830,16 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
        &am43xx_l4_wkup__control,
        &am43xx_l4_wkup__smartreflex0,
        &am43xx_l4_wkup__smartreflex1,
-       &am43xx_l4_wkup__uart1,
        &am43xx_l4_wkup__timer1,
-       &am43xx_l4_wkup__i2c1,
-       &am43xx_l4_wkup__gpio0,
        &am43xx_l4_wkup__wd_timer1,
        &am43xx_l4_wkup__adc_tsc,
        &am43xx_l3_s__qspi,
        &am33xx_l4_per__dcan0,
        &am33xx_l4_per__dcan1,
-       &am33xx_l4_per__gpio1,
-       &am33xx_l4_per__gpio2,
-       &am33xx_l4_per__gpio3,
-       &am33xx_l4_per__i2c2,
-       &am33xx_l4_per__i2c3,
        &am33xx_l4_per__mailbox,
        &am33xx_l4_per__rng,
        &am33xx_l4_ls__mcasp0,
        &am33xx_l4_ls__mcasp1,
-       &am33xx_l4_ls__mmc0,
-       &am33xx_l4_ls__mmc1,
-       &am33xx_l3_s__mmc2,
        &am33xx_l4_ls__timer2,
        &am33xx_l4_ls__timer3,
        &am33xx_l4_ls__timer4,
@@ -955,11 +847,6 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
        &am33xx_l4_ls__timer6,
        &am33xx_l4_ls__timer7,
        &am33xx_l3_main__tpcc,
-       &am33xx_l4_ls__uart2,
-       &am33xx_l4_ls__uart3,
-       &am33xx_l4_ls__uart4,
-       &am33xx_l4_ls__uart5,
-       &am33xx_l4_ls__uart6,
        &am33xx_l4_ls__spinlock,
        &am33xx_l4_ls__elm,
        &am33xx_l4_ls__epwmss0,
index a95dbac..b8de550 100644 (file)
@@ -21,9 +21,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/platform_data/hsmmc-omap.h>
 #include <linux/power/smartreflex.h>
-#include <linux/platform_data/i2c-omap.h>
 
 #include <linux/omap-dma.h>
 
@@ -33,7 +31,6 @@
 #include "cm2_44xx.h"
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
-#include "i2c.h"
 #include "wd_timer.h"
 
 /* Base offset for all OMAP4 interrupts external to MPUSS */
@@ -1055,160 +1052,6 @@ static struct omap_hwmod omap44xx_fdif_hwmod = {
        },
 };
 
-/*
- * 'gpio' class
- * general purpose io module
- */
-
-static struct omap_hwmod_class_sysconfig omap44xx_gpio_sysc = {
-       .rev_offs       = 0x0000,
-       .sysc_offs      = 0x0010,
-       .syss_offs      = 0x0114,
-       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
-                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-                          SYSS_HAS_RESET_STATUS),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap44xx_gpio_hwmod_class = {
-       .name   = "gpio",
-       .sysc   = &omap44xx_gpio_sysc,
-       .rev    = 2,
-};
-
-/* gpio1 */
-static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio1_dbclk" },
-};
-
-static struct omap_hwmod omap44xx_gpio1_hwmod = {
-       .name           = "gpio1",
-       .class          = &omap44xx_gpio_hwmod_class,
-       .clkdm_name     = "l4_wkup_clkdm",
-       .main_clk       = "l4_wkup_clk_mux_ck",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_WKUP_GPIO1_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_WKUP_GPIO1_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio1_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio1_opt_clks),
-};
-
-/* gpio2 */
-static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio2_dbclk" },
-};
-
-static struct omap_hwmod omap44xx_gpio2_hwmod = {
-       .name           = "gpio2",
-       .class          = &omap44xx_gpio_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4_div_ck",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_GPIO2_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_GPIO2_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio2_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio2_opt_clks),
-};
-
-/* gpio3 */
-static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio3_dbclk" },
-};
-
-static struct omap_hwmod omap44xx_gpio3_hwmod = {
-       .name           = "gpio3",
-       .class          = &omap44xx_gpio_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4_div_ck",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_GPIO3_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_GPIO3_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio3_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio3_opt_clks),
-};
-
-/* gpio4 */
-static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio4_dbclk" },
-};
-
-static struct omap_hwmod omap44xx_gpio4_hwmod = {
-       .name           = "gpio4",
-       .class          = &omap44xx_gpio_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4_div_ck",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_GPIO4_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_GPIO4_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio4_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio4_opt_clks),
-};
-
-/* gpio5 */
-static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio5_dbclk" },
-};
-
-static struct omap_hwmod omap44xx_gpio5_hwmod = {
-       .name           = "gpio5",
-       .class          = &omap44xx_gpio_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4_div_ck",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_GPIO5_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_GPIO5_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio5_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio5_opt_clks),
-};
-
-/* gpio6 */
-static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio6_dbclk" },
-};
-
-static struct omap_hwmod omap44xx_gpio6_hwmod = {
-       .name           = "gpio6",
-       .class          = &omap44xx_gpio_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4_div_ck",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_GPIO6_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_GPIO6_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio6_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio6_opt_clks),
-};
-
 /*
  * 'gpmc' class
  * general purpose memory controller
@@ -1354,94 +1197,6 @@ static struct omap_hwmod omap44xx_hsi_hwmod = {
        },
 };
 
-/*
- * 'i2c' class
- * multimaster high-speed i2c controller
- */
-
-static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = {
-       .rev_offs       = 0,
-       .sysc_offs      = 0x0010,
-       .syss_offs      = 0x0090,
-       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
-                          SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-                          SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap44xx_i2c_hwmod_class = {
-       .name   = "i2c",
-       .sysc   = &omap44xx_i2c_sysc,
-       .rev    = OMAP_I2C_IP_VERSION_2,
-       .reset  = &omap_i2c_reset,
-};
-
-/* i2c1 */
-static struct omap_hwmod omap44xx_i2c1_hwmod = {
-       .name           = "i2c1",
-       .class          = &omap44xx_i2c_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_I2C1_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_I2C1_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* i2c2 */
-static struct omap_hwmod omap44xx_i2c2_hwmod = {
-       .name           = "i2c2",
-       .class          = &omap44xx_i2c_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_I2C2_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_I2C2_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* i2c3 */
-static struct omap_hwmod omap44xx_i2c3_hwmod = {
-       .name           = "i2c3",
-       .class          = &omap44xx_i2c_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_I2C3_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_I2C3_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* i2c4 */
-static struct omap_hwmod omap44xx_i2c4_hwmod = {
-       .name           = "i2c4",
-       .class          = &omap44xx_i2c_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_I2C4_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_I2C4_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
 /*
  * 'ipu' class
  * imaging processor unit
@@ -1818,189 +1573,6 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = {
        },
 };
 
-/*
- * 'mcspi' class
- * multichannel serial port interface (mcspi) / master/slave synchronous serial
- * bus
- */
-
-static struct omap_hwmod_class_sysconfig omap44xx_mcspi_sysc = {
-       .rev_offs       = 0x0000,
-       .sysc_offs      = 0x0010,
-       .sysc_flags     = (SYSC_HAS_EMUFREE | SYSC_HAS_RESET_STATUS |
-                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type2,
-};
-
-static struct omap_hwmod_class omap44xx_mcspi_hwmod_class = {
-       .name   = "mcspi",
-       .sysc   = &omap44xx_mcspi_sysc,
-};
-
-/* mcspi1 */
-static struct omap_hwmod omap44xx_mcspi1_hwmod = {
-       .name           = "mcspi1",
-       .class          = &omap44xx_mcspi_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_MCSPI1_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_MCSPI1_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* mcspi2 */
-static struct omap_hwmod omap44xx_mcspi2_hwmod = {
-       .name           = "mcspi2",
-       .class          = &omap44xx_mcspi_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_MCSPI2_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_MCSPI2_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* mcspi3 */
-static struct omap_hwmod omap44xx_mcspi3_hwmod = {
-       .name           = "mcspi3",
-       .class          = &omap44xx_mcspi_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_MCSPI3_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_MCSPI3_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* mcspi4 */
-static struct omap_hwmod omap44xx_mcspi4_hwmod = {
-       .name           = "mcspi4",
-       .class          = &omap44xx_mcspi_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_MCSPI4_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_MCSPI4_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/*
- * 'mmc' class
- * multimedia card high-speed/sd/sdio (mmc/sd/sdio) host controller
- */
-
-static struct omap_hwmod_class_sysconfig omap44xx_mmc_sysc = {
-       .rev_offs       = 0x0000,
-       .sysc_offs      = 0x0010,
-       .sysc_flags     = (SYSC_HAS_EMUFREE | SYSC_HAS_MIDLEMODE |
-                          SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
-                          SYSC_HAS_SOFTRESET),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
-                          MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type2,
-};
-
-static struct omap_hwmod_class omap44xx_mmc_hwmod_class = {
-       .name   = "mmc",
-       .sysc   = &omap44xx_mmc_sysc,
-};
-
-/* mmc1 */
-static struct omap_hsmmc_dev_attr mmc1_dev_attr = {
-       .flags  = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
-};
-
-static struct omap_hwmod omap44xx_mmc1_hwmod = {
-       .name           = "mmc1",
-       .class          = &omap44xx_mmc_hwmod_class,
-       .clkdm_name     = "l3_init_clkdm",
-       .main_clk       = "hsmmc1_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L3INIT_MMC1_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L3INIT_MMC1_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-       .dev_attr       = &mmc1_dev_attr,
-};
-
-/* mmc2 */
-static struct omap_hwmod omap44xx_mmc2_hwmod = {
-       .name           = "mmc2",
-       .class          = &omap44xx_mmc_hwmod_class,
-       .clkdm_name     = "l3_init_clkdm",
-       .main_clk       = "hsmmc2_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L3INIT_MMC2_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L3INIT_MMC2_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* mmc3 */
-static struct omap_hwmod omap44xx_mmc3_hwmod = {
-       .name           = "mmc3",
-       .class          = &omap44xx_mmc_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_MMCSD3_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_MMCSD3_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* mmc4 */
-static struct omap_hwmod omap44xx_mmc4_hwmod = {
-       .name           = "mmc4",
-       .class          = &omap44xx_mmc_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_MMCSD4_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_MMCSD4_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* mmc5 */
-static struct omap_hwmod omap44xx_mmc5_hwmod = {
-       .name           = "mmc5",
-       .class          = &omap44xx_mmc_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_MMCSD5_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_MMCSD5_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
 /*
  * 'mmu' class
  * The memory management unit performs virtual to physical address translation
@@ -2367,7 +1939,6 @@ static struct omap_hwmod_class_sysconfig omap44xx_smartreflex_sysc = {
 static struct omap_hwmod_class omap44xx_smartreflex_hwmod_class = {
        .name   = "smartreflex",
        .sysc   = &omap44xx_smartreflex_sysc,
-       .rev    = 2,
 };
 
 /* smartreflex_core */
@@ -2672,92 +2243,6 @@ static struct omap_hwmod omap44xx_timer11_hwmod = {
        },
 };
 
-/*
- * 'uart' class
- * universal asynchronous receiver/transmitter (uart)
- */
-
-static struct omap_hwmod_class_sysconfig omap44xx_uart_sysc = {
-       .rev_offs       = 0x0050,
-       .sysc_offs      = 0x0054,
-       .syss_offs      = 0x0058,
-       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
-                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-                          SYSS_HAS_RESET_STATUS),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap44xx_uart_hwmod_class = {
-       .name   = "uart",
-       .sysc   = &omap44xx_uart_sysc,
-};
-
-/* uart1 */
-static struct omap_hwmod omap44xx_uart1_hwmod = {
-       .name           = "uart1",
-       .class          = &omap44xx_uart_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_UART1_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_UART1_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart2 */
-static struct omap_hwmod omap44xx_uart2_hwmod = {
-       .name           = "uart2",
-       .class          = &omap44xx_uart_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_UART2_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_UART2_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart3 */
-static struct omap_hwmod omap44xx_uart3_hwmod = {
-       .name           = "uart3",
-       .class          = &omap44xx_uart_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .flags          = DEBUG_OMAP4UART3_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_UART3_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_UART3_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart4 */
-static struct omap_hwmod omap44xx_uart4_hwmod = {
-       .name           = "uart4",
-       .class          = &omap44xx_uart_hwmod_class,
-       .clkdm_name     = "l4_per_clkdm",
-       .flags          = DEBUG_OMAP4UART4_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP4_CM_L4PER_UART4_CLKCTRL_OFFSET,
-                       .context_offs = OMAP4_RM_L4PER_UART4_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
 /*
  * 'usb_host_fs' class
  * full-speed usb host controller
@@ -3082,22 +2567,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_1 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* mmc1 -> l3_main_1 */
-static struct omap_hwmod_ocp_if omap44xx_mmc1__l3_main_1 = {
-       .master         = &omap44xx_mmc1_hwmod,
-       .slave          = &omap44xx_l3_main_1_hwmod,
-       .clk            = "l3_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mmc2 -> l3_main_1 */
-static struct omap_hwmod_ocp_if omap44xx_mmc2__l3_main_1 = {
-       .master         = &omap44xx_mmc2_hwmod,
-       .slave          = &omap44xx_l3_main_1_hwmod,
-       .clk            = "l3_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* mpu -> l3_main_1 */
 static struct omap_hwmod_ocp_if omap44xx_mpu__l3_main_1 = {
        .master         = &omap44xx_mpu_hwmod,
@@ -3554,54 +3023,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__fdif = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_wkup -> gpio1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_wkup__gpio1 = {
-       .master         = &omap44xx_l4_wkup_hwmod,
-       .slave          = &omap44xx_gpio1_hwmod,
-       .clk            = "l4_wkup_clk_mux_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio2 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_gpio2_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio3 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_gpio3_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio4 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_gpio4_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio5 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio5 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_gpio5_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio6 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio6 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_gpio6_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l3_main_2 -> gpmc */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__gpmc = {
        .master         = &omap44xx_l3_main_2_hwmod,
@@ -3634,38 +3055,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__hsi = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_per -> i2c1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c1 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_i2c1_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> i2c2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c2 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_i2c2_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> i2c3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c3 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_i2c3_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> i2c4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c4 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_i2c4_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l3_main_2 -> ipu */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__ipu = {
        .master         = &omap44xx_l3_main_2_hwmod,
@@ -3770,78 +3159,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_per -> mcspi1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi1 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_mcspi1_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> mcspi2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi2 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_mcspi2_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> mcspi3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi3 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_mcspi3_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> mcspi4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi4 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_mcspi4_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> mmc1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc1 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_mmc1_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> mmc2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc2 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_mmc2_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> mmc3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc3 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_mmc3_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> mmc4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc4 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_mmc4_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> mmc5 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc5 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_mmc5_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l3_main_2 -> ocmc_ram */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__ocmc_ram = {
        .master         = &omap44xx_l3_main_2_hwmod,
@@ -4050,38 +3367,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__timer11 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_per -> uart1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__uart1 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_uart1_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> uart2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__uart2 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_uart2_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> uart3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__uart3 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_uart3_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> uart4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__uart4 = {
-       .master         = &omap44xx_l4_per_hwmod,
-       .slave          = &omap44xx_uart4_hwmod,
-       .clk            = "l4_div_ck",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l4_cfg -> usb_host_fs */
 static struct omap_hwmod_ocp_if __maybe_unused omap44xx_l4_cfg__usb_host_fs = {
        .master         = &omap44xx_l4_cfg_hwmod,
@@ -4164,8 +3449,6 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
        &omap44xx_dss__l3_main_1,
        &omap44xx_l3_main_2__l3_main_1,
        &omap44xx_l4_cfg__l3_main_1,
-       &omap44xx_mmc1__l3_main_1,
-       &omap44xx_mmc2__l3_main_1,
        &omap44xx_mpu__l3_main_1,
        &omap44xx_debugss__l3_main_2,
        &omap44xx_dma_system__l3_main_2,
@@ -4222,20 +3505,10 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
        &omap44xx_l4_per__dss_venc,
        &omap44xx_l4_per__elm,
        &omap44xx_l4_cfg__fdif,
-       &omap44xx_l4_wkup__gpio1,
-       &omap44xx_l4_per__gpio2,
-       &omap44xx_l4_per__gpio3,
-       &omap44xx_l4_per__gpio4,
-       &omap44xx_l4_per__gpio5,
-       &omap44xx_l4_per__gpio6,
        &omap44xx_l3_main_2__gpmc,
        &omap44xx_l3_main_2__gpu,
        &omap44xx_l4_per__hdq1w,
        &omap44xx_l4_cfg__hsi,
-       &omap44xx_l4_per__i2c1,
-       &omap44xx_l4_per__i2c2,
-       &omap44xx_l4_per__i2c3,
-       &omap44xx_l4_per__i2c4,
        &omap44xx_l3_main_2__ipu,
        &omap44xx_l3_main_2__iss,
        /* &omap44xx_iva__sl2if, */
@@ -4249,15 +3522,6 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
        &omap44xx_l4_abe__mcbsp3,
        &omap44xx_l4_per__mcbsp4,
        &omap44xx_l4_abe__mcpdm,
-       &omap44xx_l4_per__mcspi1,
-       &omap44xx_l4_per__mcspi2,
-       &omap44xx_l4_per__mcspi3,
-       &omap44xx_l4_per__mcspi4,
-       &omap44xx_l4_per__mmc1,
-       &omap44xx_l4_per__mmc2,
-       &omap44xx_l4_per__mmc3,
-       &omap44xx_l4_per__mmc4,
-       &omap44xx_l4_per__mmc5,
        &omap44xx_l3_main_2__mmu_ipu,
        &omap44xx_l4_cfg__mmu_dsp,
        &omap44xx_l3_main_2__ocmc_ram,
@@ -4286,10 +3550,6 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
        &omap44xx_l4_per__timer9,
        &omap44xx_l4_per__timer10,
        &omap44xx_l4_per__timer11,
-       &omap44xx_l4_per__uart1,
-       &omap44xx_l4_per__uart2,
-       &omap44xx_l4_per__uart3,
-       &omap44xx_l4_per__uart4,
        /* &omap44xx_l4_cfg__usb_host_fs, */
        &omap44xx_l4_cfg__usb_host_hs,
        &omap44xx_l4_cfg__usb_otg_hs,
index 115473d..29805cc 100644 (file)
@@ -18,9 +18,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/platform_data/hsmmc-omap.h>
 #include <linux/power/smartreflex.h>
-#include <linux/platform_data/i2c-omap.h>
 
 #include <linux/omap-dma.h>
 
@@ -29,7 +27,6 @@
 #include "cm1_54xx.h"
 #include "cm2_54xx.h"
 #include "prm54xx.h"
-#include "i2c.h"
 #include "wd_timer.h"
 
 /* Base offset for all OMAP5 interrupts external to MPUSS */
@@ -600,308 +597,6 @@ static struct omap_hwmod omap54xx_emif2_hwmod = {
        },
 };
 
-/*
- * 'gpio' class
- * general purpose io module
- */
-
-static struct omap_hwmod_class_sysconfig omap54xx_gpio_sysc = {
-       .rev_offs       = 0x0000,
-       .sysc_offs      = 0x0010,
-       .syss_offs      = 0x0114,
-       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
-                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-                          SYSS_HAS_RESET_STATUS),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap54xx_gpio_hwmod_class = {
-       .name   = "gpio",
-       .sysc   = &omap54xx_gpio_sysc,
-       .rev    = 2,
-};
-
-/* gpio1 */
-static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio1_dbclk" },
-};
-
-static struct omap_hwmod omap54xx_gpio1_hwmod = {
-       .name           = "gpio1",
-       .class          = &omap54xx_gpio_hwmod_class,
-       .clkdm_name     = "wkupaon_clkdm",
-       .main_clk       = "wkupaon_iclk_mux",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_WKUPAON_GPIO1_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_WKUPAON_GPIO1_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio1_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio1_opt_clks),
-};
-
-/* gpio2 */
-static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio2_dbclk" },
-};
-
-static struct omap_hwmod omap54xx_gpio2_hwmod = {
-       .name           = "gpio2",
-       .class          = &omap54xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4_root_clk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO2_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_GPIO2_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio2_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio2_opt_clks),
-};
-
-/* gpio3 */
-static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio3_dbclk" },
-};
-
-static struct omap_hwmod omap54xx_gpio3_hwmod = {
-       .name           = "gpio3",
-       .class          = &omap54xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4_root_clk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO3_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_GPIO3_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio3_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio3_opt_clks),
-};
-
-/* gpio4 */
-static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio4_dbclk" },
-};
-
-static struct omap_hwmod omap54xx_gpio4_hwmod = {
-       .name           = "gpio4",
-       .class          = &omap54xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4_root_clk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO4_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_GPIO4_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio4_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio4_opt_clks),
-};
-
-/* gpio5 */
-static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio5_dbclk" },
-};
-
-static struct omap_hwmod omap54xx_gpio5_hwmod = {
-       .name           = "gpio5",
-       .class          = &omap54xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4_root_clk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO5_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_GPIO5_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio5_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio5_opt_clks),
-};
-
-/* gpio6 */
-static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio6_dbclk" },
-};
-
-static struct omap_hwmod omap54xx_gpio6_hwmod = {
-       .name           = "gpio6",
-       .class          = &omap54xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4_root_clk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO6_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_GPIO6_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio6_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio6_opt_clks),
-};
-
-/* gpio7 */
-static struct omap_hwmod_opt_clk gpio7_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio7_dbclk" },
-};
-
-static struct omap_hwmod omap54xx_gpio7_hwmod = {
-       .name           = "gpio7",
-       .class          = &omap54xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4_root_clk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO7_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_GPIO7_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio7_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio7_opt_clks),
-};
-
-/* gpio8 */
-static struct omap_hwmod_opt_clk gpio8_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio8_dbclk" },
-};
-
-static struct omap_hwmod omap54xx_gpio8_hwmod = {
-       .name           = "gpio8",
-       .class          = &omap54xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l4_root_clk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO8_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_GPIO8_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio8_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio8_opt_clks),
-};
-
-/*
- * 'i2c' class
- * multimaster high-speed i2c controller
- */
-
-static struct omap_hwmod_class_sysconfig omap54xx_i2c_sysc = {
-       .rev_offs       = 0,
-       .sysc_offs      = 0x0010,
-       .syss_offs      = 0x0090,
-       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
-                          SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-                          SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap54xx_i2c_hwmod_class = {
-       .name   = "i2c",
-       .sysc   = &omap54xx_i2c_sysc,
-       .reset  = &omap_i2c_reset,
-       .rev    = OMAP_I2C_IP_VERSION_2,
-};
-
-/* i2c1 */
-static struct omap_hwmod omap54xx_i2c1_hwmod = {
-       .name           = "i2c1",
-       .class          = &omap54xx_i2c_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_I2C1_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_I2C1_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* i2c2 */
-static struct omap_hwmod omap54xx_i2c2_hwmod = {
-       .name           = "i2c2",
-       .class          = &omap54xx_i2c_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_I2C2_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_I2C2_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* i2c3 */
-static struct omap_hwmod omap54xx_i2c3_hwmod = {
-       .name           = "i2c3",
-       .class          = &omap54xx_i2c_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_I2C3_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_I2C3_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* i2c4 */
-static struct omap_hwmod omap54xx_i2c4_hwmod = {
-       .name           = "i2c4",
-       .class          = &omap54xx_i2c_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_I2C4_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_I2C4_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* i2c5 */
-static struct omap_hwmod omap54xx_i2c5_hwmod = {
-       .name           = "i2c5",
-       .class          = &omap54xx_i2c_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_I2C5_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_I2C5_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
 /*
  * 'kbd' class
  * keyboard controller
@@ -1184,115 +879,6 @@ static struct omap_hwmod omap54xx_mcspi4_hwmod = {
        },
 };
 
-/*
- * 'mmc' class
- * multimedia card high-speed/sd/sdio (mmc/sd/sdio) host controller
- */
-
-static struct omap_hwmod_class_sysconfig omap54xx_mmc_sysc = {
-       .rev_offs       = 0x0000,
-       .sysc_offs      = 0x0010,
-       .sysc_flags     = (SYSC_HAS_EMUFREE | SYSC_HAS_MIDLEMODE |
-                          SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
-                          SYSC_HAS_SOFTRESET),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
-                          MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type2,
-};
-
-static struct omap_hwmod_class omap54xx_mmc_hwmod_class = {
-       .name   = "mmc",
-       .sysc   = &omap54xx_mmc_sysc,
-};
-
-/* mmc1 */
-static struct omap_hwmod_opt_clk mmc1_opt_clks[] = {
-       { .role = "32khz_clk", .clk = "mmc1_32khz_clk" },
-};
-
-/* mmc1 dev_attr */
-static struct omap_hsmmc_dev_attr mmc1_dev_attr = {
-       .flags  = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
-};
-
-static struct omap_hwmod omap54xx_mmc1_hwmod = {
-       .name           = "mmc1",
-       .class          = &omap54xx_mmc_hwmod_class,
-       .clkdm_name     = "l3init_clkdm",
-       .main_clk       = "mmc1_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L3INIT_MMC1_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L3INIT_MMC1_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-       .opt_clks       = mmc1_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(mmc1_opt_clks),
-       .dev_attr       = &mmc1_dev_attr,
-};
-
-/* mmc2 */
-static struct omap_hwmod omap54xx_mmc2_hwmod = {
-       .name           = "mmc2",
-       .class          = &omap54xx_mmc_hwmod_class,
-       .clkdm_name     = "l3init_clkdm",
-       .main_clk       = "mmc2_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L3INIT_MMC2_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L3INIT_MMC2_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* mmc3 */
-static struct omap_hwmod omap54xx_mmc3_hwmod = {
-       .name           = "mmc3",
-       .class          = &omap54xx_mmc_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_MMC3_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_MMC3_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* mmc4 */
-static struct omap_hwmod omap54xx_mmc4_hwmod = {
-       .name           = "mmc4",
-       .class          = &omap54xx_mmc_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_MMC4_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_MMC4_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* mmc5 */
-static struct omap_hwmod omap54xx_mmc5_hwmod = {
-       .name           = "mmc5",
-       .class          = &omap54xx_mmc_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_MMC5_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_MMC5_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
 /*
  * 'mmu' class
  * The memory management unit performs virtual to physical address translation
@@ -1657,124 +1243,6 @@ static struct omap_hwmod omap54xx_timer11_hwmod = {
        },
 };
 
-/*
- * 'uart' class
- * universal asynchronous receiver/transmitter (uart)
- */
-
-static struct omap_hwmod_class_sysconfig omap54xx_uart_sysc = {
-       .rev_offs       = 0x0050,
-       .sysc_offs      = 0x0054,
-       .syss_offs      = 0x0058,
-       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
-                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-                          SYSS_HAS_RESET_STATUS),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap54xx_uart_hwmod_class = {
-       .name   = "uart",
-       .sysc   = &omap54xx_uart_sysc,
-};
-
-/* uart1 */
-static struct omap_hwmod omap54xx_uart1_hwmod = {
-       .name           = "uart1",
-       .class          = &omap54xx_uart_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_UART1_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_UART1_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart2 */
-static struct omap_hwmod omap54xx_uart2_hwmod = {
-       .name           = "uart2",
-       .class          = &omap54xx_uart_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_UART2_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_UART2_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart3 */
-static struct omap_hwmod omap54xx_uart3_hwmod = {
-       .name           = "uart3",
-       .class          = &omap54xx_uart_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = DEBUG_OMAP4UART3_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_UART3_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_UART3_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart4 */
-static struct omap_hwmod omap54xx_uart4_hwmod = {
-       .name           = "uart4",
-       .class          = &omap54xx_uart_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = DEBUG_OMAP4UART4_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_UART4_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_UART4_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart5 */
-static struct omap_hwmod omap54xx_uart5_hwmod = {
-       .name           = "uart5",
-       .class          = &omap54xx_uart_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_UART5_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_UART5_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart6 */
-static struct omap_hwmod omap54xx_uart6_hwmod = {
-       .name           = "uart6",
-       .class          = &omap54xx_uart_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .main_clk       = "func_48m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = OMAP54XX_CM_L4PER_UART6_CLKCTRL_OFFSET,
-                       .context_offs = OMAP54XX_RM_L4PER_UART6_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
 /*
  * 'usb_host_hs' class
  * high-speed multi-port usb host controller
@@ -2274,110 +1742,6 @@ static struct omap_hwmod_ocp_if omap54xx_mpu__emif2 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_wkup -> gpio1 */
-static struct omap_hwmod_ocp_if omap54xx_l4_wkup__gpio1 = {
-       .master         = &omap54xx_l4_wkup_hwmod,
-       .slave          = &omap54xx_gpio1_hwmod,
-       .clk            = "wkupaon_iclk_mux",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio2 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__gpio2 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_gpio2_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio3 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__gpio3 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_gpio3_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio4 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__gpio4 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_gpio4_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio5 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__gpio5 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_gpio5_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio6 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__gpio6 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_gpio6_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio7 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__gpio7 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_gpio7_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> gpio8 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__gpio8 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_gpio8_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> i2c1 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__i2c1 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_i2c1_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> i2c2 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__i2c2 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_i2c2_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> i2c3 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__i2c3 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_i2c3_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> i2c4 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__i2c4 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_i2c4_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> i2c5 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__i2c5 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_i2c5_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l4_wkup -> kbd */
 static struct omap_hwmod_ocp_if omap54xx_l4_wkup__kbd = {
        .master         = &omap54xx_l4_wkup_hwmod,
@@ -2458,46 +1822,6 @@ static struct omap_hwmod_ocp_if omap54xx_l4_per__mcspi4 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_per -> mmc1 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__mmc1 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_mmc1_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> mmc2 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__mmc2 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_mmc2_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> mmc3 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__mmc3 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_mmc3_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> mmc4 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__mmc4 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_mmc4_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> mmc5 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__mmc5 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_mmc5_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l4_cfg -> mpu */
 static struct omap_hwmod_ocp_if omap54xx_l4_cfg__mpu = {
        .master         = &omap54xx_l4_cfg_hwmod,
@@ -2610,54 +1934,6 @@ static struct omap_hwmod_ocp_if omap54xx_l4_per__timer11 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_per -> uart1 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__uart1 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_uart1_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> uart2 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__uart2 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_uart2_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> uart3 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__uart3 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_uart3_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> uart4 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__uart4 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_uart4_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> uart5 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__uart5 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_uart5_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per -> uart6 */
-static struct omap_hwmod_ocp_if omap54xx_l4_per__uart6 = {
-       .master         = &omap54xx_l4_per_hwmod,
-       .slave          = &omap54xx_uart6_hwmod,
-       .clk            = "l4_root_clk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l4_cfg -> usb_host_hs */
 static struct omap_hwmod_ocp_if omap54xx_l4_cfg__usb_host_hs = {
        .master         = &omap54xx_l4_cfg_hwmod,
@@ -2719,19 +1995,6 @@ static struct omap_hwmod_ocp_if *omap54xx_hwmod_ocp_ifs[] __initdata = {
        &omap54xx_l3_main_2__dss_rfbi,
        &omap54xx_mpu__emif1,
        &omap54xx_mpu__emif2,
-       &omap54xx_l4_wkup__gpio1,
-       &omap54xx_l4_per__gpio2,
-       &omap54xx_l4_per__gpio3,
-       &omap54xx_l4_per__gpio4,
-       &omap54xx_l4_per__gpio5,
-       &omap54xx_l4_per__gpio6,
-       &omap54xx_l4_per__gpio7,
-       &omap54xx_l4_per__gpio8,
-       &omap54xx_l4_per__i2c1,
-       &omap54xx_l4_per__i2c2,
-       &omap54xx_l4_per__i2c3,
-       &omap54xx_l4_per__i2c4,
-       &omap54xx_l4_per__i2c5,
        &omap54xx_l3_main_2__mmu_ipu,
        &omap54xx_l4_wkup__kbd,
        &omap54xx_l4_cfg__mailbox,
@@ -2743,11 +2006,6 @@ static struct omap_hwmod_ocp_if *omap54xx_hwmod_ocp_ifs[] __initdata = {
        &omap54xx_l4_per__mcspi2,
        &omap54xx_l4_per__mcspi3,
        &omap54xx_l4_per__mcspi4,
-       &omap54xx_l4_per__mmc1,
-       &omap54xx_l4_per__mmc2,
-       &omap54xx_l4_per__mmc3,
-       &omap54xx_l4_per__mmc4,
-       &omap54xx_l4_per__mmc5,
        &omap54xx_l4_cfg__mpu,
        &omap54xx_l4_cfg__spinlock,
        &omap54xx_l4_cfg__ocp2scp1,
@@ -2762,12 +2020,6 @@ static struct omap_hwmod_ocp_if *omap54xx_hwmod_ocp_ifs[] __initdata = {
        &omap54xx_l4_per__timer9,
        &omap54xx_l4_per__timer10,
        &omap54xx_l4_per__timer11,
-       &omap54xx_l4_per__uart1,
-       &omap54xx_l4_per__uart2,
-       &omap54xx_l4_per__uart3,
-       &omap54xx_l4_per__uart4,
-       &omap54xx_l4_per__uart5,
-       &omap54xx_l4_per__uart6,
        &omap54xx_l4_cfg__usb_host_hs,
        &omap54xx_l4_cfg__usb_tll_hs,
        &omap54xx_l4_cfg__usb_otg_ss,
index e6c7061..7e85bd2 100644 (file)
@@ -18,9 +18,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/platform_data/hsmmc-omap.h>
 #include <linux/power/smartreflex.h>
-#include <linux/platform_data/i2c-omap.h>
 
 #include <linux/omap-dma.h>
 
@@ -29,7 +27,6 @@
 #include "cm1_7xx.h"
 #include "cm2_7xx.h"
 #include "prm7xx.h"
-#include "i2c.h"
 #include "wd_timer.h"
 #include "soc.h"
 
@@ -693,7 +690,6 @@ static struct omap_hwmod_class_sysconfig dra7xx_aes_sysc = {
 static struct omap_hwmod_class dra7xx_aes_hwmod_class = {
        .name   = "aes",
        .sysc   = &dra7xx_aes_sysc,
-       .rev    = 2,
 };
 
 /* AES1 */
@@ -737,7 +733,6 @@ static struct omap_hwmod_class_sysconfig dra7xx_sha0_sysc = {
 static struct omap_hwmod_class dra7xx_sha0_hwmod_class = {
        .name           = "sham",
        .sysc           = &dra7xx_sha0_sysc,
-       .rev            = 2,
 };
 
 struct omap_hwmod dra7xx_sha0_hwmod = {
@@ -791,205 +786,6 @@ static struct omap_hwmod dra7xx_elm_hwmod = {
        },
 };
 
-/*
- * 'gpio' class
- *
- */
-
-static struct omap_hwmod_class_sysconfig dra7xx_gpio_sysc = {
-       .rev_offs       = 0x0000,
-       .sysc_offs      = 0x0010,
-       .syss_offs      = 0x0114,
-       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
-                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-                          SYSS_HAS_RESET_STATUS),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class dra7xx_gpio_hwmod_class = {
-       .name   = "gpio",
-       .sysc   = &dra7xx_gpio_sysc,
-       .rev    = 2,
-};
-
-/* gpio1 */
-static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio1_dbclk" },
-};
-
-static struct omap_hwmod dra7xx_gpio1_hwmod = {
-       .name           = "gpio1",
-       .class          = &dra7xx_gpio_hwmod_class,
-       .clkdm_name     = "wkupaon_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "wkupaon_iclk_mux",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_WKUPAON_GPIO1_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_WKUPAON_GPIO1_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio1_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio1_opt_clks),
-};
-
-/* gpio2 */
-static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio2_dbclk" },
-};
-
-static struct omap_hwmod dra7xx_gpio2_hwmod = {
-       .name           = "gpio2",
-       .class          = &dra7xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l3_iclk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_GPIO2_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_GPIO2_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio2_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio2_opt_clks),
-};
-
-/* gpio3 */
-static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio3_dbclk" },
-};
-
-static struct omap_hwmod dra7xx_gpio3_hwmod = {
-       .name           = "gpio3",
-       .class          = &dra7xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l3_iclk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_GPIO3_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_GPIO3_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio3_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio3_opt_clks),
-};
-
-/* gpio4 */
-static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio4_dbclk" },
-};
-
-static struct omap_hwmod dra7xx_gpio4_hwmod = {
-       .name           = "gpio4",
-       .class          = &dra7xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l3_iclk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_GPIO4_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_GPIO4_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio4_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio4_opt_clks),
-};
-
-/* gpio5 */
-static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio5_dbclk" },
-};
-
-static struct omap_hwmod dra7xx_gpio5_hwmod = {
-       .name           = "gpio5",
-       .class          = &dra7xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l3_iclk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_GPIO5_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_GPIO5_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio5_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio5_opt_clks),
-};
-
-/* gpio6 */
-static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio6_dbclk" },
-};
-
-static struct omap_hwmod dra7xx_gpio6_hwmod = {
-       .name           = "gpio6",
-       .class          = &dra7xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l3_iclk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_GPIO6_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_GPIO6_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio6_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio6_opt_clks),
-};
-
-/* gpio7 */
-static struct omap_hwmod_opt_clk gpio7_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio7_dbclk" },
-};
-
-static struct omap_hwmod dra7xx_gpio7_hwmod = {
-       .name           = "gpio7",
-       .class          = &dra7xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l3_iclk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_GPIO7_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_GPIO7_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio7_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio7_opt_clks),
-};
-
-/* gpio8 */
-static struct omap_hwmod_opt_clk gpio8_opt_clks[] = {
-       { .role = "dbclk", .clk = "gpio8_dbclk" },
-};
-
-static struct omap_hwmod dra7xx_gpio8_hwmod = {
-       .name           = "gpio8",
-       .class          = &dra7xx_gpio_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-       .main_clk       = "l3_iclk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_GPIO8_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_GPIO8_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_HWCTRL,
-               },
-       },
-       .opt_clks       = gpio8_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(gpio8_opt_clks),
-};
-
 /*
  * 'gpmc' class
  *
@@ -1064,110 +860,6 @@ static struct omap_hwmod dra7xx_hdq1w_hwmod = {
        },
 };
 
-/*
- * 'i2c' class
- *
- */
-
-static struct omap_hwmod_class_sysconfig dra7xx_i2c_sysc = {
-       .rev_offs       = 0,
-       .sysc_offs      = 0x0010,
-       .syss_offs      = 0x0090,
-       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
-                          SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-                          SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class dra7xx_i2c_hwmod_class = {
-       .name   = "i2c",
-       .sysc   = &dra7xx_i2c_sysc,
-       .reset  = &omap_i2c_reset,
-       .rev    = OMAP_I2C_IP_VERSION_2,
-};
-
-/* i2c1 */
-static struct omap_hwmod dra7xx_i2c1_hwmod = {
-       .name           = "i2c1",
-       .class          = &dra7xx_i2c_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_I2C1_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_I2C1_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* i2c2 */
-static struct omap_hwmod dra7xx_i2c2_hwmod = {
-       .name           = "i2c2",
-       .class          = &dra7xx_i2c_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_I2C2_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_I2C2_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* i2c3 */
-static struct omap_hwmod dra7xx_i2c3_hwmod = {
-       .name           = "i2c3",
-       .class          = &dra7xx_i2c_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_I2C3_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_I2C3_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* i2c4 */
-static struct omap_hwmod dra7xx_i2c4_hwmod = {
-       .name           = "i2c4",
-       .class          = &dra7xx_i2c_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_I2C4_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_I2C4_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* i2c5 */
-static struct omap_hwmod dra7xx_i2c5_hwmod = {
-       .name           = "i2c5",
-       .class          = &dra7xx_i2c_hwmod_class,
-       .clkdm_name     = "ipu_clkdm",
-       .flags          = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-       .main_clk       = "func_96m_fclk",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_IPU_I2C5_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_IPU_I2C5_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
 /*
  * 'mailbox' class
  *
@@ -1631,118 +1323,6 @@ static struct omap_hwmod dra7xx_mcasp8_hwmod = {
        .opt_clks_cnt   = ARRAY_SIZE(mcasp8_opt_clks),
 };
 
-/*
- * 'mmc' class
- *
- */
-
-static struct omap_hwmod_class_sysconfig dra7xx_mmc_sysc = {
-       .rev_offs       = 0x0000,
-       .sysc_offs      = 0x0010,
-       .sysc_flags     = (SYSC_HAS_EMUFREE | SYSC_HAS_MIDLEMODE |
-                          SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
-                          SYSC_HAS_SOFTRESET),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
-                          MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type2,
-};
-
-static struct omap_hwmod_class dra7xx_mmc_hwmod_class = {
-       .name   = "mmc",
-       .sysc   = &dra7xx_mmc_sysc,
-};
-
-/* mmc1 */
-static struct omap_hwmod_opt_clk mmc1_opt_clks[] = {
-       { .role = "clk32k", .clk = "mmc1_clk32k" },
-};
-
-/* mmc1 dev_attr */
-static struct omap_hsmmc_dev_attr mmc1_dev_attr = {
-       .flags  = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
-};
-
-static struct omap_hwmod dra7xx_mmc1_hwmod = {
-       .name           = "mmc1",
-       .class          = &dra7xx_mmc_hwmod_class,
-       .clkdm_name     = "l3init_clkdm",
-       .main_clk       = "mmc1_fclk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L3INIT_MMC1_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L3INIT_MMC1_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-       .opt_clks       = mmc1_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(mmc1_opt_clks),
-       .dev_attr       = &mmc1_dev_attr,
-};
-
-/* mmc2 */
-static struct omap_hwmod_opt_clk mmc2_opt_clks[] = {
-       { .role = "clk32k", .clk = "mmc2_clk32k" },
-};
-
-static struct omap_hwmod dra7xx_mmc2_hwmod = {
-       .name           = "mmc2",
-       .class          = &dra7xx_mmc_hwmod_class,
-       .clkdm_name     = "l3init_clkdm",
-       .main_clk       = "mmc2_fclk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L3INIT_MMC2_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L3INIT_MMC2_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-       .opt_clks       = mmc2_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(mmc2_opt_clks),
-};
-
-/* mmc3 */
-static struct omap_hwmod_opt_clk mmc3_opt_clks[] = {
-       { .role = "clk32k", .clk = "mmc3_clk32k" },
-};
-
-static struct omap_hwmod dra7xx_mmc3_hwmod = {
-       .name           = "mmc3",
-       .class          = &dra7xx_mmc_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .main_clk       = "mmc3_gfclk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_MMC3_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_MMC3_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-       .opt_clks       = mmc3_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(mmc3_opt_clks),
-};
-
-/* mmc4 */
-static struct omap_hwmod_opt_clk mmc4_opt_clks[] = {
-       { .role = "clk32k", .clk = "mmc4_clk32k" },
-};
-
-static struct omap_hwmod dra7xx_mmc4_hwmod = {
-       .name           = "mmc4",
-       .class          = &dra7xx_mmc_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .main_clk       = "mmc4_gfclk_div",
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_MMC4_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_MMC4_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-       .opt_clks       = mmc4_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(mmc4_opt_clks),
-};
-
 /*
  * 'mpu' class
  *
@@ -1832,7 +1412,7 @@ static struct omap_hwmod dra7xx_ocp2scp3_hwmod = {
  * We use a PCIeSS HWMOD class specific reset handler to deassert the hardreset
  * lines after asserting them.
  */
-static int dra7xx_pciess_reset(struct omap_hwmod *oh)
+int dra7xx_pciess_reset(struct omap_hwmod *oh)
 {
        int i;
 
@@ -2019,7 +1599,6 @@ static struct omap_hwmod_class_sysconfig dra7xx_smartreflex_sysc = {
 static struct omap_hwmod_class dra7xx_smartreflex_hwmod_class = {
        .name   = "smartreflex",
        .sysc   = &dra7xx_smartreflex_sysc,
-       .rev    = 2,
 };
 
 /* smartreflex_core */
@@ -2375,188 +1954,6 @@ static struct omap_hwmod dra7xx_timer16_hwmod = {
        },
 };
 
-/*
- * 'uart' class
- *
- */
-
-static struct omap_hwmod_class_sysconfig dra7xx_uart_sysc = {
-       .rev_offs       = 0x0050,
-       .sysc_offs      = 0x0054,
-       .syss_offs      = 0x0058,
-       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
-                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-                          SYSS_HAS_RESET_STATUS),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class dra7xx_uart_hwmod_class = {
-       .name   = "uart",
-       .sysc   = &dra7xx_uart_sysc,
-};
-
-/* uart1 */
-static struct omap_hwmod dra7xx_uart1_hwmod = {
-       .name           = "uart1",
-       .class          = &dra7xx_uart_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .main_clk       = "uart1_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT | DEBUG_OMAP2UART1_FLAGS,
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_UART1_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_UART1_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart2 */
-static struct omap_hwmod dra7xx_uart2_hwmod = {
-       .name           = "uart2",
-       .class          = &dra7xx_uart_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .main_clk       = "uart2_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_UART2_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_UART2_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart3 */
-static struct omap_hwmod dra7xx_uart3_hwmod = {
-       .name           = "uart3",
-       .class          = &dra7xx_uart_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .main_clk       = "uart3_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT | DEBUG_OMAP4UART3_FLAGS,
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_UART3_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_UART3_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart4 */
-static struct omap_hwmod dra7xx_uart4_hwmod = {
-       .name           = "uart4",
-       .class          = &dra7xx_uart_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .main_clk       = "uart4_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT | DEBUG_OMAP4UART4_FLAGS,
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_UART4_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_UART4_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart5 */
-static struct omap_hwmod dra7xx_uart5_hwmod = {
-       .name           = "uart5",
-       .class          = &dra7xx_uart_hwmod_class,
-       .clkdm_name     = "l4per_clkdm",
-       .main_clk       = "uart5_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER_UART5_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER_UART5_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart6 */
-static struct omap_hwmod dra7xx_uart6_hwmod = {
-       .name           = "uart6",
-       .class          = &dra7xx_uart_hwmod_class,
-       .clkdm_name     = "ipu_clkdm",
-       .main_clk       = "uart6_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_IPU_UART6_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_IPU_UART6_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart7 */
-static struct omap_hwmod dra7xx_uart7_hwmod = {
-       .name           = "uart7",
-       .class          = &dra7xx_uart_hwmod_class,
-       .clkdm_name     = "l4per2_clkdm",
-       .main_clk       = "uart7_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER2_UART7_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER2_UART7_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart8 */
-static struct omap_hwmod dra7xx_uart8_hwmod = {
-       .name           = "uart8",
-       .class          = &dra7xx_uart_hwmod_class,
-       .clkdm_name     = "l4per2_clkdm",
-       .main_clk       = "uart8_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER2_UART8_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER2_UART8_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart9 */
-static struct omap_hwmod dra7xx_uart9_hwmod = {
-       .name           = "uart9",
-       .class          = &dra7xx_uart_hwmod_class,
-       .clkdm_name     = "l4per2_clkdm",
-       .main_clk       = "uart9_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_L4PER2_UART9_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_L4PER2_UART9_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
-/* uart10 */
-static struct omap_hwmod dra7xx_uart10_hwmod = {
-       .name           = "uart10",
-       .class          = &dra7xx_uart_hwmod_class,
-       .clkdm_name     = "wkupaon_clkdm",
-       .main_clk       = "uart10_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
-       .prcm = {
-               .omap4 = {
-                       .clkctrl_offs = DRA7XX_CM_WKUPAON_UART10_CLKCTRL_OFFSET,
-                       .context_offs = DRA7XX_RM_WKUPAON_UART10_CONTEXT_OFFSET,
-                       .modulemode   = MODULEMODE_SWCTRL,
-               },
-       },
-};
-
 /* DES (the 'P' (public) device) */
 static struct omap_hwmod_class_sysconfig dra7xx_des_sysc = {
        .rev_offs       = 0x0030,
@@ -3113,70 +2510,6 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per1__elm = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_wkup -> gpio1 */
-static struct omap_hwmod_ocp_if dra7xx_l4_wkup__gpio1 = {
-       .master         = &dra7xx_l4_wkup_hwmod,
-       .slave          = &dra7xx_gpio1_hwmod,
-       .clk            = "wkupaon_iclk_mux",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> gpio2 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__gpio2 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_gpio2_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> gpio3 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__gpio3 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_gpio3_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> gpio4 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__gpio4 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_gpio4_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> gpio5 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__gpio5 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_gpio5_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> gpio6 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__gpio6 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_gpio6_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> gpio7 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__gpio7 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_gpio7_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> gpio8 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__gpio8 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_gpio8_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l3_main_1 -> gpmc */
 static struct omap_hwmod_ocp_if dra7xx_l3_main_1__gpmc = {
        .master         = &dra7xx_l3_main_1_hwmod,
@@ -3193,46 +2526,6 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per1__hdq1w = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_per1 -> i2c1 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__i2c1 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_i2c1_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> i2c2 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__i2c2 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_i2c2_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> i2c3 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__i2c3 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_i2c3_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> i2c4 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__i2c4 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_i2c4_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> i2c5 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__i2c5 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_i2c5_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l4_cfg -> mailbox1 */
 static struct omap_hwmod_ocp_if dra7xx_l4_cfg__mailbox1 = {
        .master         = &dra7xx_l4_cfg_hwmod,
@@ -3369,38 +2662,6 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per1__mcspi4 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_per1 -> mmc1 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__mmc1 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_mmc1_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> mmc2 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__mmc2 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_mmc2_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> mmc3 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__mmc3 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_mmc3_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> mmc4 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__mmc4 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_mmc4_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l4_cfg -> mpu */
 static struct omap_hwmod_ocp_if dra7xx_l4_cfg__mpu = {
        .master         = &dra7xx_l4_cfg_hwmod,
@@ -3633,62 +2894,6 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per3__timer16 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_per1 -> uart1 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__uart1 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_uart1_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> uart2 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__uart2 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_uart2_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> uart3 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__uart3 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_uart3_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> uart4 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__uart4 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_uart4_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> uart5 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__uart5 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_uart5_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per1 -> uart6 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per1__uart6 = {
-       .master         = &dra7xx_l4_per1_hwmod,
-       .slave          = &dra7xx_uart6_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per2 -> uart7 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per2__uart7 = {
-       .master         = &dra7xx_l4_per2_hwmod,
-       .slave          = &dra7xx_uart7_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l4_per1 -> des */
 static struct omap_hwmod_ocp_if dra7xx_l4_per1__des = {
        .master         = &dra7xx_l4_per1_hwmod,
@@ -3697,30 +2902,6 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per1__des = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_per2 -> uart8 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per2__uart8 = {
-       .master         = &dra7xx_l4_per2_hwmod,
-       .slave          = &dra7xx_uart8_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_per2 -> uart9 */
-static struct omap_hwmod_ocp_if dra7xx_l4_per2__uart9 = {
-       .master         = &dra7xx_l4_per2_hwmod,
-       .slave          = &dra7xx_uart9_hwmod,
-       .clk            = "l3_iclk_div",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4_wkup -> uart10 */
-static struct omap_hwmod_ocp_if dra7xx_l4_wkup__uart10 = {
-       .master         = &dra7xx_l4_wkup_hwmod,
-       .slave          = &dra7xx_uart10_hwmod,
-       .clk            = "wkupaon_iclk_mux",
-       .user           = OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l4_per1 -> rng */
 static struct omap_hwmod_ocp_if dra7xx_l4_per1__rng = {
        .master         = &dra7xx_l4_per1_hwmod,
@@ -3866,21 +3047,8 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
        &dra7xx_l3_main_1__aes2,
        &dra7xx_l3_main_1__sha0,
        &dra7xx_l4_per1__elm,
-       &dra7xx_l4_wkup__gpio1,
-       &dra7xx_l4_per1__gpio2,
-       &dra7xx_l4_per1__gpio3,
-       &dra7xx_l4_per1__gpio4,
-       &dra7xx_l4_per1__gpio5,
-       &dra7xx_l4_per1__gpio6,
-       &dra7xx_l4_per1__gpio7,
-       &dra7xx_l4_per1__gpio8,
        &dra7xx_l3_main_1__gpmc,
        &dra7xx_l4_per1__hdq1w,
-       &dra7xx_l4_per1__i2c1,
-       &dra7xx_l4_per1__i2c2,
-       &dra7xx_l4_per1__i2c3,
-       &dra7xx_l4_per1__i2c4,
-       &dra7xx_l4_per1__i2c5,
        &dra7xx_l4_cfg__mailbox1,
        &dra7xx_l4_per3__mailbox2,
        &dra7xx_l4_per3__mailbox3,
@@ -3898,10 +3066,6 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
        &dra7xx_l4_per1__mcspi2,
        &dra7xx_l4_per1__mcspi3,
        &dra7xx_l4_per1__mcspi4,
-       &dra7xx_l4_per1__mmc1,
-       &dra7xx_l4_per1__mmc2,
-       &dra7xx_l4_per1__mmc3,
-       &dra7xx_l4_per1__mmc4,
        &dra7xx_l4_cfg__mpu,
        &dra7xx_l4_cfg__ocp2scp1,
        &dra7xx_l4_cfg__ocp2scp3,
@@ -3929,16 +3093,6 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
        &dra7xx_l4_per3__timer14,
        &dra7xx_l4_per3__timer15,
        &dra7xx_l4_per3__timer16,
-       &dra7xx_l4_per1__uart1,
-       &dra7xx_l4_per1__uart2,
-       &dra7xx_l4_per1__uart3,
-       &dra7xx_l4_per1__uart4,
-       &dra7xx_l4_per1__uart5,
-       &dra7xx_l4_per1__uart6,
-       &dra7xx_l4_per2__uart7,
-       &dra7xx_l4_per2__uart8,
-       &dra7xx_l4_per2__uart9,
-       &dra7xx_l4_wkup__uart10,
        &dra7xx_l4_per1__des,
        &dra7xx_l4_per3__usb_otg_ss1,
        &dra7xx_l4_per3__usb_otg_ss2,
index debcd88..83230d9 100644 (file)
@@ -484,7 +484,6 @@ static struct omap_hwmod_class_sysconfig dm81xx_gpio_sysc = {
 static struct omap_hwmod_class dm81xx_gpio_hwmod_class = {
        .name   = "gpio",
        .sysc   = &dm81xx_gpio_sysc,
-       .rev    = 2,
 };
 
 static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
index 724cf57..f11442e 100644 (file)
 #include <asm/suspend.h>
 #include <linux/errno.h>
 #include <linux/platform_data/pm33xx.h>
+#include <linux/clk.h>
+#include <linux/platform_data/gpio-omap.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/wkup_m3_ipc.h>
+#include <linux/of.h>
+#include <linux/rtc.h>
 
 #include "cm33xx.h"
 #include "common.h"
@@ -38,6 +44,29 @@ static int am43xx_map_scu(void)
        return 0;
 }
 
+static int am33xx_check_off_mode_enable(void)
+{
+       if (enable_off_mode)
+               pr_warn("WARNING: This platform does not support off-mode, entering DeepSleep suspend.\n");
+
+       /* off mode not supported on am335x so return 0 always */
+       return 0;
+}
+
+static int am43xx_check_off_mode_enable(void)
+{
+       /*
+        * Check for am437x-gp-evm which has the right Hardware design to
+        * support this mode reliably.
+        */
+       if (of_machine_is_compatible("ti,am437x-gp-evm") && enable_off_mode)
+               return enable_off_mode;
+       else if (enable_off_mode)
+               pr_warn("WARNING: This platform does not support off-mode, entering DeepSleep suspend.\n");
+
+       return 0;
+}
+
 static int amx3_common_init(void)
 {
        gfx_pwrdm = pwrdm_lookup("gfx_pwrdm");
@@ -51,10 +80,12 @@ static int amx3_common_init(void)
 
        /* CEFUSE domain can be turned off post bootup */
        cefuse_pwrdm = pwrdm_lookup("cefuse_pwrdm");
-       if (cefuse_pwrdm)
-               omap_set_pwrdm_state(cefuse_pwrdm, PWRDM_POWER_OFF);
-       else
+       if (!cefuse_pwrdm)
                pr_err("PM: Failed to get cefuse_pwrdm\n");
+       else if (omap_type() != OMAP2_DEVICE_TYPE_GP)
+               pr_info("PM: Leaving EFUSE power domain active\n");
+       else
+               omap_set_pwrdm_state(cefuse_pwrdm, PWRDM_POWER_OFF);
 
        return 0;
 }
@@ -139,7 +170,9 @@ static int am43xx_suspend(unsigned int state, int (*fn)(unsigned long),
        scu_power_mode(scu_base, SCU_PM_POWEROFF);
        ret = cpu_suspend(args, fn);
        scu_power_mode(scu_base, SCU_PM_NORMAL);
-       amx3_post_suspend_common();
+
+       if (!am43xx_check_off_mode_enable())
+               amx3_post_suspend_common();
 
        return ret;
 }
@@ -161,10 +194,48 @@ void __iomem *am43xx_get_rtc_base_addr(void)
        return omap_hwmod_get_mpu_rt_va(rtc_oh);
 }
 
+static void am43xx_save_context(void)
+{
+}
+
+static void am33xx_save_context(void)
+{
+       omap_intc_save_context();
+}
+
+static void am33xx_restore_context(void)
+{
+       omap_intc_restore_context();
+}
+
+static void am43xx_restore_context(void)
+{
+       /*
+        * HACK: restore dpll_per_clkdcoldo register contents, to avoid
+        * breaking suspend-resume
+        */
+       writel_relaxed(0x0, AM33XX_L4_WK_IO_ADDRESS(0x44df2e14));
+}
+
+static void am43xx_prepare_rtc_suspend(void)
+{
+       omap_hwmod_enable(rtc_oh);
+}
+
+static void am43xx_prepare_rtc_resume(void)
+{
+       omap_hwmod_idle(rtc_oh);
+}
+
 static struct am33xx_pm_platform_data am33xx_ops = {
        .init = am33xx_suspend_init,
        .soc_suspend = am33xx_suspend,
        .get_sram_addrs = amx3_get_sram_addrs,
+       .save_context = am33xx_save_context,
+       .restore_context = am33xx_restore_context,
+       .prepare_rtc_suspend = am43xx_prepare_rtc_suspend,
+       .prepare_rtc_resume = am43xx_prepare_rtc_resume,
+       .check_off_mode_enable = am33xx_check_off_mode_enable,
        .get_rtc_base_addr = am43xx_get_rtc_base_addr,
 };
 
@@ -172,6 +243,11 @@ static struct am33xx_pm_platform_data am43xx_ops = {
        .init = am43xx_suspend_init,
        .soc_suspend = am43xx_suspend,
        .get_sram_addrs = amx3_get_sram_addrs,
+       .save_context = am43xx_save_context,
+       .restore_context = am43xx_restore_context,
+       .prepare_rtc_suspend = am43xx_prepare_rtc_suspend,
+       .prepare_rtc_resume = am43xx_prepare_rtc_resume,
+       .check_off_mode_enable = am43xx_check_off_mode_enable,
        .get_rtc_base_addr = am43xx_get_rtc_base_addr,
 };
 
index 5b9343b..0c10314 100644 (file)
@@ -368,6 +368,9 @@ wait_emif_enable1:
        mov     r1, #AM43XX_EMIF_POWEROFF_DISABLE
        str     r1, [r2, #0x0]
 
+       ldr     r1, [r9, #EMIF_PM_RUN_HW_LEVELING]
+       blx     r1
+
 #ifdef CONFIG_CACHE_L2X0
        ldr     r2, l2_cache_base
        ldr     r0, [r2, #L2X0_CTRL]
index 0854ed9..248f6d9 100644 (file)
@@ -119,7 +119,10 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
        }
 
        sr_data->name = oh->name;
-       sr_data->ip_type = oh->class->rev;
+       if (cpu_is_omap343x())
+               sr_data->ip_type = 1;
+       else
+               sr_data->ip_type = 2;
        sr_data->senn_mod = 0x1;
        sr_data->senp_mod = 0x1;
 
index c67f92b..7bcb411 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/serial_8250.h>
index ffe05c2..1607dea 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <linux/of.h>
index 4bcbd3d..1f24e02 100644 (file)
@@ -35,7 +35,7 @@
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index e68acdd..510625d 100644 (file)
@@ -24,7 +24,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach-types.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <mach/audio.h>
 #include "colibri.h"
index 6a5558d..2f635bd 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/interrupt.h>
 
 #include <asm/mach-types.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 
index 17067a3..ffcefe6 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/usb/gpio_vbus.h>
 
 #include <asm/mach-types.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 
index e31a591..0c88e4e 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/etherdevice.h>
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/system_info.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
index 4764acc..eb03283 100644 (file)
@@ -33,7 +33,7 @@
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index e9f401b..5c03c4f 100644 (file)
@@ -33,7 +33,7 @@
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index c1bd0d5..8259398 100644 (file)
@@ -39,7 +39,7 @@
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index d6e17d4..b3f8592 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index c76f1da..99a2ee4 100644 (file)
@@ -35,7 +35,7 @@
 #include <asm/memory.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index ab2f892..c4c25a2 100644 (file)
@@ -58,7 +58,7 @@
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/system_info.h>
 
 #include <asm/mach/arch.h>
index 51984a4..4675d92 100644 (file)
@@ -245,6 +245,7 @@ static int __init rockchip_smp_prepare_pmu(void)
        }
 
        pmu_base = of_iomap(node, 0);
+       of_node_put(node);
        if (!pmu_base) {
                pr_err("%s: could not map pmu registers\n", __func__);
                return -ENOMEM;
index 0592534..065b09e 100644 (file)
@@ -59,7 +59,7 @@ static inline u32 rk3288_l2_config(void)
        return l2ctlr;
 }
 
-static void rk3288_config_bootdata(void)
+static void __init rk3288_config_bootdata(void)
 {
        rkpm_bootdata_cpusp = rk3288_bootram_phy + (SZ_4K - 8);
        rkpm_bootdata_cpu_code = __pa_symbol(cpu_resume);
@@ -230,7 +230,7 @@ static void rk3288_suspend_finish(void)
                pr_err("%s: Suspend finish failed\n", __func__);
 }
 
-static int rk3288_suspend_init(struct device_node *np)
+static int __init rk3288_suspend_init(struct device_node *np)
 {
        struct device_node *sram_np;
        struct resource res;
index e41cabc..06ab03b 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/of_platform.h>
 #include <linux/irqchip.h>
 #include <linux/clk-provider.h>
index 1b29757..f28ac6c 100644 (file)
@@ -15,7 +15,7 @@ extern unsigned int s3c2410_modify_misccr(unsigned int clr, unsigned int chg);
 
 #endif /* __ASSEMBLY__ */
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <mach/map.h>
 
 #endif /* __ASM_ARCH_HARDWARE_H */
index 76c4855..937d0a8 100644 (file)
@@ -328,6 +328,8 @@ static const struct {
        int num_i2c_devs;
        const struct spi_board_info *spi_devs;
        int num_spi_devs;
+
+       struct gpiod_lookup_table *gpiod_table;
 } gf_mods[] = {
        { .id = 0x01, .rev = 0xff, .name = "1250-EV1 Springbank" },
        { .id = 0x02, .rev = 0xff, .name = "1251-EV1 Jura" },
@@ -362,13 +364,16 @@ static const struct {
          .i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs) },
        { .id = 0x3c, .rev = 0xff, .name = "1273-EV1 Longmorn" },
        { .id = 0x3d, .rev = 0xff, .name = "1277-EV1 Littlemill",
-         .i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs) },
+         .i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs),
+         .gpiod_table = &wm8994_gpiod_table },
        { .id = 0x3e, .rev = 0, .name = "WM5102-6271-EV1-CS127 Amrut",
          .spi_devs = wm5102_reva_spi_devs,
-         .num_spi_devs = ARRAY_SIZE(wm5102_reva_spi_devs) },
+         .num_spi_devs = ARRAY_SIZE(wm5102_reva_spi_devs),
+         .gpiod_table = &wm5102_reva_gpiod_table },
        { .id = 0x3e, .rev = -1, .name = "WM5102-6271-EV1-CS127 Amrut",
          .spi_devs = wm5102_spi_devs,
-         .num_spi_devs = ARRAY_SIZE(wm5102_spi_devs) },
+         .num_spi_devs = ARRAY_SIZE(wm5102_spi_devs),
+         .gpiod_table = &wm5102_gpiod_table },
        { .id = 0x3f, .rev = -1, .name = "WM2200-6271-CS90-M-REV1",
          .i2c_devs = wm2200_i2c, .num_i2c_devs = ARRAY_SIZE(wm2200_i2c) },
 };
@@ -408,6 +413,9 @@ static int wlf_gf_module_probe(struct i2c_client *i2c,
 
                spi_register_board_info(gf_mods[i].spi_devs,
                                        gf_mods[i].num_spi_devs);
+
+               if (gf_mods[i].gpiod_table)
+                       gpiod_add_lookup_table(gf_mods[i].gpiod_table);
        } else {
                dev_warn(&i2c->dev, "Unknown module ID 0x%x revision %d\n",
                         id, rev + 1);
index fa5cf47..3b19296 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 /*
  * Because of the wide memory address space between physical RAM banks on the
index eb60a71..a671e4c 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/sa1111.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <mach/hardware.h>
 #include <mach/assabet.h>
index 8c2a205..e84599d 100644 (file)
@@ -72,6 +72,7 @@ void __init rcar_gen2_pm_init(void)
        }
 
        error = of_address_to_resource(np, 0, &res);
+       of_node_put(np);
        if (error) {
                pr_err("Failed to get smp-sram address: %d\n", error);
                return;
index dc526ef..ee94925 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * R-Car Generation 2 da9063/da9210 regulator quirk
+ * R-Car Generation 2 da9063(L)/da9210 regulator quirk
  *
  * Certain Gen2 development boards have an da9063 and one or more da9210
  * regulators. All of these regulators have their interrupt request lines
@@ -65,6 +65,7 @@ static struct i2c_msg da9210_msg = {
 
 static const struct of_device_id rcar_gen2_quirk_match[] = {
        { .compatible = "dlg,da9063", .data = &da9063_msg },
+       { .compatible = "dlg,da9063l", .data = &da9063_msg },
        { .compatible = "dlg,da9210", .data = &da9210_msg },
        {},
 };
@@ -147,6 +148,7 @@ static int __init rcar_gen2_regulator_quirk(void)
 
        if (!of_machine_is_compatible("renesas,koelsch") &&
            !of_machine_is_compatible("renesas,lager") &&
+           !of_machine_is_compatible("renesas,porter") &&
            !of_machine_is_compatible("renesas,stout") &&
            !of_machine_is_compatible("renesas,gose"))
                return -ENODEV;
@@ -210,7 +212,7 @@ static int __init rcar_gen2_regulator_quirk(void)
                goto err_free;
        }
 
-       pr_info("IRQ2 is asserted, installing da9063/da9210 regulator quirk\n");
+       pr_info("IRQ2 is asserted, installing regulator quirk\n");
 
        bus_register_notifier(&i2c_bus_type, &regulator_quirk_nb);
        return 0;
index 713c068..651bdf4 100644 (file)
@@ -4,6 +4,7 @@ menuconfig ARCH_STM32
        select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7
        select ARM_GIC if ARCH_MULTI_V7
        select ARM_PSCI if ARCH_MULTI_V7
+       select ARM_AMBA
        select ARCH_HAS_RESET_CONTROLLER
        select CLKSRC_STM32
        select PINCTRL
@@ -18,22 +19,18 @@ if ARM_SINGLE_ARMV7M
 
 config MACH_STM32F429
        bool "STMicroelectronics STM32F429"
-       select ARM_AMBA
        default y
 
 config MACH_STM32F469
        bool "STMicroelectronics STM32F469"
-       select ARM_AMBA
        default y
 
 config MACH_STM32F746
        bool "STMicroelectronics STM32F746"
-       select ARM_AMBA
        default y
 
 config MACH_STM32F769
        bool "STMicroelectronics STM32F769"
-       select ARM_AMBA
        default y
 
 config MACH_STM32H743
index b4037b6..239084c 100644 (file)
@@ -89,6 +89,7 @@ static bool sunxi_core_is_cortex_a15(unsigned int core, unsigned int cluster)
 {
        struct device_node *node;
        int cpu = cluster * SUNXI_CPUS_PER_CLUSTER + core;
+       bool is_compatible;
 
        node = of_cpu_device_node_get(cpu);
 
@@ -107,7 +108,9 @@ static bool sunxi_core_is_cortex_a15(unsigned int core, unsigned int cluster)
                return false;
        }
 
-       return of_device_is_compatible(node, "arm,cortex-a15");
+       is_compatible = of_device_is_compatible(node, "arm,cortex-a15");
+       of_node_put(node);
+       return is_compatible;
 }
 
 static int sunxi_cpu_power_switch_set(unsigned int cpu, unsigned int cluster,
index 8fb5088..bdde9ef 100644 (file)
@@ -50,6 +50,7 @@ static void __init sun6i_smp_prepare_cpus(unsigned int max_cpus)
        }
 
        prcm_membase = of_iomap(node, 0);
+       of_node_put(node);
        if (!prcm_membase) {
                pr_err("Couldn't map A31 PRCM registers\n");
                return;
@@ -63,6 +64,7 @@ static void __init sun6i_smp_prepare_cpus(unsigned int max_cpus)
        }
 
        cpucfg_membase = of_iomap(node, 0);
+       of_node_put(node);
        if (!cpucfg_membase)
                pr_err("Couldn't map A31 CPU config registers\n");
 
@@ -133,6 +135,7 @@ static void __init sun8i_smp_prepare_cpus(unsigned int max_cpus)
        }
 
        prcm_membase = of_iomap(node, 0);
+       of_node_put(node);
        if (!prcm_membase) {
                pr_err("Couldn't map A23 PRCM registers\n");
                return;
@@ -146,6 +149,7 @@ static void __init sun8i_smp_prepare_cpus(unsigned int max_cpus)
        }
 
        cpucfg_membase = of_iomap(node, 0);
+       of_node_put(node);
        if (!cpucfg_membase)
                pr_err("Couldn't map A23 CPU config registers\n");
 
index 7f3b83e..3a06ba2 100644 (file)
@@ -2,7 +2,7 @@
 menuconfig ARCH_TEGRA
        bool "NVIDIA Tegra"
        depends on ARCH_MULTI_V7
-       select ARCH_SUPPORTS_TRUSTED_FOUNDATIONS
+       select ARCH_HAS_RESET_CONTROLLER
        select ARM_AMBA
        select ARM_GIC
        select CLKSRC_MMIO
@@ -10,8 +10,8 @@ menuconfig ARCH_TEGRA
        select HAVE_ARM_SCU if SMP
        select HAVE_ARM_TWD if SMP
        select PINCTRL
+       select PM
        select PM_OPP
-       select ARCH_HAS_RESET_CONTROLLER
        select RESET_CONTROLLER
        select SOC_BUS
        select ZONE_DMA if ARM_LPAE
index e3fbcfe..43c695d 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 
+#include <linux/firmware/trusted_foundations.h>
+
 #include <asm/cpuidle.h>
 #include <asm/smp_plat.h>
 #include <asm/suspend.h>
@@ -46,7 +48,7 @@ static int tegra114_idle_power_down(struct cpuidle_device *dev,
        tegra_set_cpu_in_lp2();
        cpu_pm_enter();
 
-       call_firmware_op(prepare_idle);
+       call_firmware_op(prepare_idle, TF_PM_MODE_LP2_NOFLUSH_L2);
 
        /* Do suspend by ourselves if the firmware does not implement it */
        if (call_firmware_op(do_idle, 0) == -ENOSYS)
index 3f24add..6620d61 100644 (file)
@@ -61,7 +61,8 @@ static struct cpuidle_driver tegra_idle_driver = {
                        .exit_latency     = 5000,
                        .target_residency = 10000,
                        .power_usage      = 0,
-                       .flags            = CPUIDLE_FLAG_COUPLED,
+                       .flags            = CPUIDLE_FLAG_COUPLED |
+                                           CPUIDLE_FLAG_TIMER_STOP,
                        .name             = "powered-down",
                        .desc             = "CPU power gated",
                },
@@ -136,12 +137,8 @@ static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
        if (tegra20_reset_cpu_1() || !tegra_cpu_rail_off_ready())
                return false;
 
-       tick_broadcast_enter();
-
        tegra_idle_lp2_last();
 
-       tick_broadcast_exit();
-
        if (cpu_online(1))
                tegra20_wake_cpu1_from_reset();
 
@@ -153,14 +150,10 @@ static bool tegra20_idle_enter_lp2_cpu_1(struct cpuidle_device *dev,
                                         struct cpuidle_driver *drv,
                                         int index)
 {
-       tick_broadcast_enter();
-
        cpu_suspend(0, tegra20_sleep_cpu_secondary_finish);
 
        tegra20_cpu_clear_resettable();
 
-       tick_broadcast_exit();
-
        return true;
 }
 #else
index c141736..c8fe044 100644 (file)
@@ -56,6 +56,7 @@ static struct cpuidle_driver tegra_idle_driver = {
                        .exit_latency           = 2000,
                        .target_residency       = 2200,
                        .power_usage            = 0,
+                       .flags                  = CPUIDLE_FLAG_TIMER_STOP,
                        .name                   = "powered-down",
                        .desc                   = "CPU power gated",
                },
@@ -76,12 +77,8 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
                return false;
        }
 
-       tick_broadcast_enter();
-
        tegra_idle_lp2_last();
 
-       tick_broadcast_exit();
-
        return true;
 }
 
@@ -90,14 +87,10 @@ static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
                                        struct cpuidle_driver *drv,
                                        int index)
 {
-       tick_broadcast_enter();
-
        smp_wmb();
 
        cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
 
-       tick_broadcast_exit();
-
        return true;
 }
 #else
index 9bc291e..ba61db7 100644 (file)
@@ -20,7 +20,7 @@
 #define __MACH_TEGRA_IOMAP_H
 
 #include <asm/pgtable.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #define TEGRA_IRAM_BASE                        0x40000000
 #define TEGRA_IRAM_SIZE                        SZ_256K
 #define TEGRA_PMC_BASE                 0x7000E400
 #define TEGRA_PMC_SIZE                 SZ_256
 
-#define TEGRA_MC_BASE                  0x7000F000
-#define TEGRA_MC_SIZE                  SZ_1K
-
 #define TEGRA_EMC_BASE                 0x7000F400
 #define TEGRA_EMC_SIZE                 SZ_1K
 
-#define TEGRA114_MC_BASE               0x70019000
-#define TEGRA114_MC_SIZE               SZ_4K
-
 #define TEGRA_EMC0_BASE                        0x7001A000
 #define TEGRA_EMC0_SIZE                        SZ_2K
 
 #define TEGRA_EMC1_BASE                        0x7001A800
 #define TEGRA_EMC1_SIZE                        SZ_2K
 
-#define TEGRA124_MC_BASE               0x70019000
-#define TEGRA124_MC_SIZE               SZ_4K
-
 #define TEGRA124_EMC_BASE              0x7001B000
 #define TEGRA124_EMC_SIZE              SZ_2K
 
index e32e174..6a7bb88 100644 (file)
@@ -17,7 +17,7 @@
 #ifndef __MACH_TEGRA_IRAMMAP_H
 #define __MACH_TEGRA_IRAMMAP_H
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 /* The first 1K of IRAM is permanently reserved for the CPU reset handler */
 #define TEGRA_IRAM_RESET_HANDLER_OFFSET        0
index 1ad5719..1b0ade0 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/suspend.h>
 
+#include <linux/firmware/trusted_foundations.h>
+
 #include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/pm.h>
 #include <soc/tegra/pmc.h>
 
 #include <asm/cacheflush.h>
+#include <asm/firmware.h>
 #include <asm/idmap.h>
 #include <asm/proc-fns.h>
 #include <asm/smp_plat.h>
@@ -159,6 +162,28 @@ int tegra_cpu_do_idle(void)
 
 static int tegra_sleep_cpu(unsigned long v2p)
 {
+       /*
+        * L2 cache disabling using kernel API only allowed when all
+        * secondary CPU's are offline. Cache have to be disabled with
+        * MMU-on if cache maintenance is done via Trusted Foundations
+        * firmware. Note that CPUIDLE won't ever enter powergate on Tegra30
+        * if any of secondary CPU's is online and this is the LP2-idle
+        * code-path only for Tegra20/30.
+        */
+       if (trusted_foundations_registered())
+               outer_disable();
+
+       /*
+        * Note that besides of setting up CPU reset vector this firmware
+        * call may also do the following, depending on the FW version:
+        *  1) Disable L2. But this doesn't matter since we already
+        *     disabled the L2.
+        *  2) Disable D-cache. This need to be taken into account in
+        *     particular by the tegra_disable_clean_inv_dcache() which
+        *     shall avoid the re-disable.
+        */
+       call_firmware_op(prepare_idle, TF_PM_MODE_LP2);
+
        setup_mm_for_reboot();
        tegra_sleep_cpu_finish(v2p);
 
@@ -197,6 +222,14 @@ void tegra_idle_lp2_last(void)
 
        cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
 
+       /*
+        * Resume L2 cache if it wasn't re-enabled early during resume,
+        * which is the case for Tegra30 that has to re-enable the cache
+        * via firmware call. In other cases cache is already enabled and
+        * hence re-enabling is a no-op. This is always a no-op on Tegra114+.
+        */
+       outer_resume();
+
        restore_cpu_complex();
        cpu_cluster_pm_exit();
 }
@@ -215,6 +248,15 @@ enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
 
 static int tegra_sleep_core(unsigned long v2p)
 {
+       /*
+        * Cache have to be disabled with MMU-on if cache maintenance is done
+        * via Trusted Foundations firmware. This is a no-op on Tegra114+.
+        */
+       if (trusted_foundations_registered())
+               outer_disable();
+
+       call_firmware_op(prepare_idle, TF_PM_MODE_LP1);
+
        setup_mm_for_reboot();
        tegra_sleep_core_finish(v2p);
 
@@ -342,6 +384,14 @@ static int tegra_suspend_enter(suspend_state_t state)
 
        cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func);
 
+       /*
+        * Resume L2 cache if it wasn't re-enabled early during resume,
+        * which is the case for Tegra30 that has to re-enable the cache
+        * via firmware call. In other cases cache is already enabled and
+        * hence re-enabling is a no-op.
+        */
+       outer_resume();
+
        switch (mode) {
        case TEGRA_SUSPEND_LP1:
                tegra_suspend_exit_lp1();
index e22ccf8..cd94d7c 100644 (file)
@@ -20,6 +20,7 @@
 #include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 
+#include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
 
@@ -29,8 +30,6 @@
 
 #define PMC_SCRATCH41  0x140
 
-#define RESET_DATA(x)  ((TEGRA_RESET_##x)*4)
-
 #ifdef CONFIG_PM_SLEEP
 /*
  *     tegra_resume
@@ -78,6 +77,7 @@ ENTRY(tegra_resume)
        orr     r1, r1, #1
        str     r1, [r0]
 #endif
+       bl      tegra_resume_trusted_foundations
 
 #ifdef CONFIG_CACHE_L2X0
        /* L2 cache resume & re-enable */
@@ -90,6 +90,30 @@ end_ca9_scu_l2_resume:
 
        b       cpu_resume
 ENDPROC(tegra_resume)
+
+/*
+ *     tegra_resume_trusted_foundations
+ *
+ *       Trusted Foundations firmware initialization.
+ *
+ *     Doesn't return if firmware presents.
+ *     Corrupted registers: r1, r2
+ */
+ENTRY(tegra_resume_trusted_foundations)
+       /* Check whether Trusted Foundations firmware presents. */
+       mov32   r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
+       ldr     r1, =__tegra_cpu_reset_handler_data_offset + \
+                                                       RESET_DATA(TF_PRESENT)
+       ldr     r1, [r2, r1]
+       cmp     r1, #0
+       reteq   lr
+
+ .arch_extension sec
+       /* First call after suspend wakes firmware. No arguments required. */
+       smc     #0
+
+       b       cpu_resume
+ENDPROC(tegra_resume_trusted_foundations)
 #endif
 
        .align L1_CACHE_SHIFT
@@ -115,12 +139,19 @@ ENTRY(__tegra_cpu_reset_handler_start)
  *       must be position-independent.
  */
 
+       .arm
        .align L1_CACHE_SHIFT
 ENTRY(__tegra_cpu_reset_handler)
 
        cpsid   aif, 0x13                       @ SVC mode, interrupts disabled
 
        tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
+
+       adr     r12, __tegra_cpu_reset_handler_data
+       ldr     r5, [r12, #RESET_DATA(TF_PRESENT)]
+       cmp     r5, #0
+       bne     after_errata
+
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
 t20_check:
        cmp     r6, #TEGRA20
@@ -155,7 +186,6 @@ after_errata:
        and     r10, r10, #0x3                  @ R10 = CPU number
        mov     r11, #1
        mov     r11, r11, lsl r10               @ R11 = CPU mask
-       adr     r12, __tegra_cpu_reset_handler_data
 
 #ifdef CONFIG_SMP
        /* Does the OS know about this CPU? */
@@ -169,10 +199,9 @@ after_errata:
        cmp     r6, #TEGRA20
        bne     1f
        /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
-       mov32   r5, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
        mov     r0, #CPU_NOT_RESETTABLE
        cmp     r10, #0
-       strbne  r0, [r5, #__tegra20_cpu1_resettable_status_offset]
+       strbne  r0, [r12, #RESET_DATA(RESETTABLE_STATUS)]
 1:
 #endif
 
@@ -277,14 +306,13 @@ ENDPROC(__tegra_cpu_reset_handler)
        .align L1_CACHE_SHIFT
        .type   __tegra_cpu_reset_handler_data, %object
        .globl  __tegra_cpu_reset_handler_data
+       .globl  __tegra_cpu_reset_handler_data_offset
+       .equ    __tegra_cpu_reset_handler_data_offset, \
+                                       . - __tegra_cpu_reset_handler_start
 __tegra_cpu_reset_handler_data:
-       .rept   TEGRA_RESET_DATA_SIZE
-       .long   0
+       .rept   TEGRA_RESET_DATA_SIZE
+       .long   0
        .endr
-       .globl  __tegra20_cpu1_resettable_status_offset
-       .equ    __tegra20_cpu1_resettable_status_offset, \
-                                       . - __tegra_cpu_reset_handler_start
-       .byte   0
        .align L1_CACHE_SHIFT
 
 ENTRY(__tegra_cpu_reset_handler_end)
index dc55889..35dc5d4 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/init.h>
 #include <linux/io.h>
 
+#include <linux/firmware/trusted_foundations.h>
+
 #include <soc/tegra/fuse.h>
 
 #include <asm/cacheflush.h>
@@ -89,6 +91,8 @@ static void __init tegra_cpu_reset_handler_enable(void)
 
 void __init tegra_cpu_reset_handler_init(void)
 {
+       __tegra_cpu_reset_handler_data[TEGRA_RESET_TF_PRESENT] =
+               trusted_foundations_registered();
 
 #ifdef CONFIG_SMP
        __tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] =
index 9c479c7..db0e6b3 100644 (file)
 #define TEGRA_RESET_STARTUP_SECONDARY  3
 #define TEGRA_RESET_STARTUP_LP2                4
 #define TEGRA_RESET_STARTUP_LP1                5
-#define TEGRA_RESET_DATA_SIZE          6
+#define TEGRA_RESET_RESETTABLE_STATUS  6
+#define TEGRA_RESET_TF_PRESENT         7
+#define TEGRA_RESET_DATA_SIZE          8
+
+#define RESET_DATA(x)  ((TEGRA_RESET_##x)*4)
 
 #ifndef __ASSEMBLY__
 
@@ -49,7 +53,8 @@ void __tegra_cpu_reset_handler_end(void);
         (u32)__tegra_cpu_reset_handler_start)))
 #define tegra20_cpu1_resettable_status \
        (IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
-        (u32)__tegra20_cpu1_resettable_status_offset))
+       ((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_RESETTABLE_STATUS] - \
+        (u32)__tegra_cpu_reset_handler_start)))
 #endif
 
 #define tegra_cpu_reset_handler_offset \
index dedeebf..50d51d3 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/cache.h>
 
 #include "irammap.h"
+#include "reset.h"
 #include "sleep.h"
 
 #define EMC_CFG                                0xc
@@ -53,6 +54,9 @@
 #define APB_MISC_XM2CFGCPADCTRL2       0x8e4
 #define APB_MISC_XM2CFGDPADCTRL2       0x8e8
 
+#define __tegra20_cpu1_resettable_status_offset \
+       (__tegra_cpu_reset_handler_data_offset + RESET_DATA(RESETTABLE_STATUS))
+
 .macro pll_enable, rd, r_car_base, pll_base
        ldr     \rd, [\r_car_base, #\pll_base]
        tst     \rd, #(1 << 30)
index d0b4c48..7727e00 100644 (file)
@@ -44,8 +44,6 @@
 #define EMC_XM2VTTGENPADCTRL           0x310
 #define EMC_XM2VTTGENPADCTRL2          0x314
 
-#define MC_EMEM_ARB_CFG                        0x90
-
 #define PMC_CTRL                       0x0
 #define PMC_CTRL_SIDE_EFFECT_LP0 (1 << 14) /* enter LP0 when CPU pwr gated */
 
@@ -420,22 +418,6 @@ _pll_m_c_x_done:
        movweq  r0, #:lower16:TEGRA124_EMC_BASE
        movteq  r0, #:upper16:TEGRA124_EMC_BASE
 
-       cmp     r10, #TEGRA30
-       moveq   r2, #0x20
-       movweq  r4, #:lower16:TEGRA_MC_BASE
-       movteq  r4, #:upper16:TEGRA_MC_BASE
-       cmp     r10, #TEGRA114
-       moveq   r2, #0x34
-       movweq  r4, #:lower16:TEGRA114_MC_BASE
-       movteq  r4, #:upper16:TEGRA114_MC_BASE
-       cmp     r10, #TEGRA124
-       moveq   r2, #0x20
-       movweq  r4, #:lower16:TEGRA124_MC_BASE
-       movteq  r4, #:upper16:TEGRA124_MC_BASE
-
-       ldr     r1, [r5, r2]            @ restore MC_EMEM_ARB_CFG
-       str     r1, [r4, #MC_EMEM_ARB_CFG]
-
 exit_self_refresh:
        ldr     r1, [r5, #0xC]          @ restore EMC_XM2VTTGENPADCTRL
        str     r1, [r0, #EMC_XM2VTTGENPADCTRL]
@@ -564,7 +546,6 @@ tegra30_sdram_pad_address:
        .word   TEGRA_PMC_BASE + PMC_IO_DPD_STATUS                      @0x14
        .word   TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT     @0x18
        .word   TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST             @0x1c
-       .word   TEGRA_MC_BASE + MC_EMEM_ARB_CFG                         @0x20
 tegra30_sdram_pad_address_end:
 
 tegra114_sdram_pad_address:
@@ -581,7 +562,6 @@ tegra114_sdram_pad_address:
        .word   TEGRA_EMC1_BASE + EMC_AUTO_CAL_INTERVAL                 @0x28
        .word   TEGRA_EMC1_BASE + EMC_XM2VTTGENPADCTRL                  @0x2c
        .word   TEGRA_EMC1_BASE + EMC_XM2VTTGENPADCTRL2                 @0x30
-       .word   TEGRA114_MC_BASE + MC_EMEM_ARB_CFG                      @0x34
 tegra114_sdram_pad_adress_end:
 
 tegra124_sdram_pad_address:
@@ -593,7 +573,6 @@ tegra124_sdram_pad_address:
        .word   TEGRA_PMC_BASE + PMC_IO_DPD_STATUS                      @0x14
        .word   TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT     @0x18
        .word   TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST             @0x1c
-       .word   TEGRA124_MC_BASE + MC_EMEM_ARB_CFG                      @0x20
 tegra124_sdram_pad_address_end:
 
 tegra30_sdram_pad_size:
index 5e34967..1735ded 100644 (file)
@@ -49,8 +49,9 @@ ENTRY(tegra_disable_clean_inv_dcache)
 
        /* Disable the D-cache */
        mrc     p15, 0, r2, c1, c0, 0
+       tst     r2, #CR_C                       @ see tegra_sleep_cpu()
        bic     r2, r2, #CR_C
-       mcr     p15, 0, r2, c1, c0, 0
+       mcrne   p15, 0, r2, c1, c0, 0
        isb
 
        /* Flush the D-cache */
@@ -132,10 +133,13 @@ ENTRY(tegra_shut_off_mmu)
 #ifdef CONFIG_CACHE_L2X0
        /* Disable L2 cache */
        check_cpu_part_num 0xc09, r9, r10
-       movweq  r2, #:lower16:(TEGRA_ARM_PERIF_BASE + 0x3000)
-       movteq  r2, #:upper16:(TEGRA_ARM_PERIF_BASE + 0x3000)
-       moveq   r3, #0
-       streq   r3, [r2, #L2X0_CTRL]
+       retne   r0
+
+       mov32   r2, TEGRA_ARM_PERIF_BASE + 0x3000
+       ldr     r3, [r2, #L2X0_CTRL]
+       tst     r3, #L2X0_CTRL_EN               @ see tegra_sleep_cpu()
+       mov     r3, #0
+       strne   r3, [r2, #L2X0_CTRL]
 #endif
        ret     r0
 ENDPROC(tegra_shut_off_mmu)
index f9587be..3e88f67 100644 (file)
 #include <linux/sys_soc.h>
 #include <linux/usb/tegra_usb_phy.h>
 
+#include <linux/firmware/trusted_foundations.h>
+
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/pmc.h>
 
+#include <asm/firmware.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach-types.h>
 #include <asm/setup.h>
-#include <asm/trusted_foundations.h>
 
 #include "board.h"
 #include "common.h"
@@ -74,6 +76,7 @@ static void __init tegra_init_early(void)
 {
        of_register_trusted_foundations();
        tegra_cpu_reset_handler_init();
+       call_firmware_op(l2x0_init);
 }
 
 static void __init tegra_dt_init_irq(void)
index 595b574..96ec72b 100644 (file)
@@ -130,3 +130,5 @@ static int __init u300_init_boardpower(void)
 }
 
 device_initcall(u300_init_boardpower);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Linus Walleij");
index fe3c626..2e6555d 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <mach/map.h>
 
 #endif /* __ASM_ARCH_HARDWARE_H */
index 6aba9eb..7f634ea 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/cpumask.h>
 #include <linux/platform_device.h>
index 43f46aa..0a75058 100644 (file)
@@ -1577,31 +1577,21 @@ static int __arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma
                    void *cpu_addr, dma_addr_t dma_addr, size_t size,
                    unsigned long attrs)
 {
-       unsigned long uaddr = vma->vm_start;
-       unsigned long usize = vma->vm_end - vma->vm_start;
        struct page **pages = __iommu_get_pages(cpu_addr, attrs);
        unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
-       unsigned long off = vma->vm_pgoff;
+       int err;
 
        if (!pages)
                return -ENXIO;
 
-       if (off >= nr_pages || (usize >> PAGE_SHIFT) > nr_pages - off)
+       if (vma->vm_pgoff >= nr_pages)
                return -ENXIO;
 
-       pages += off;
-
-       do {
-               int ret = vm_insert_page(vma, uaddr, *pages++);
-               if (ret) {
-                       pr_err("Remapping memory failed: %d\n", ret);
-                       return ret;
-               }
-               uaddr += PAGE_SIZE;
-               usize -= PAGE_SIZE;
-       } while (usize > 0);
+       err = vm_map_pages(vma, pages, nr_pages);
+       if (err)
+               pr_err("Remapping memory failed: %d\n", err);
 
-       return 0;
+       return err;
 }
 static int arm_iommu_mmap_attrs(struct device *dev,
                struct vm_area_struct *vma, void *cpu_addr,
index c2daabb..be0b429 100644 (file)
@@ -182,21 +182,6 @@ int pfn_valid(unsigned long pfn)
 EXPORT_SYMBOL(pfn_valid);
 #endif
 
-#ifndef CONFIG_SPARSEMEM
-static void __init arm_memory_present(void)
-{
-}
-#else
-static void __init arm_memory_present(void)
-{
-       struct memblock_region *reg;
-
-       for_each_memblock(memory, reg)
-               memory_present(0, memblock_region_memory_base_pfn(reg),
-                              memblock_region_memory_end_pfn(reg));
-}
-#endif
-
 static bool arm_memblock_steal_permitted = true;
 
 phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align)
@@ -293,7 +278,7 @@ void __init bootmem_init(void)
         * Sparsemem tries to allocate bootmem in memory_present(),
         * so must be done after the fixed reservations
         */
-       arm_memory_present();
+       memblocks_present();
 
        /*
         * sparse_init() needs the bootmem allocator up and running.
@@ -695,27 +680,14 @@ void free_initmem(void)
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
-
-static int keep_initrd;
-
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-       if (!keep_initrd) {
-               if (start == initrd_start)
-                       start = round_down(start, PAGE_SIZE);
-               if (end == initrd_end)
-                       end = round_up(end, PAGE_SIZE);
-
-               poison_init_mem((void *)start, PAGE_ALIGN(end) - start);
-               free_reserved_area((void *)start, (void *)end, -1, "initrd");
-       }
-}
+       if (start == initrd_start)
+               start = round_down(start, PAGE_SIZE);
+       if (end == initrd_end)
+               end = round_up(end, PAGE_SIZE);
 
-static int __init keepinitrd_setup(char *__unused)
-{
-       keep_initrd = 1;
-       return 1;
+       poison_init_mem((void *)start, PAGE_ALIGN(end) - start);
+       free_reserved_area((void *)start, (void *)end, -1, "initrd");
 }
-
-__setup("keepinitrd", keepinitrd_setup);
 #endif
index f519199..bf25f78 100644 (file)
@@ -183,18 +183,12 @@ static int pxa_ssp_probe(struct platform_device *pdev)
 
 static int pxa_ssp_remove(struct platform_device *pdev)
 {
-       struct resource *res;
        struct ssp_device *ssp;
 
        ssp = platform_get_drvdata(pdev);
        if (ssp == NULL)
                return -ENODEV;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, resource_size(res));
-
-       clk_put(ssp->clk);
-
        mutex_lock(&ssp_lock);
        list_del(&ssp->node);
        mutex_unlock(&ssp_lock);
index f4efff9..fadf554 100644 (file)
@@ -10,12 +10,12 @@ obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
 ccflags-y := -fPIC -fno-common -fno-builtin -fno-stack-protector
 ccflags-y += -DDISABLE_BRANCH_PROFILING
 
-VDSO_LDFLAGS := -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1
-VDSO_LDFLAGS += -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
-VDSO_LDFLAGS += -nostdlib -shared
-VDSO_LDFLAGS += $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
-VDSO_LDFLAGS += $(call cc-ldoption, -Wl$(comma)--build-id)
-VDSO_LDFLAGS += $(call cc-ldoption, -fuse-ld=bfd)
+ldflags-y = -Bsymbolic --no-undefined -soname=linux-vdso.so.1 \
+           -z max-page-size=4096 -z common-page-size=4096 \
+           -nostdlib -shared \
+           $(call ld-option, --hash-style=sysv) \
+           $(call ld-option, --build-id) \
+           -T
 
 obj-$(CONFIG_VDSO) += vdso.o
 extra-$(CONFIG_VDSO) += vdso.lds
@@ -37,8 +37,8 @@ KCOV_INSTRUMENT := n
 $(obj)/vdso.o : $(obj)/vdso.so
 
 # Link rule for the .so file
-$(obj)/vdso.so.raw: $(src)/vdso.lds $(obj-vdso) FORCE
-       $(call if_changed,vdsold)
+$(obj)/vdso.so.raw: $(obj)/vdso.lds $(obj-vdso) FORCE
+       $(call if_changed,ld)
 
 $(obj)/vdso.so.dbg: $(obj)/vdso.so.raw $(obj)/vdsomunge FORCE
        $(call if_changed,vdsomunge)
@@ -48,11 +48,6 @@ $(obj)/%.so: OBJCOPYFLAGS := -S
 $(obj)/%.so: $(obj)/%.so.dbg FORCE
        $(call if_changed,objcopy)
 
-# Actual build commands
-quiet_cmd_vdsold = VDSO    $@
-      cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \
-                   -Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@
-
 quiet_cmd_vdsomunge = MUNGE   $@
       cmd_vdsomunge = $(objtree)/$(obj)/vdsomunge $< $@
 
index e70a49f..da2a704 100644 (file)
@@ -70,8 +70,9 @@ unsigned long __pfn_to_mfn(unsigned long pfn)
                entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
                if (entry->pfn <= pfn &&
                                entry->pfn + entry->nr_pages > pfn) {
+                       unsigned long mfn = entry->mfn + (pfn - entry->pfn);
                        read_unlock_irqrestore(&p2m_lock, irqflags);
-                       return entry->mfn + (pfn - entry->pfn);
+                       return mfn;
                }
                if (pfn < entry->pfn)
                        n = n->rb_left;
@@ -156,6 +157,7 @@ bool __set_phys_to_machine_multi(unsigned long pfn,
        rc = xen_add_phys_to_mach_entry(p2m_entry);
        if (rc < 0) {
                write_unlock_irqrestore(&p2m_lock, irqflags);
+               kfree(p2m_entry);
                return false;
        }
        write_unlock_irqrestore(&p2m_lock, irqflags);
index 3f95744..69a59a5 100644 (file)
@@ -19,8 +19,9 @@ config ARM64
        select ARCH_HAS_FAST_MULTIPLIER
        select ARCH_HAS_FORTIFY_SOURCE
        select ARCH_HAS_GCOV_PROFILE_ALL
-       select ARCH_HAS_GIGANTIC_PAGE if (MEMORY_ISOLATION && COMPACTION) || CMA
+       select ARCH_HAS_GIGANTIC_PAGE
        select ARCH_HAS_KCOV
+       select ARCH_HAS_KEEPINITRD
        select ARCH_HAS_MEMBARRIER_SYNC_CORE
        select ARCH_HAS_PTE_SPECIAL
        select ARCH_HAS_SETUP_DMA_OPS
@@ -59,6 +60,7 @@ config ARM64
        select ARCH_INLINE_SPIN_UNLOCK_BH if !PREEMPT
        select ARCH_INLINE_SPIN_UNLOCK_IRQ if !PREEMPT
        select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPT
+       select ARCH_KEEP_MEMBLOCK
        select ARCH_USE_CMPXCHG_LOCKREF
        select ARCH_USE_QUEUED_RWLOCKS
        select ARCH_USE_QUEUED_SPINLOCKS
index b5ca9c5..0f4d918 100644 (file)
@@ -7,6 +7,11 @@ config ARCH_ACTIONS
        help
          This enables support for the Actions Semiconductor S900 SoC family.
 
+config ARCH_AGILEX
+       bool "Intel's Agilex SoCFPGA Family"
+       help
+         This enables support for Intel's Agilex SoCFPGA Family.
+
 config ARCH_SUNXI
        bool "Allwinner sunxi 64-bit SoC Family"
        select ARCH_HAS_RESET_CONTROLLER
index 5bc7533..f19b762 100644 (file)
@@ -13,6 +13,7 @@ subdir-y += cavium
 subdir-y += exynos
 subdir-y += freescale
 subdir-y += hisilicon
+subdir-y += intel
 subdir-y += lg
 subdir-y += marvell
 subdir-y += mediatek
index 0b09171..f6db061 100644 (file)
@@ -2,6 +2,7 @@
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-amarula-relic.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-bananapi-m64.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-nanopi-a64.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-oceanic-5205-5inmfd.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-olinuxino.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-orangepi-win.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-lts.dtb
@@ -19,6 +20,8 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-pc2.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-prime.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus2.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-beelink-gs1.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-3.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-lite2.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb
index 6cb2b7f..019ae09 100644 (file)
                stdout-path = "serial0:115200n8";
        };
 
+       i2c {
+               compatible = "i2c-gpio";
+               sda-gpios = <&pio 4 13 GPIO_ACTIVE_HIGH>;
+               scl-gpios = <&pio 4 12 GPIO_ACTIVE_HIGH>;
+               i2c-gpio,delay-us = <5>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               ov5640: camera@3c {
+                       compatible = "ovti,ov5640";
+                       reg = <0x3c>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&csi_mclk_pin>;
+                       clocks = <&ccu CLK_CSI_MCLK>;
+                       clock-names = "xclk";
+
+                       AVDD-supply = <&reg_aldo1>;
+                       DOVDD-supply = <&reg_dldo3>;
+                       DVDD-supply = <&reg_eldo3>;
+                       reset-gpios = <&pio 4 14 GPIO_ACTIVE_LOW>; /* CSI-RST-R: PE14 */
+                       powerdown-gpios = <&pio 4 15 GPIO_ACTIVE_HIGH>; /* CSI-STBY-R: PE15 */
+
+                       port {
+                               ov5640_ep: endpoint {
+                                       remote-endpoint = <&csi_ep>;
+                                       bus-width = <8>;
+                                       hsync-active = <1>; /* Active high */
+                                       vsync-active = <0>; /* Active low */
+                                       data-active = <1>;  /* Active high */
+                                       pclk-sample = <1>;  /* Rising */
+                               };
+                       };
+               };
+       };
+
        wifi_pwrseq: wifi-pwrseq {
                compatible = "mmc-pwrseq-simple";
                clocks = <&rtc 1>;
        };
 };
 
+&csi {
+       status = "okay";
+
+       port {
+               csi_ep: endpoint {
+                       remote-endpoint = <&ov5640_ep>;
+                       bus-width = <8>;
+                       hsync-active = <1>; /* Active high */
+                       vsync-active = <0>; /* Active low */
+                       data-active = <1>;  /* Active high */
+                       pclk-sample = <1>;  /* Rising */
+               };
+       };
+};
+
 &ehci0 {
        status = "okay";
 };
 
+&i2c0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c0_pins>;
+       status = "okay";
+
+       sensor@48 {
+               compatible = "st,stlm75";
+               reg = <0x48>;
+       };
+};
+
+&i2c0_pins {
+       bias-pull-up;
+};
+
 &mmc1 {
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pins>;
index 7793ebb..0a56c0c 100644 (file)
 };
 
 &codec_analog {
-       hpvcc-supply = <&reg_eldo1>;
+       cpvdd-supply = <&reg_eldo1>;
        status = "okay";
 };
 
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-oceanic-5205-5inmfd.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-oceanic-5205-5inmfd.dts
new file mode 100644 (file)
index 0000000..6a21545
--- /dev/null
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Oceanic Systems (UK) Ltd.
+ * Copyright (C) 2019 Amarula Solutions B.V.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+/dts-v1/;
+
+#include "sun50i-a64-sopine.dtsi"
+
+/ {
+       model = "Oceanic 5205 5inMFD";
+       compatible = "oceanic,5205-5inmfd", "allwinner,sun50i-a64";
+
+       aliases {
+               ethernet0 = &emac;
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+};
+
+&ehci0 {
+       status = "okay";
+};
+
+&emac {
+       pinctrl-names = "default";
+       pinctrl-0 = <&rgmii_pins>;
+       phy-mode = "rgmii";
+       phy-handle = <&ext_rgmii_phy>;
+       phy-supply = <&reg_dc1sw>;
+       allwinner,tx-delay-ps = <600>;
+       status = "okay";
+};
+
+&mdio {
+       ext_rgmii_phy: ethernet-phy@1 {
+               compatible = "ethernet-phy-ieee802.3-c22";
+               reg = <1>;
+       };
+};
+
+&ohci0 {
+       status = "okay";
+};
+
+&reg_dc1sw {
+       regulator-name = "vcc-phy";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pb_pins>;
+       status = "okay";
+};
+
+&usb_otg {
+       dr_mode = "host";
+       status = "okay";
+};
+
+&usbphy {
+       status = "okay";
+};
index c0b9cc7..b7ac637 100644 (file)
@@ -80,7 +80,7 @@
 };
 
 &codec_analog {
-       hpvcc-supply = <&reg_eldo1>;
+       cpvdd-supply = <&reg_eldo1>;
        status = "okay";
 };
 
index d22736a..2b6345d 100644 (file)
@@ -94,7 +94,7 @@
 };
 
 &codec_analog {
-       hpvcc-supply = <&reg_eldo1>;
+       cpvdd-supply = <&reg_eldo1>;
        status = "okay";
 };
 
 
 &ehci0 {
        phys = <&usbphy 0>;
-       phy-names = "usb";
        status = "okay";
 };
 
 
 &ohci0 {
        phys = <&usbphy 0>;
-       phy-names = "usb";
        status = "okay";
 };
 
index d2651f2..9d20e13 100644 (file)
@@ -48,7 +48,7 @@
 #include <dt-bindings/gpio/gpio.h>
 
 &codec_analog {
-       hpvcc-supply = <&reg_eldo1>;
+       cpvdd-supply = <&reg_eldo1>;
 };
 
 &mmc0 {
index 7b7b14b..0ec46b9 100644 (file)
                serial0 = &uart0;
        };
 
+       backlight: backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm 0 50000 0>;
+               power-supply = <&reg_dcdc1>;
+               brightness-levels = <0 5 7 10 14 20 28 40 56 80 112>;
+               default-brightness-level = <5>;
+               enable-gpios = <&pio 3 23 GPIO_ACTIVE_HIGH>; /* PD23 */
+       };
+
        chosen {
                stdout-path = "serial0:115200n8";
 
        status = "okay";
 };
 
+&pwm {
+       status = "okay";
+};
+
 &r_rsb {
        status = "okay";
 
index e628d06..8c5b521 100644 (file)
                #size-cells = <1>;
                ranges;
 
-               de2@1000000 {
+               bus@1000000 {
                        compatible = "allwinner,sun50i-a64-de2";
                        reg = <0x1000000 0x400000>;
                        allwinner,sram = <&de2_sram 1>;
                                        #size-cells = <0>;
 
                                        mixer0_out: port@1 {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
                                                reg = <1>;
 
-                                               mixer0_out_tcon0: endpoint {
+                                               mixer0_out_tcon0: endpoint@0 {
+                                                       reg = <0>;
                                                        remote-endpoint = <&tcon0_in_mixer0>;
                                                };
+
+                                               mixer0_out_tcon1: endpoint@1 {
+                                                       reg = <1>;
+                                                       remote-endpoint = <&tcon1_in_mixer0>;
+                                               };
                                        };
                                };
                        };
                                        #size-cells = <0>;
 
                                        mixer1_out: port@1 {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
                                                reg = <1>;
 
-                                               mixer1_out_tcon1: endpoint {
+                                               mixer1_out_tcon0: endpoint@0 {
+                                                       reg = <0>;
+                                                       remote-endpoint = <&tcon0_in_mixer1>;
+                                               };
+
+                                               mixer1_out_tcon1: endpoint@1 {
+                                                       reg = <1>;
                                                        remote-endpoint = <&tcon1_in_mixer1>;
                                                };
                                        };
                        clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_TCON0>;
                        clock-names = "ahb", "tcon-ch0";
                        clock-output-names = "tcon-pixel-clock";
+                       #clock-cells = <0>;
                        resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>;
                        reset-names = "lcd", "lvds";
 
                                                reg = <0>;
                                                remote-endpoint = <&mixer0_out_tcon0>;
                                        };
+
+                                       tcon0_in_mixer1: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&mixer1_out_tcon0>;
+                                       };
                                };
 
                                tcon0_out: port@1 {
                                #size-cells = <0>;
 
                                tcon1_in: port@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
                                        reg = <0>;
 
-                                       tcon1_in_mixer1: endpoint {
+                                       tcon1_in_mixer0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&mixer0_out_tcon1>;
+                                       };
+
+                                       tcon1_in_mixer1: endpoint@1 {
+                                               reg = <1>;
                                                remote-endpoint = <&mixer1_out_tcon1>;
                                        };
                                };
                        phys = <&usbphy 0>;
                        phy-names = "usb";
                        extcon = <&usbphy 0>;
+                       dr_mode = "otg";
                        status = "disabled";
                };
 
                        resets = <&ccu RST_BUS_OHCI1>,
                                 <&ccu RST_BUS_EHCI1>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                                 <&ccu CLK_USB_OHCI1>;
                        resets = <&ccu RST_BUS_OHCI1>;
                        phys = <&usbphy 1>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu 58>;
+                       clocks = <&ccu 58>, <&osc24M>, <&rtc 0>;
+                       clock-names = "apb", "hosc", "losc";
                        gpio-controller;
                        #gpio-cells = <3>;
                        interrupt-controller;
                                function = "csi";
                        };
 
-                       i2c0_pins: i2c0_pins {
+                       /omit-if-no-ref/
+                       csi_mclk_pin: csi-mclk-pin {
+                               pins = "PE1";
+                               function = "csi";
+                       };
+
+                       i2c0_pins: i2c0-pins {
                                pins = "PH0", "PH1";
                                function = "i2c0";
                        };
 
-                       i2c1_pins: i2c1_pins {
+                       i2c1_pins: i2c1-pins {
                                pins = "PH2", "PH3";
                                function = "i2c1";
                        };
                                bias-pull-up;
                        };
 
-                       pwm_pin: pwm_pin {
+                       pwm_pin: pwm-pin {
                                pins = "PD22";
                                function = "pwm";
                        };
 
-                       rmii_pins: rmii_pins {
+                       rmii_pins: rmii-pins {
                                pins = "PD10", "PD11", "PD13", "PD14", "PD17",
                                       "PD18", "PD19", "PD20", "PD22", "PD23";
                                function = "emac";
                                drive-strength = <40>;
                        };
 
-                       rgmii_pins: rgmii_pins {
+                       rgmii_pins: rgmii-pins {
                                pins = "PD8", "PD9", "PD10", "PD11", "PD12",
                                       "PD13", "PD15", "PD16", "PD17", "PD18",
                                       "PD19", "PD20", "PD21", "PD22", "PD23";
                                drive-strength = <40>;
                        };
 
-                       spdif_tx_pin: spdif {
+                       spdif_tx_pin: spdif-tx-pin {
                                pins = "PH8";
                                function = "spdif";
                        };
 
-                       spi0_pins: spi0 {
+                       spi0_pins: spi0-pins {
                                pins = "PC0", "PC1", "PC2", "PC3";
                                function = "spi0";
                        };
 
-                       spi1_pins: spi1 {
+                       spi1_pins: spi1-pins {
                                pins = "PD0", "PD1", "PD2", "PD3";
                                function = "spi1";
                        };
                                function = "uart0";
                        };
 
-                       uart1_pins: uart1_pins {
+                       uart1_pins: uart1-pins {
                                pins = "PG6", "PG7";
                                function = "uart1";
                        };
 
-                       uart1_rts_cts_pins: uart1_rts_cts_pins {
+                       uart1_rts_cts_pins: uart1-rts-cts-pins {
                                pins = "PG8", "PG9";
                                function = "uart1";
                        };
                        clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>;
                        clock-names = "apb", "mod";
                        resets = <&ccu RST_BUS_CODEC>;
-                       reset-names = "rst";
                        dmas = <&dma 15>, <&dma 15>;
                        dma-names = "rx", "tx";
                        status = "disabled";
                                function = "s_i2c";
                        };
 
-                       r_pwm_pin: pwm {
+                       r_pwm_pin: r-pwm-pin {
                                pins = "PL10";
                                function = "s_pwm";
                        };
 
-                       r_rsb_pins: rsb {
+                       r_rsb_pins: r-rsb-pins {
                                pins = "PL0", "PL1";
                                function = "s_rsb";
                        };
index 85e7993..62409af 100644 (file)
@@ -46,7 +46,6 @@
 
        vdd_cpux: gpio-regulator {
                compatible = "regulator-gpio";
-               pinctrl-names = "default";
                regulator-name = "vdd-cpux";
                regulator-type = "voltage";
                regulator-boot-on;
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index e4d5037..82f4b44 100644 (file)
@@ -21,7 +21,6 @@
 
        wifi_pwrseq: wifi_pwrseq {
                compatible = "mmc-pwrseq-simple";
-               pinctrl-names = "default";
                reset-gpios = <&pio 2 7 GPIO_ACTIVE_LOW>; /* PC7 */
                post-power-on-delay-ms = <200>;
        };
index 506e25b..9887948 100644 (file)
@@ -78,7 +78,6 @@
 
        reg_gmac_3v3: gmac-3v3 {
                compatible = "regulator-fixed";
-               pinctrl-names = "default";
                regulator-name = "gmac-3v3";
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
@@ -96,7 +95,6 @@
 
        vdd_cpux: gpio-regulator {
                compatible = "regulator-gpio";
-               pinctrl-names = "default";
                regulator-name = "vdd-cpux";
                regulator-type = "voltage";
                regulator-boot-on;
 
        wifi_pwrseq: wifi_pwrseq {
                compatible = "mmc-pwrseq-simple";
-               pinctrl-names = "default";
                reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */
                post-power-on-delay-ms = <200>;
        };
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index cc268a6..57a6f45 100644 (file)
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index 3e0d5a9..e126c1c 100644 (file)
 
 &ir {
        pinctrl-names = "default";
-       pinctrl-0 = <&ir_pins_a>;
+       pinctrl-0 = <&r_ir_rx_pin>;
        status = "okay";
 };
 
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index b75ca4d..d9b3ed2 100644 (file)
 
 &ir {
        pinctrl-names = "default";
-       pinctrl-0 = <&ir_pins_a>;
+       pinctrl-0 = <&r_ir_rx_pin>;
        status = "okay";
 };
 
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index 1238de2..db6ea7b 100644 (file)
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index 53c8c11..dacf613 100644 (file)
@@ -78,7 +78,6 @@
 
        wifi_pwrseq: wifi_pwrseq {
                compatible = "mmc-pwrseq-simple";
-               pinctrl-names = "default";
                reset-gpios = <&pio 0 9 GPIO_ACTIVE_LOW>; /* PA9 */
                post-power-on-delay-ms = <200>;
        };
 
 &uart0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart0_pins_a>;
+       pinctrl-0 = <&uart0_pa_pins>;
        status = "okay";
 };
 
index 96acafd..f002a49 100644 (file)
 &rtc {
        compatible = "allwinner,sun50i-h5-rtc";
 };
+
+&sid {
+       compatible = "allwinner,sun50i-h5-sid";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
new file mode 100644 (file)
index 0000000..0dc33c9
--- /dev/null
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2019 Clément Péron <peron.clem@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "sun50i-h6.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       model = "Beelink GS1";
+       compatible = "azw,beelink-gs1", "allwinner,sun50i-h6";
+
+       aliases {
+               ethernet0 = &emac;
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       connector {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_con_in: endpoint {
+                               remote-endpoint = <&hdmi_out_con>;
+                       };
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               power {
+                       label = "beelink:white:power";
+                       gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */
+                       default-state = "on";
+               };
+       };
+
+       reg_vcc5v: vcc5v {
+               /* board wide 5V supply directly from the DC jack */
+               compatible = "regulator-fixed";
+               regulator-name = "vcc-5v";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+};
+
+&de {
+       status = "okay";
+};
+
+&ehci0 {
+       status = "okay";
+};
+
+&emac {
+       pinctrl-names = "default";
+       pinctrl-0 = <&ext_rgmii_pins>;
+       phy-mode = "rgmii";
+       phy-handle = <&ext_rgmii_phy>;
+       phy-supply = <&reg_aldo2>;
+       status = "okay";
+};
+
+&hdmi {
+       status = "okay";
+};
+
+&hdmi_out {
+       hdmi_out_con: endpoint {
+               remote-endpoint = <&hdmi_con_in>;
+       };
+};
+
+&mdio {
+       ext_rgmii_phy: ethernet-phy@1 {
+               compatible = "ethernet-phy-ieee802.3-c22";
+               reg = <1>;
+       };
+};
+
+&mmc0 {
+       vmmc-supply = <&reg_cldo1>;
+       cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+       bus-width = <4>;
+       status = "okay";
+};
+
+&mmc2 {
+       vmmc-supply = <&reg_cldo1>;
+       vqmmc-supply = <&reg_bldo2>;
+       non-removable;
+       cap-mmc-hw-reset;
+       bus-width = <8>;
+       status = "okay";
+};
+
+&ohci0 {
+       status = "okay";
+};
+
+&pio {
+       vcc-pd-supply = <&reg_cldo1>;
+       vcc-pg-supply = <&reg_aldo1>;
+};
+
+&r_i2c {
+       status = "okay";
+
+       axp805: pmic@36 {
+               compatible = "x-powers,axp805", "x-powers,axp806";
+               reg = <0x36>;
+               interrupt-parent = <&r_intc>;
+               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               x-powers,self-working-mode;
+               vina-supply = <&reg_vcc5v>;
+               vinb-supply = <&reg_vcc5v>;
+               vinc-supply = <&reg_vcc5v>;
+               vind-supply = <&reg_vcc5v>;
+               vine-supply = <&reg_vcc5v>;
+               aldoin-supply = <&reg_vcc5v>;
+               bldoin-supply = <&reg_vcc5v>;
+               cldoin-supply = <&reg_vcc5v>;
+
+               regulators {
+                       reg_aldo1: aldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-pl";
+                       };
+
+                       reg_aldo2: aldo2 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-ac200";
+                               regulator-enable-ramp-delay = <100000>;
+                       };
+
+                       reg_aldo3: aldo3 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc25-dram";
+                       };
+
+                       reg_bldo1: bldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc-bias-pll";
+                       };
+
+                       reg_bldo2: bldo2 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc-efuse-pcie-hdmi-io";
+                       };
+
+                       reg_bldo3: bldo3 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc-dcxoio";
+                       };
+
+                       bldo4 {
+                               /* unused */
+                       };
+
+                       reg_cldo1: cldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-3v3";
+                       };
+
+                       reg_cldo2: cldo2 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-wifi-1";
+                       };
+
+                       reg_cldo3: cldo3 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-wifi-2";
+                       };
+
+                       reg_dcdca: dcdca {
+                               regulator-always-on;
+                               regulator-min-microvolt = <810000>;
+                               regulator-max-microvolt = <1080000>;
+                               regulator-name = "vdd-cpu";
+                       };
+
+                       reg_dcdcc: dcdcc {
+                               regulator-min-microvolt = <810000>;
+                               regulator-max-microvolt = <1080000>;
+                               regulator-name = "vdd-gpu";
+                       };
+
+                       reg_dcdcd: dcdcd {
+                               regulator-always-on;
+                               regulator-min-microvolt = <960000>;
+                               regulator-max-microvolt = <960000>;
+                               regulator-name = "vdd-sys";
+                       };
+
+                       reg_dcdce: dcdce {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-name = "vcc-dram";
+                       };
+
+                       sw {
+                               /* unused */
+                       };
+               };
+       };
+};
+
+&r_pio {
+       /*
+        * PL0 and PL1 are used for PMIC I2C
+        * don't enable the pl-supply else
+        * it will fail at boot
+        *
+        * vcc-pl-supply = <&reg_aldo1>;
+        */
+       vcc-pm-supply = <&reg_aldo1>;
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_ph_pins>;
+       status = "okay";
+};
+
+&usb2otg {
+       dr_mode = "host";
+       status = "okay";
+};
+
+&usb2phy {
+       usb0_vbus-supply = <&reg_vcc5v>;
+       status = "okay";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts
new file mode 100644 (file)
index 0000000..17d4969
--- /dev/null
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2019 Ondřej Jirman <megous@megous.com>
+ */
+
+/dts-v1/;
+
+#include "sun50i-h6.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       model = "OrangePi 3";
+       compatible = "xunlong,orangepi-3", "allwinner,sun50i-h6";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               power {
+                       label = "orangepi:red:power";
+                       gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */
+                       default-state = "on";
+               };
+
+               status {
+                       label = "orangepi:green:status";
+                       gpios = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */
+               };
+       };
+
+       reg_vcc5v: vcc5v {
+               /* board wide 5V supply directly from the DC jack */
+               compatible = "regulator-fixed";
+               regulator-name = "vcc-5v";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+};
+
+&cpu0 {
+       cpu-supply = <&reg_dcdca>;
+};
+
+&ehci0 {
+       status = "okay";
+};
+
+&ehci3 {
+       status = "okay";
+};
+
+&mmc0 {
+       vmmc-supply = <&reg_cldo1>;
+       cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+       bus-width = <4>;
+       status = "okay";
+};
+
+&ohci0 {
+       status = "okay";
+};
+
+&ohci3 {
+       status = "okay";
+};
+
+&pio {
+       vcc-pc-supply = <&reg_bldo2>;
+       vcc-pd-supply = <&reg_cldo1>;
+};
+
+&r_i2c {
+       status = "okay";
+
+       axp805: pmic@36 {
+               compatible = "x-powers,axp805", "x-powers,axp806";
+               reg = <0x36>;
+               interrupt-parent = <&r_intc>;
+               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               x-powers,self-working-mode;
+               vina-supply = <&reg_vcc5v>;
+               vinb-supply = <&reg_vcc5v>;
+               vinc-supply = <&reg_vcc5v>;
+               vind-supply = <&reg_vcc5v>;
+               vine-supply = <&reg_vcc5v>;
+               aldoin-supply = <&reg_vcc5v>;
+               bldoin-supply = <&reg_vcc5v>;
+               cldoin-supply = <&reg_vcc5v>;
+
+               regulators {
+                       reg_aldo1: aldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-pl-led-ir";
+                       };
+
+                       reg_aldo2: aldo2 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc33-audio-tv-ephy-mac";
+                       };
+
+                       /* ALDO3 is shorted to CLDO1 */
+                       reg_aldo3: aldo3 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc33-io-pd-emmc-sd-usb-uart-1";
+                       };
+
+                       reg_bldo1: bldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc18-dram-bias-pll";
+                       };
+
+                       reg_bldo2: bldo2 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc-efuse-pcie-hdmi-pc";
+                       };
+
+                       bldo3 {
+                               /* unused */
+                       };
+
+                       bldo4 {
+                               /* unused */
+                       };
+
+                       reg_cldo1: cldo1 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc33-io-pd-emmc-sd-usb-uart-2";
+                       };
+
+                       cldo2 {
+                               /* unused */
+                       };
+
+                       cldo3 {
+                               /* unused */
+                       };
+
+                       reg_dcdca: dcdca {
+                               regulator-always-on;
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1160000>;
+                               regulator-name = "vdd-cpu";
+                       };
+
+                       reg_dcdcc: dcdcc {
+                               regulator-min-microvolt = <810000>;
+                               regulator-max-microvolt = <1080000>;
+                               regulator-name = "vdd-gpu";
+                       };
+
+                       reg_dcdcd: dcdcd {
+                               regulator-always-on;
+                               regulator-min-microvolt = <960000>;
+                               regulator-max-microvolt = <960000>;
+                               regulator-name = "vdd-sys";
+                       };
+
+                       reg_dcdce: dcdce {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-name = "vcc-dram";
+                       };
+
+                       sw {
+                               /* unused */
+                       };
+               };
+       };
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_ph_pins>;
+       status = "okay";
+};
+
+&usb2otg {
+       /*
+        * This board doesn't have a controllable VBUS even though it
+        * does have an ID pin. Using it as anything but a USB host is
+        * unsafe.
+        */
+       dr_mode = "host";
+       status = "okay";
+};
+
+&usb2phy {
+       usb0_id_det-gpios = <&pio 2 15 GPIO_ACTIVE_HIGH>; /* PC15 */
+       usb0_vbus-supply = <&reg_vcc5v>;
+       usb3_vbus-supply = <&reg_vcc5v>;
+       status = "okay";
+};
index b2526da..62e2794 100644 (file)
@@ -56,8 +56,6 @@
 };
 
 &mmc0 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&mmc0_pins>;
        vmmc-supply = <&reg_cldo1>;
        cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
        bus-width = <4>;
index bdb8470..4802902 100644 (file)
 };
 
 &mmc0 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&mmc0_pins>;
        vmmc-supply = <&reg_cldo1>;
        cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
        bus-width = <4>;
 };
 
 &mmc2 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&mmc2_pins>;
        vmmc-supply = <&reg_cldo1>;
        vqmmc-supply = <&reg_bldo2>;
        non-removable;
index c9e861a..16c5c3d 100644 (file)
                #size-cells = <1>;
                ranges;
 
-               display-engine@1000000 {
+               bus@1000000 {
                        compatible = "allwinner,sun50i-h6-de3",
                                     "allwinner,sun50i-a64-de2";
                        reg = <0x1000000 0x400000>;
                        };
                };
 
+               video-codec@1c0e000 {
+                       compatible = "allwinner,sun50i-h6-video-engine";
+                       reg = <0x01c0e000 0x2000>;
+                       clocks = <&ccu CLK_BUS_VE>, <&ccu CLK_VE>,
+                                <&ccu CLK_MBUS_VE>;
+                       clock-names = "ahb", "mod", "ram";
+                       resets = <&ccu RST_BUS_VE>;
+                       interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+                       allwinner,sram = <&ve_sram 1>;
+               };
+
                syscon: syscon@3000000 {
                        compatible = "allwinner,sun50i-h6-system-control",
                                     "allwinner,sun50i-a64-system-control";
                        #reset-cells = <1>;
                };
 
+               sid: sid@3006000 {
+                       compatible = "allwinner,sun50i-h6-sid";
+                       reg = <0x03006000 0x400>;
+               };
+
                pio: pinctrl@300b000 {
                        compatible = "allwinner,sun50i-h6-pinctrl";
                        reg = <0x0300b000 0x400>;
                        interrupt-controller;
                        #interrupt-cells = <3>;
 
-                       ext_rgmii_pins: rgmii_pins {
+                       ext_rgmii_pins: rgmii-pins {
                                pins = "PD0", "PD1", "PD2", "PD3", "PD4",
                                       "PD5", "PD7", "PD8", "PD9", "PD10",
                                       "PD11", "PD12", "PD13", "PD19", "PD20";
                                bias-pull-up;
                        };
 
+                       /omit-if-no-ref/
+                       mmc1_pins: mmc1-pins {
+                               pins = "PG0", "PG1", "PG2", "PG3",
+                                      "PG4", "PG5";
+                               function = "mmc1";
+                               drive-strength = <30>;
+                               bias-pull-up;
+                       };
+
                        mmc2_pins: mmc2-pins {
                                pins = "PC1", "PC4", "PC5", "PC6",
                                       "PC7", "PC8", "PC9", "PC10",
                                bias-pull-up;
                        };
 
-                       uart0_ph_pins: uart0-ph {
+                       uart0_ph_pins: uart0-ph-pins {
                                pins = "PH0", "PH1";
                                function = "uart0";
                        };
                        resets = <&ccu RST_BUS_MMC0>;
                        reset-names = "ahb";
                        interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mmc0_pins>;
                        status = "disabled";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        resets = <&ccu RST_BUS_MMC1>;
                        reset-names = "ahb";
                        interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mmc1_pins>;
                        status = "disabled";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        resets = <&ccu RST_BUS_MMC2>;
                        reset-names = "ahb";
                        interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mmc2_pins>;
                        status = "disabled";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        resets = <&ccu RST_BUS_OHCI3>,
                                 <&ccu RST_BUS_EHCI3>;
                        phys = <&usb2phy 3>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                                 <&ccu CLK_USB_OHCI3>;
                        resets = <&ccu RST_BUS_OHCI3>;
                        phys = <&usb2phy 3>;
-                       phy-names = "usb";
                        status = "disabled";
                };
 
                        interrupt-controller;
                        #interrupt-cells = <3>;
 
-                       r_i2c_pins: r-i2c {
+                       r_i2c_pins: r-i2c-pins {
                                pins = "PL0", "PL1";
                                function = "s_i2c";
                        };
index a2cec62..fe107ce 100644 (file)
                };
 
                sysmgr: sysmgr@ffd12000 {
-                       compatible = "altr,sys-mgr", "syscon";
+                       compatible = "altr,sys-mgr-s10","altr,sys-mgr";
                        reg = <0xffd12000 0x228>;
                };
 
index 2e3863e..d037563 100644 (file)
 &mmc {
        status = "okay";
        cap-sd-highspeed;
+       cap-mmc-highspeed;
        broken-cd;
        bus-width = <4>;
 };
                #size-cells = <1>;
                compatible = "n25q00a";
                reg = <0>;
-               spi-max-frequency = <50000000>;
+               spi-max-frequency = <100000000>;
 
                m25p,fast-read;
                cdns,page-size = <256>;
index 0821fed..e129c03 100644 (file)
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 dtb-$(CONFIG_ARCH_MESON) += meson-axg-s400.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-g12a-sei510.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-g12a-u200.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-g12a-x96-max.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nanopi-k2.dtb
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts
new file mode 100644 (file)
index 0000000..34b4058
--- /dev/null
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre SAS. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include "meson-g12a.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/meson-g12a-gpio.h>
+
+/ {
+       compatible = "seirobotics,sei510", "amlogic,g12a";
+       model = "SEI Robotics SEI510";
+
+       aliases {
+               serial0 = &uart_AO;
+       };
+
+       adc_keys {
+               compatible = "adc-keys";
+               io-channels = <&saradc 0>;
+               io-channel-names = "buttons";
+               keyup-threshold-microvolt = <1800000>;
+
+               button-onoff {
+                       label = "On/Off";
+                       linux,code = <KEY_POWER>;
+                       press-threshold-microvolt = <1700000>;
+               };
+       };
+
+       ao_5v: regulator-ao_5v {
+               compatible = "regulator-fixed";
+               regulator-name = "AO_5V";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               vin-supply = <&dc_in>;
+               regulator-always-on;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       cvbs-connector {
+               compatible = "composite-video-connector";
+
+               port {
+                       cvbs_connector_in: endpoint {
+                               remote-endpoint = <&cvbs_vdac_out>;
+                       };
+               };
+       };
+
+       dc_in: regulator-dc_in {
+               compatible = "regulator-fixed";
+               regulator-name = "DC_IN";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+
+       emmc_1v8: regulator-emmc_1v8 {
+               compatible = "regulator-fixed";
+               regulator-name = "EMMC_1V8";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vddao_3v3>;
+               regulator-always-on;
+       };
+
+       hdmi-connector {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_connector_in: endpoint {
+                               remote-endpoint = <&hdmi_tx_tmds_out>;
+                       };
+               };
+       };
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x0 0x0 0x0 0x40000000>;
+       };
+
+       reserved-memory {
+               /* TEE Reserved Memory */
+               bl32_reserved: bl32@5000000 {
+                       reg = <0x0 0x05300000 0x0 0x2000000>;
+                       no-map;
+               };
+       };
+
+       vddao_3v3: regulator-vddao_3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDAO_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&dc_in>;
+               regulator-always-on;
+       };
+
+       vddao_3v3_t: regultor-vddao_3v3_t {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDAO_3V3_T";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&vddao_3v3>;
+               gpio = <&gpio GPIOH_8 GPIO_OPEN_DRAIN>;
+               enable-active-high;
+       };
+
+       vddio_ao1v8: regulator-vddio_ao1v8 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDIO_AO1V8";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vddao_3v3>;
+               regulator-always-on;
+       };
+};
+
+&cec_AO {
+       pinctrl-0 = <&cec_ao_a_h_pins>;
+       pinctrl-names = "default";
+       status = "disabled";
+       hdmi-phandle = <&hdmi_tx>;
+};
+
+&cecb_AO {
+       pinctrl-0 = <&cec_ao_b_h_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+       hdmi-phandle = <&hdmi_tx>;
+};
+
+&cvbs_vdac_port {
+       cvbs_vdac_out: endpoint {
+               remote-endpoint = <&cvbs_connector_in>;
+       };
+};
+
+&saradc {
+       status = "okay";
+       vref-supply = <&vddio_ao1v8>;
+};
+
+&uart_A {
+       status = "okay";
+       pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
+       pinctrl-names = "default";
+       uart-has-rtscts;
+
+       bluetooth {
+               compatible = "brcm,bcm43438-bt";
+               shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
+       };
+};
+
+&hdmi_tx {
+       status = "okay";
+       pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>;
+       pinctrl-names = "default";
+};
+
+&hdmi_tx_tmds_port {
+       hdmi_tx_tmds_out: endpoint {
+               remote-endpoint = <&hdmi_connector_in>;
+       };
+};
+
+&uart_AO {
+       status = "okay";
+       pinctrl-0 = <&uart_ao_a_pins>;
+       pinctrl-names = "default";
+};
+
+&usb {
+       status = "okay";
+       dr_mode = "host";
+};
index c44dbdd..0e8045b 100644 (file)
@@ -6,6 +6,8 @@
 /dts-v1/;
 
 #include "meson-g12a.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/gpio/meson-g12a-gpio.h>
 
 / {
        compatible = "amlogic,u200", "amlogic,g12a";
                device_type = "memory";
                reg = <0x0 0x0 0x0 0x40000000>;
        };
+
+       cvbs-connector {
+               compatible = "composite-video-connector";
+
+               port {
+                       cvbs_connector_in: endpoint {
+                               remote-endpoint = <&cvbs_vdac_out>;
+                       };
+               };
+       };
+
+       flash_1v8: regulator-flash_1v8 {
+               compatible = "regulator-fixed";
+               regulator-name = "FLASH_1V8";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vcc_3v3>;
+               regulator-always-on;
+       };
+
+       hdmi-connector {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_connector_in: endpoint {
+                               remote-endpoint = <&hdmi_tx_tmds_out>;
+                       };
+               };
+       };
+
+       main_12v: regulator-main_12v {
+               compatible = "regulator-fixed";
+               regulator-name = "12V";
+               regulator-min-microvolt = <12000000>;
+               regulator-max-microvolt = <12000000>;
+               regulator-always-on;
+       };
+
+       vcc_1v8: regulator-vcc_1v8 {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC_1V8";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vcc_3v3>;
+               regulator-always-on;
+       };
+
+       vcc_3v3: regulator-vcc_3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&vddao_3v3>;
+               regulator-always-on;
+               /* FIXME: actually controlled by VDDCPU_B_EN */
+       };
+
+       vcc_5v: regulator-vcc_5v {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC_5V";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               vin-supply = <&main_12v>;
+
+               gpio = <&gpio GPIOH_8 GPIO_OPEN_DRAIN>;
+               enable-active-high;
+       };
+
+       usb_pwr_en: regulator-usb_pwr_en {
+               compatible = "regulator-fixed";
+               regulator-name = "USB_PWR_EN";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               vin-supply = <&vcc_5v>;
+
+               gpio = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       vddao_1v8: regulator-vddao_1v8 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDAO_1V8";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vddao_3v3>;
+               regulator-always-on;
+       };
+
+       vddao_3v3: regulator-vddao_3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDAO_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&main_12v>;
+               regulator-always-on;
+       };
+
+};
+
+&cec_AO {
+       pinctrl-0 = <&cec_ao_a_h_pins>;
+       pinctrl-names = "default";
+       status = "disabled";
+       hdmi-phandle = <&hdmi_tx>;
+};
+
+&cecb_AO {
+       pinctrl-0 = <&cec_ao_b_h_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+       hdmi-phandle = <&hdmi_tx>;
+};
+
+&cvbs_vdac_port {
+       cvbs_vdac_out: endpoint {
+               remote-endpoint = <&cvbs_connector_in>;
+       };
+};
+
+&hdmi_tx {
+       status = "okay";
+       pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>;
+       pinctrl-names = "default";
+       hdmi-supply = <&vcc_5v>;
+};
+
+&hdmi_tx_tmds_port {
+       hdmi_tx_tmds_out: endpoint {
+               remote-endpoint = <&hdmi_connector_in>;
+       };
 };
 
 &uart_AO {
        status = "okay";
+       pinctrl-0 = <&uart_ao_a_pins>;
+       pinctrl-names = "default";
 };
 
+&usb {
+       status = "okay";
+       vbus-supply = <&usb_pwr_en>;
+};
+
+&usb2_phy0 {
+       phy-supply = <&vcc_5v>;
+};
+
+&usb2_phy1 {
+       phy-supply = <&vcc_5v>;
+};
index c62d3d5..b3d913f 100644 (file)
@@ -6,6 +6,8 @@
 /dts-v1/;
 
 #include "meson-g12a.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/gpio/meson-g12a-gpio.h>
 
 / {
        compatible = "amediatech,x96-max", "amlogic,u200", "amlogic,g12a";
                device_type = "memory";
                reg = <0x0 0x0 0x0 0x40000000>;
        };
+
+       cvbs-connector {
+               compatible = "composite-video-connector";
+
+               port {
+                       cvbs_connector_in: endpoint {
+                               remote-endpoint = <&cvbs_vdac_out>;
+                       };
+               };
+       };
+
+       hdmi-connector {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_connector_in: endpoint {
+                               remote-endpoint = <&hdmi_tx_tmds_out>;
+                       };
+               };
+       };
+
+       flash_1v8: regulator-flash_1v8 {
+               compatible = "regulator-fixed";
+               regulator-name = "FLASH_1V8";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vcc_3v3>;
+               regulator-always-on;
+       };
+
+       dc_in: regulator-dc_in {
+               compatible = "regulator-fixed";
+               regulator-name = "DC_IN";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+
+       vcc_1v8: regulator-vcc_1v8 {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC_1V8";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vcc_3v3>;
+               regulator-always-on;
+       };
+
+       vcc_3v3: regulator-vcc_3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&vddao_3v3>;
+               regulator-always-on;
+               /* FIXME: actually controlled by VDDCPU_B_EN */
+       };
+
+       vcc_5v: regulator-vcc_5v {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC_5V";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               vin-supply = <&dc_in>;
+
+               gpio = <&gpio GPIOH_8 GPIO_OPEN_DRAIN>;
+               enable-active-low;
+       };
+
+       vddao_1v8: regulator-vddao_1v8 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDAO_1V8";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vddao_3v3>;
+               regulator-always-on;
+       };
+
+       vddao_3v3: regulator-vddao_3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDAO_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&dc_in>;
+               regulator-always-on;
+       };
+};
+
+&cec_AO {
+       pinctrl-0 = <&cec_ao_a_h_pins>;
+       pinctrl-names = "default";
+       status = "disabled";
+       hdmi-phandle = <&hdmi_tx>;
+};
+
+&cecb_AO {
+       pinctrl-0 = <&cec_ao_b_h_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+       hdmi-phandle = <&hdmi_tx>;
+};
+
+&cvbs_vdac_port {
+       cvbs_vdac_out: endpoint {
+               remote-endpoint = <&cvbs_connector_in>;
+       };
+};
+
+&hdmi_tx {
+       status = "okay";
+       pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>;
+       pinctrl-names = "default";
+       hdmi-supply = <&vcc_5v>;
+};
+
+&hdmi_tx_tmds_port {
+       hdmi_tx_tmds_out: endpoint {
+               remote-endpoint = <&hdmi_connector_in>;
+       };
+};
+
+&uart_A {
+       status = "okay";
+       pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
+       pinctrl-names = "default";
+       uart-has-rtscts;
+
+       bluetooth {
+               compatible = "brcm,bcm43438-bt";
+               shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
+       };
 };
 
 &uart_AO {
        status = "okay";
+       pinctrl-0 = <&uart_ao_a_pins>;
+       pinctrl-names = "default";
+};
+
+&usb {
+       status = "okay";
+       dr_mode = "host";
 };
index 17c6217..9f72396 100644 (file)
@@ -3,9 +3,13 @@
  * Copyright (c) 2018 Amlogic, Inc. All rights reserved.
  */
 
+#include <dt-bindings/phy/phy.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/g12a-clkc.h>
+#include <dt-bindings/clock/g12a-aoclkc.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/amlogic,meson-g12a-reset.h>
 
 / {
        compatible = "amlogic,g12a";
                };
        };
 
+       efuse: efuse {
+               compatible = "amlogic,meson-gxbb-efuse";
+               clocks = <&clkc CLKID_EFUSE>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               read-only;
+       };
+
        psci {
                compatible = "arm,psci-1.0";
                method = "smc";
                        reg = <0x0 0x05000000 0x0 0x300000>;
                        no-map;
                };
+
+               linux,cma {
+                       compatible = "shared-dma-pool";
+                       reusable;
+                       size = <0x0 0x10000000>;
+                       alignment = <0x0 0x400000>;
+                       linux,cma-default;
+               };
+       };
+
+       sm: secure-monitor {
+               compatible = "amlogic,meson-gxbb-sm";
        };
 
        soc {
                        #size-cells = <2>;
                        ranges = <0x0 0x0 0x0 0xff600000 0x0 0x200000>;
 
+                       hdmi_tx: hdmi-tx@0 {
+                               compatible = "amlogic,meson-g12a-dw-hdmi";
+                               reg = <0x0 0x0 0x0 0x10000>;
+                               interrupts = <GIC_SPI 57 IRQ_TYPE_EDGE_RISING>;
+                               resets = <&reset RESET_HDMITX_CAPB3>,
+                                        <&reset RESET_HDMITX_PHY>,
+                                        <&reset RESET_HDMITX>;
+                               reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy";
+                               clocks = <&clkc CLKID_HDMI>,
+                                        <&clkc CLKID_HTX_PCLK>,
+                                        <&clkc CLKID_VPU_INTR>;
+                               clock-names = "isfr", "iahb", "venci";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+
+                               /* VPU VENC Input */
+                               hdmi_tx_venc_port: port@0 {
+                                       reg = <0>;
+
+                                       hdmi_tx_in: endpoint {
+                                               remote-endpoint = <&hdmi_tx_out>;
+                                       };
+                               };
+
+                               /* TMDS Output */
+                               hdmi_tx_tmds_port: port@1 {
+                                       reg = <1>;
+                               };
+                       };
+
                        periphs: bus@34400 {
                                compatible = "simple-bus";
                                reg = <0x0 0x34400 0x0 0x400>;
                                #address-cells = <2>;
                                #size-cells = <2>;
                                ranges = <0x0 0x0 0x0 0x34400 0x0 0x400>;
+
+                               periphs_pinctrl: pinctrl@40 {
+                                       compatible = "amlogic,meson-g12a-periphs-pinctrl";
+                                       #address-cells = <2>;
+                                       #size-cells = <2>;
+                                       ranges;
+
+                                       gpio: bank@40 {
+                                               reg = <0x0 0x40  0x0 0x4c>,
+                                                     <0x0 0xe8  0x0 0x18>,
+                                                     <0x0 0x120 0x0 0x18>,
+                                                     <0x0 0x2c0 0x0 0x40>,
+                                                     <0x0 0x340 0x0 0x1c>;
+                                               reg-names = "gpio",
+                                                           "pull",
+                                                           "pull-enable",
+                                                           "mux",
+                                                           "ds";
+                                               gpio-controller;
+                                               #gpio-cells = <2>;
+                                               gpio-ranges = <&periphs_pinctrl 0 0 86>;
+                                       };
+
+                                       cec_ao_a_h_pins: cec_ao_a_h {
+                                               mux {
+                                                       groups = "cec_ao_a_h";
+                                                       function = "cec_ao_a_h";
+                                                       bias-disable;
+                                               };
+                                       };
+
+                                       cec_ao_b_h_pins: cec_ao_b_h {
+                                               mux {
+                                                       groups = "cec_ao_b_h";
+                                                       function = "cec_ao_b_h";
+                                                       bias-disable;
+                                               };
+                                       };
+
+                                       hdmitx_ddc_pins: hdmitx_ddc {
+                                               mux {
+                                                       groups = "hdmitx_sda",
+                                                                "hdmitx_sck";
+                                                       function = "hdmitx";
+                                                       bias-disable;
+                                               };
+                                       };
+
+                                       hdmitx_hpd_pins: hdmitx_hpd {
+                                               mux {
+                                                       groups = "hdmitx_hpd_in";
+                                                       function = "hdmitx";
+                                                       bias-disable;
+                                               };
+                                       };
+
+                                       uart_a_pins: uart-a {
+                                               mux {
+                                                       groups = "uart_a_tx",
+                                                                "uart_a_rx";
+                                                       function = "uart_a";
+                                                       bias-disable;
+                                               };
+                                       };
+
+                                       uart_a_cts_rts_pins: uart-a-cts-rts {
+                                               mux {
+                                                       groups = "uart_a_cts",
+                                                                "uart_a_rts";
+                                                       function = "uart_a";
+                                                       bias-disable;
+                                               };
+                                       };
+
+                                       uart_b_pins: uart-b {
+                                               mux {
+                                                       groups = "uart_b_tx",
+                                                                "uart_b_rx";
+                                                       function = "uart_b";
+                                                       bias-disable;
+                                               };
+                                       };
+
+                                       uart_c_pins: uart-c {
+                                               mux {
+                                                       groups = "uart_c_tx",
+                                                                "uart_c_rx";
+                                                       function = "uart_c";
+                                                       bias-disable;
+                                               };
+                                       };
+
+                                       uart_c_cts_rts_pins: uart-c-cts-rts {
+                                               mux {
+                                                       groups = "uart_c_cts",
+                                                                "uart_c_rts";
+                                                       function = "uart_c";
+                                                       bias-disable;
+                                               };
+                                       };
+                               };
+                       };
+
+                       usb2_phy0: phy@36000 {
+                               compatible = "amlogic,g12a-usb2-phy";
+                               reg = <0x0 0x36000 0x0 0x2000>;
+                               clocks = <&xtal>;
+                               clock-names = "xtal";
+                               resets = <&reset RESET_USB_PHY20>;
+                               reset-names = "phy";
+                               #phy-cells = <0>;
+                       };
+
+                       dmc: bus@38000 {
+                               compatible = "simple-bus";
+                               reg = <0x0 0x38000 0x0 0x400>;
+                               #address-cells = <2>;
+                               #size-cells = <2>;
+                               ranges = <0x0 0x0 0x0 0x38000 0x0 0x400>;
+
+                               canvas: video-lut@48 {
+                                       compatible = "amlogic,canvas";
+                                       reg = <0x0 0x48 0x0 0x14>;
+                               };
+                       };
+
+                       usb2_phy1: phy@3a000 {
+                               compatible = "amlogic,g12a-usb2-phy";
+                               reg = <0x0 0x3a000 0x0 0x2000>;
+                               clocks = <&xtal>;
+                               clock-names = "xtal";
+                               resets = <&reset RESET_USB_PHY21>;
+                               reset-names = "phy";
+                               #phy-cells = <0>;
                        };
 
                        hiu: bus@3c000 {
                                        };
                                };
                        };
+
+                       usb3_pcie_phy: phy@46000 {
+                               compatible = "amlogic,g12a-usb3-pcie-phy";
+                               reg = <0x0 0x46000 0x0 0x2000>;
+                               clocks = <&clkc CLKID_PCIE_PLL>;
+                               clock-names = "ref_clk";
+                               resets = <&reset RESET_PCIE_PHY>;
+                               reset-names = "phy";
+                               assigned-clocks = <&clkc CLKID_PCIE_PLL>;
+                               assigned-clock-rates = <100000000>;
+                               #phy-cells = <1>;
+                       };
                };
 
                aobus: bus@ff800000 {
                        #size-cells = <2>;
                        ranges = <0x0 0x0 0x0 0xff800000 0x0 0x100000>;
 
+                       rti: sys-ctrl@0 {
+                               compatible = "amlogic,meson-gx-ao-sysctrl",
+                                            "simple-mfd", "syscon";
+                               reg = <0x0 0x0 0x0 0x100>;
+                               #address-cells = <2>;
+                               #size-cells = <2>;
+                               ranges = <0x0 0x0 0x0 0x0 0x0 0x100>;
+
+                               clkc_AO: clock-controller {
+                                       compatible = "amlogic,meson-g12a-aoclkc";
+                                       #clock-cells = <1>;
+                                       #reset-cells = <1>;
+                                       clocks = <&xtal>, <&clkc CLKID_CLK81>;
+                                       clock-names = "xtal", "mpeg-clk";
+                               };
+
+                               pwrc_vpu: power-controller-vpu {
+                                       compatible = "amlogic,meson-g12a-pwrc-vpu";
+                                       #power-domain-cells = <0>;
+                                       amlogic,hhi-sysctrl = <&hhi>;
+                                       resets = <&reset RESET_VIU>,
+                                                <&reset RESET_VENC>,
+                                                <&reset RESET_VCBUS>,
+                                                <&reset RESET_BT656>,
+                                                <&reset RESET_RDMA>,
+                                                <&reset RESET_VENCI>,
+                                                <&reset RESET_VENCP>,
+                                                <&reset RESET_VDAC>,
+                                                <&reset RESET_VDI6>,
+                                                <&reset RESET_VENCL>,
+                                                <&reset RESET_VID_LOCK>;
+                                       clocks = <&clkc CLKID_VPU>,
+                                                <&clkc CLKID_VAPB>;
+                                       clock-names = "vpu", "vapb";
+                                       /*
+                                        * VPU clocking is provided by two identical clock paths
+                                        * VPU_0 and VPU_1 muxed to a single clock by a glitch
+                                        * free mux to safely change frequency while running.
+                                        * Same for VAPB but with a final gate after the glitch free mux.
+                                        */
+                                       assigned-clocks = <&clkc CLKID_VPU_0_SEL>,
+                                                         <&clkc CLKID_VPU_0>,
+                                                         <&clkc CLKID_VPU>, /* Glitch free mux */
+                                                         <&clkc CLKID_VAPB_0_SEL>,
+                                                         <&clkc CLKID_VAPB_0>,
+                                                         <&clkc CLKID_VAPB_SEL>; /* Glitch free mux */
+                                       assigned-clock-parents = <&clkc CLKID_FCLK_DIV3>,
+                                                                <0>, /* Do Nothing */
+                                                                <&clkc CLKID_VPU_0>,
+                                                                <&clkc CLKID_FCLK_DIV4>,
+                                                                <0>, /* Do Nothing */
+                                                                <&clkc CLKID_VAPB_0>;
+                                       assigned-clock-rates = <0>, /* Do Nothing */
+                                                              <666666666>,
+                                                              <0>, /* Do Nothing */
+                                                              <0>, /* Do Nothing */
+                                                              <250000000>,
+                                                              <0>; /* Do Nothing */
+                               };
+
+                               ao_pinctrl: pinctrl@14 {
+                                       compatible = "amlogic,meson-g12a-aobus-pinctrl";
+                                       #address-cells = <2>;
+                                       #size-cells = <2>;
+                                       ranges;
+
+                                       gpio_ao: bank@14 {
+                                               reg = <0x0 0x14 0x0 0x8>,
+                                                     <0x0 0x1c 0x0 0x8>,
+                                                     <0x0 0x24 0x0 0x14>;
+                                               reg-names = "mux",
+                                                           "ds",
+                                                           "gpio";
+                                               gpio-controller;
+                                               #gpio-cells = <2>;
+                                               gpio-ranges = <&ao_pinctrl 0 0 15>;
+                                       };
+
+                                       uart_ao_a_pins: uart-a-ao {
+                                               mux {
+                                                       groups = "uart_ao_a_tx",
+                                                                "uart_ao_a_rx";
+                                                       function = "uart_ao_a";
+                                                       bias-disable;
+                                               };
+                                       };
+
+                                       uart_ao_a_cts_rts_pins: uart-ao-a-cts-rts {
+                                               mux {
+                                                       groups = "uart_ao_a_cts",
+                                                                "uart_ao_a_rts";
+                                                       function = "uart_ao_a";
+                                                       bias-disable;
+                                               };
+                                       };
+                               };
+                       };
+
+                       cec_AO: cec@100 {
+                               compatible = "amlogic,meson-gx-ao-cec";
+                               reg = <0x0 0x00100 0x0 0x14>;
+                               interrupts = <GIC_SPI 199 IRQ_TYPE_EDGE_RISING>;
+                               clocks = <&clkc_AO CLKID_AO_CEC>;
+                               clock-names = "core";
+                               status = "disabled";
+                       };
+
+                       sec_AO: ao-secure@140 {
+                               compatible = "amlogic,meson-gx-ao-secure", "syscon";
+                               reg = <0x0 0x140 0x0 0x140>;
+                               amlogic,has-chip-id;
+                       };
+
+                       cecb_AO: cec@280 {
+                               compatible = "amlogic,meson-g12a-ao-cec";
+                               reg = <0x0 0x00280 0x0 0x1c>;
+                               interrupts = <GIC_SPI 203 IRQ_TYPE_EDGE_RISING>;
+                               clocks = <&clkc_AO CLKID_AO_CTS_OSCIN>;
+                               clock-names = "oscin";
+                               status = "disabled";
+                       };
+
                        uart_AO: serial@3000 {
                                compatible = "amlogic,meson-gx-uart",
                                             "amlogic,meson-ao-uart";
                                clock-names = "xtal", "pclk", "baud";
                                status = "disabled";
                        };
+
+                       saradc: adc@9000 {
+                               compatible = "amlogic,meson-g12a-saradc",
+                                            "amlogic,meson-saradc";
+                               reg = <0x0 0x9000 0x0 0x48>;
+                               #io-channel-cells = <1>;
+                               interrupts = <GIC_SPI 200 IRQ_TYPE_EDGE_RISING>;
+                               clocks = <&xtal>,
+                                        <&clkc_AO CLKID_AO_SAR_ADC>,
+                                        <&clkc_AO CLKID_AO_SAR_ADC_CLK>,
+                                        <&clkc_AO CLKID_AO_SAR_ADC_SEL>;
+                               clock-names = "clkin", "core", "adc_clk", "adc_sel";
+                               status = "disabled";
+                       };
+               };
+
+               vpu: vpu@ff900000 {
+                       compatible = "amlogic,meson-g12a-vpu";
+                       reg = <0x0 0xff900000 0x0 0x100000>,
+                             <0x0 0xff63c000 0x0 0x1000>;
+                       reg-names = "vpu", "hhi";
+                       interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       amlogic,canvas = <&canvas>;
+                       power-domains = <&pwrc_vpu>;
+
+                       /* CVBS VDAC output port */
+                       cvbs_vdac_port: port@0 {
+                               reg = <0>;
+                       };
+
+                       /* HDMI-TX output port */
+                       hdmi_tx_port: port@1 {
+                               reg = <1>;
+
+                               hdmi_tx_out: endpoint {
+                                       remote-endpoint = <&hdmi_tx_in>;
+                               };
+                       };
                };
 
                gic: interrupt-controller@ffc01000 {
                        #size-cells = <2>;
                        ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x100000>;
 
+                       reset: reset-controller@1004 {
+                               compatible = "amlogic,meson-g12a-reset",
+                                            "amlogic,meson-axg-reset";
+                               reg = <0x0 0x1004 0x0 0x9c>;
+                               #reset-cells = <1>;
+                       };
+
                        clk_msr: clock-measure@18000 {
                                compatible = "amlogic,meson-g12a-clk-measure";
                                reg = <0x0 0x18000 0x0 0x10>;
                        };
+
+                       uart_C: serial@22000 {
+                               compatible = "amlogic,meson-gx-uart";
+                               reg = <0x0 0x22000 0x0 0x18>;
+                               interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+                               clocks = <&xtal>, <&clkc CLKID_UART2>, <&xtal>;
+                               clock-names = "xtal", "pclk", "baud";
+                               status = "disabled";
+                       };
+
+                       uart_B: serial@23000 {
+                               compatible = "amlogic,meson-gx-uart";
+                               reg = <0x0 0x23000 0x0 0x18>;
+                               interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
+                               clocks = <&xtal>, <&clkc CLKID_UART1>, <&xtal>;
+                               clock-names = "xtal", "pclk", "baud";
+                               status = "disabled";
+                       };
+
+                       uart_A: serial@24000 {
+                               compatible = "amlogic,meson-gx-uart";
+                               reg = <0x0 0x24000 0x0 0x18>;
+                               interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
+                               clocks = <&xtal>, <&clkc CLKID_UART0>, <&xtal>;
+                               clock-names = "xtal", "pclk", "baud";
+                               status = "disabled";
+                       };
+               };
+
+               usb: usb@ffe09000 {
+                       status = "disabled";
+                       compatible = "amlogic,meson-g12a-usb-ctrl";
+                       reg = <0x0 0xffe09000 0x0 0xa0>;
+                       interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+
+                       clocks = <&clkc CLKID_USB>;
+                       resets = <&reset RESET_USB>;
+
+                       dr_mode = "otg";
+
+                       phys = <&usb2_phy0>, <&usb2_phy1>,
+                              <&usb3_pcie_phy PHY_TYPE_USB3>;
+                       phy-names = "usb2-phy0", "usb2-phy1", "usb3-phy0";
+
+                       dwc2: usb@ff400000 {
+                               compatible = "amlogic,meson-g12a-usb", "snps,dwc2";
+                               reg = <0x0 0xff400000 0x0 0x40000>;
+                               interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clkc CLKID_USB1_DDR_BRIDGE>;
+                               clock-names = "ddr";
+                               phys = <&usb2_phy1>;
+                               dr_mode = "peripheral";
+                               g-rx-fifo-size = <192>;
+                               g-np-tx-fifo-size = <128>;
+                               g-tx-fifo-size = <128 128 16 16 16>;
+                       };
+
+                       dwc3: usb@ff500000 {
+                               compatible = "snps,dwc3";
+                               reg = <0x0 0xff500000 0x0 0x100000>;
+                               interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+                               dr_mode = "host";
+                               snps,dis_u2_susphy_quirk;
+                               snps,quirk-frame-length-adjustment;
+                       };
+               };
+
+               mali: gpu@ffe40000 {
+                       compatible = "amlogic,meson-g12a-mali", "arm,mali-bifrost";
+                       reg = <0x0 0xffe40000 0x0 0x40000>;
+                       interrupt-parent = <&gic>;
+                       interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "gpu", "mmu", "job";
+                       clocks = <&clkc CLKID_MALI>;
+                       resets = <&reset RESET_DVALIN_CAPB3>, <&reset RESET_DVALIN>;
+
+                       /*
+                        * Mali clocking is provided by two identical clock paths
+                        * MALI_0 and MALI_1 muxed to a single clock by a glitch
+                        * free mux to safely change frequency while running.
+                        */
+                       assigned-clocks = <&clkc CLKID_MALI_0_SEL>,
+                                         <&clkc CLKID_MALI_0>,
+                                         <&clkc CLKID_MALI>; /* Glitch free mux */
+                       assigned-clock-parents = <&clkc CLKID_FCLK_DIV2P5>,
+                                                <0>, /* Do Nothing */
+                                                <&clkc CLKID_MALI_0>;
+                       assigned-clock-rates = <0>, /* Do Nothing */
+                                              <800000000>,
+                                              <0>; /* Do Nothing */
                };
        };
 
index 9a8a8a7..b5667f1 100644 (file)
        cvbs-connector {
                status = "disabled";
        };
+
+       leds {
+               compatible = "gpio-leds";
+
+               status {
+                       label = "n1:white:status";
+                       gpios = <&gpio_ao GPIOAO_9 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+               };
+       };
 };
 
 &cvbs_vdac_port {
index 8acfd40..25f3b6b 100644 (file)
        pinctrl-0 = <&uart_ao_a_pins>;
        pinctrl-names = "default";
 };
+
+&usb0 {
+       status = "okay";
+};
index ed3a3d5..7a85a82 100644 (file)
                reset-names = "phy";
                status = "okay";
        };
+
+       mali: gpu@c0000 {
+               compatible = "amlogic,meson-gxm-mali", "arm,mali-t820";
+               reg = <0x0 0xc0000 0x0 0x40000>;
+               interrupt-parent = <&gic>;
+               interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "gpu", "mmu", "job";
+               clocks = <&clkc CLKID_MALI>;
+               resets = <&reset RESET_MALI_CAPB3>, <&reset RESET_MALI>;
+
+               /*
+                * Mali clocking is provided by two identical clock paths
+                * MALI_0 and MALI_1 muxed to a single clock by a glitch
+                * free mux to safely change frequency while running.
+                */
+               assigned-clocks = <&clkc CLKID_MALI_0_SEL>,
+                                 <&clkc CLKID_MALI_0>,
+                                 <&clkc CLKID_MALI>; /* Glitch free mux */
+               assigned-clock-parents = <&clkc CLKID_FCLK_DIV3>,
+                                        <0>, /* Do Nothing */
+                                        <&clkc CLKID_MALI_0>;
+               assigned-clock-rates = <0>, /* Do Nothing */
+                                      <666666666>,
+                                      <0>; /* Do Nothing */
+       };
 };
 
 &clkc_AO {
index 6a32555..3e8c707 100644 (file)
@@ -8,6 +8,28 @@
 
 #include "bm1880.dtsi"
 
+/*
+ * GPIO name legend: proper name = the GPIO line is used as GPIO
+ *         NC = not connected (pin out but not routed from the chip to
+ *              anything the board)
+ *         "[PER]" = pin is muxed for [peripheral] (not GPIO)
+ *         LSEC = Low Speed External Connector
+ *         HSEC = High Speed External Connector
+ *
+ * Line names are taken from the schematic "sophon-edge-schematics"
+ * version, 1.0210.
+ *
+ * For the lines routed to the external connectors the
+ * lines are named after the 96Boards CE Specification 1.0,
+ * Appendix "Expansion Connector Signal Description".
+ *
+ * When the 96Board naming of a line and the schematic name of
+ * the same line are in conflict, the 96Board specification
+ * takes precedence. This is only for the informational
+ * lines i.e. "[FOO]", the GPIO named lines "GPIO-A" thru "GPIO-L"
+ * are the only ones actually used for GPIO.
+ */
+
 / {
        compatible = "bitmain,sophon-edge", "bitmain,bm1880";
        model = "Sophon Edge";
                clock-frequency = <500000000>;
                #clock-cells = <0>;
        };
+
+       soc {
+               gpio0: gpio@50027000 {
+                       porta: gpio-controller@0 {
+                               gpio-line-names =
+                                       "GPIO-A", /* GPIO0, LSEC pin 23 */
+                                       "GPIO-C", /* GPIO1, LSEC pin 25 */
+                                       "[GPIO2_PHY0_RST]", /* GPIO2 */
+                                       "GPIO-E", /* GPIO3, LSEC pin 27 */
+                                       "[USB_DET]", /* GPIO4 */
+                                       "[EN_P5V]", /* GPIO5 */
+                                       "[VDDIO_MS1_SEL]", /* GPIO6 */
+                                       "GPIO-G", /* GPIO7, LSEC pin 29 */
+                                       "[BM_TUSB_RST_L]", /* GPIO8 */
+                                       "[EN_P5V_USBHUB]", /* GPIO9 */
+                                       "NC",
+                                       "LED_WIFI", /* GPIO11 */
+                                       "LED_BT", /* GPIO12 */
+                                       "[BM_BLM8221_EN_L]", /* GPIO13 */
+                                       "NC", /* GPIO14 */
+                                       "NC", /* GPIO15 */
+                                       "NC", /* GPIO16 */
+                                       "NC", /* GPIO17 */
+                                       "NC", /* GPIO18 */
+                                       "NC", /* GPIO19 */
+                                       "NC", /* GPIO20 */
+                                       "NC", /* GPIO21 */
+                                       "NC", /* GPIO22 */
+                                       "NC", /* GPIO23 */
+                                       "NC", /* GPIO24 */
+                                       "NC", /* GPIO25 */
+                                       "NC", /* GPIO26 */
+                                       "NC", /* GPIO27 */
+                                       "NC", /* GPIO28 */
+                                       "NC", /* GPIO29 */
+                                       "NC", /* GPIO30 */
+                                       "NC"; /* GPIO31 */
+                       };
+               };
+
+               gpio1: gpio@50027400 {
+                       portb: gpio-controller@0 {
+                               gpio-line-names =
+                                       "NC", /* GPIO32 */
+                                       "NC", /* GPIO33 */
+                                       "[I2C0_SDA]", /* GPIO34, LSEC pin 17 */
+                                       "[I2C0_SCL]", /* GPIO35, LSEC pin 15 */
+                                       "[JTAG0_TDO]", /* GPIO36 */
+                                       "[JTAG0_TCK]", /* GPIO37 */
+                                       "[JTAG0_TDI]", /* GPIO38 */
+                                       "[JTAG0_TMS]", /* GPIO39 */
+                                       "[JTAG0_TRST_X]", /* GPIO40 */
+                                       "[JTAG1_TDO]", /* GPIO41 */
+                                       "[JTAG1_TCK]", /* GPIO42 */
+                                       "[JTAG1_TDI]", /* GPIO43 */
+                                       "[CPU_TX]", /* GPIO44 */
+                                       "[CPU_RX]", /* GPIO45 */
+                                       "[UART1_TXD]", /* GPIO46 */
+                                       "[UART1_RXD]", /* GPIO47 */
+                                       "[UART0_TXD]", /* GPIO48 */
+                                       "[UART0_RXD]", /* GPIO49 */
+                                       "GPIO-I", /* GPIO50, LSEC pin 31 */
+                                       "GPIO-K", /* GPIO51, LSEC pin 33 */
+                                       "USER_LED2", /* GPIO52 */
+                                       "USER_LED1", /* GPIO53 */
+                                       "[UART0_RTS]", /* GPIO54 */
+                                       "[UART0_CTS]", /* GPIO55 */
+                                       "USER_LED4", /* GPIO56, JTAG1_TRST_X */
+                                       "USER_LED3", /* GPIO57, JTAG1_TMS */
+                                       "[I2S0_SCLK]", /* GPIO58 */
+                                       "[I2S0_FS]", /* GPIO59 */
+                                       "[I2S0_SDI]", /* GPIO60 */
+                                       "[I2S0_SDO]", /* GPIO61 */
+                                       "GPIO-B", /* GPIO62, LSEC pin 24 */
+                                       "GPIO-F"; /* GPIO63, I2S1_SCLK, LSEC pin 28 */
+                       };
+               };
+
+               gpio2: gpio@50027800 {
+                       portc: gpio-controller@0 {
+                               gpio-line-names =
+                                       "GPIO-D", /* GPIO64, I2S1_FS, LSEC pin 26 */
+                                       "GPIO-J", /* GPIO65, I2S1_SDI, LSEC pin 32 */
+                                       "GPIO-H", /* GPIO66, I2S1_SDO, LSEC pin 30 */
+                                       "GPIO-L", /* GPIO67, LSEC pin 34 */
+                                       "[SPI0_CS]", /* GPIO68, SPI1_CS, LSEC pin 12 */
+                                       "[SPI0_DIN]", /* GPIO69, SPI1_SDI, LSEC pin 10 */
+                                       "[SPI0_DOUT]", /* GPIO70, SPI1_SDO, LSEC pin 14 */
+                                       "[SPI0_SCLK]"; /* GPIO71, SPI1_SCK, LSEC pin 8 */
+                       };
+               };
+       };
+};
+
+&pinctrl {
+       pinctrl_uart0_default: pinctrl-uart0-default {
+               pinmux {
+                       groups = "uart0_grp";
+                       function = "uart0";
+               };
+       };
+
+       pinctrl_uart1_default: pinctrl-uart1-default {
+               pinmux {
+                       groups = "uart1_grp";
+                       function = "uart1";
+               };
+       };
+
+       pinctrl_uart2_default: pinctrl-uart2-default {
+               pinmux {
+                       groups = "uart2_grp";
+                       function = "uart2";
+               };
+       };
 };
 
 &uart0 {
        status = "okay";
        clocks = <&uart_clk>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart0_default>;
 };
 
 &uart1 {
        status = "okay";
        clocks = <&uart_clk>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1_default>;
 };
 
 &uart2 {
        status = "okay";
        clocks = <&uart_clk>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2_default>;
 };
index 55a4769..7726fd4 100644 (file)
                        #interrupt-cells = <3>;
                };
 
+               sctrl: system-controller@50010000 {
+                       compatible = "bitmain,bm1880-sctrl", "syscon",
+                                    "simple-mfd";
+                       reg = <0x0 0x50010000 0x0 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x0 0x50010000 0x1000>;
+
+                       pinctrl: pinctrl@50 {
+                               compatible = "bitmain,bm1880-pinctrl";
+                               reg = <0x50 0x4B0>;
+                       };
+               };
+
+               gpio0: gpio@50027000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,dw-apb-gpio";
+                       reg = <0x0 0x50027000 0x0 0x400>;
+
+                       porta: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <32>;
+                               reg = <0>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               gpio1: gpio@50027400 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,dw-apb-gpio";
+                       reg = <0x0 0x50027400 0x0 0x400>;
+
+                       portb: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <32>;
+                               reg = <0>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               gpio2: gpio@50027800 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,dw-apb-gpio";
+                       reg = <0x0 0x50027800 0x0 0x400>;
+
+                       portc: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <8>;
+                               reg = <0>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
                uart0: serial@58018000 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x0 0x58018000 0x0 0x2000>;
index d88e2f0..d2de166 100644 (file)
        assigned-clock-parents = <&cmu_top CLK_ACLK_MFC_400>;
 };
 
+&cmu_mif {
+       assigned-clocks = <&cmu_mif CLK_MOUT_SCLK_DSD_A>, <&cmu_mif CLK_DIV_SCLK_DSD>;
+       assigned-clock-parents = <&cmu_mif CLK_MOUT_MFC_PLL_DIV2>;
+       assigned-clock-rates = <0>, <333000000>;
+};
+
 &cmu_mscl {
        assigned-clocks = <&cmu_mscl CLK_MOUT_ACLK_MSCL_400_USER>,
                          <&cmu_mscl CLK_MOUT_SCLK_JPEG_USER>,
index 3d7e0a7..dda5d27 100644 (file)
@@ -33,7 +33,8 @@
                          <&cmu_disp CLK_MOUT_DISP_PLL>,
                          <&cmu_mif CLK_MOUT_SCLK_DECON_TV_ECLK_A>,
                          <&cmu_disp CLK_MOUT_SCLK_DECON_TV_ECLK_USER>,
-                         <&cmu_disp CLK_MOUT_SCLK_DECON_TV_ECLK>;
+                         <&cmu_disp CLK_MOUT_SCLK_DECON_TV_ECLK>,
+                         <&cmu_disp CLK_MOUT_SCLK_DSD_USER>;
        assigned-clock-parents = <0>, <0>,
                                 <&cmu_mif CLK_ACLK_DISP_333>,
                                 <&cmu_mif CLK_SCLK_DSIM0_DISP>,
@@ -45,7 +46,8 @@
                                 <&cmu_disp CLK_FOUT_DISP_PLL>,
                                 <&cmu_mif CLK_MOUT_BUS_PLL_DIV2>,
                                 <&cmu_mif CLK_SCLK_DECON_TV_ECLK_DISP>,
-                                <&cmu_disp CLK_MOUT_SCLK_DECON_TV_ECLK_USER>;
+                                <&cmu_disp CLK_MOUT_SCLK_DECON_TV_ECLK_USER>,
+                                <&cmu_mif CLK_SCLK_DSD_DISP>;
        assigned-clock-rates = <250000000>, <400000000>;
 };
 
index a04e803..d29d13f 100644 (file)
 
        interrupt-parent = <&gic>;
 
+       arm_a53_pmu {
+               compatible = "arm,cortex-a53-pmu", "arm,armv8-pmuv3";
+               interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+       };
+
+       arm_a57_pmu {
+               compatible = "arm,cortex-a57-pmu", "arm,armv8-pmuv3";
+               interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-affinity = <&cpu4>, <&cpu5>, <&cpu6>, <&cpu7>;
+       };
+
+       xxti: clock {
+               /* XXTI */
+               compatible = "fixed-clock";
+               clock-output-names = "oscclk";
+               #clock-cells = <0>;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
                #size-cells = <1>;
                ranges;
 
-               arm_a53_pmu {
-                       compatible = "arm,cortex-a53-pmu", "arm,armv8-pmuv3";
-                       interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
-               };
-
-               arm_a57_pmu {
-                       compatible = "arm,cortex-a57-pmu", "arm,armv8-pmuv3";
-                       interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-affinity = <&cpu4>, <&cpu5>, <&cpu6>, <&cpu7>;
-               };
-
                chipid@10000000 {
                        compatible = "samsung,exynos4210-chipid";
                        reg = <0x10000000 0x100>;
                };
 
-               xxti: xxti {
-                       compatible = "fixed-clock";
-                       clock-output-names = "oscclk";
-                       #clock-cells = <0>;
-               };
-
                cmu_top: clock-controller@10030000 {
                        compatible = "samsung,exynos5433-cmu-top";
                        reg = <0x10030000 0x1000>;
                                <&cmu_top CLK_DIV_ACLK_IMEM_200>;
                };
 
+               slim_sss: slim-sss@11140000 {
+                       compatible = "samsung,exynos5433-slim-sss";
+                       reg = <0x11140000 0x1000>;
+                       interrupts = <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-names = "aclk", "pclk";
+                       clocks = <&cmu_imem CLK_ACLK_SLIMSSS>,
+                                <&cmu_imem CLK_PCLK_SLIMSSS>;
+               };
+
                pd_gscl: power-domain@105c4000 {
                        compatible = "samsung,exynos5433-pd";
                        reg = <0x105c4000 0x20>;
                                <&cmu_disp CLK_ACLK_XIU_DECON1X>,
                                <&cmu_disp CLK_PCLK_SMMU_DECON1X>,
                                <&cmu_disp CLK_SCLK_DECON_VCLK>,
-                               <&cmu_disp CLK_SCLK_DECON_ECLK>;
+                               <&cmu_disp CLK_SCLK_DECON_ECLK>,
+                               <&cmu_disp CLK_SCLK_DSD>;
                        clock-names = "pclk", "aclk_decon", "aclk_smmu_decon0x",
                                "aclk_xiu_decon0x", "pclk_smmu_decon0x",
                                "aclk_smmu_decon1x", "aclk_xiu_decon1x",
                                "pclk_smmu_decon1x", "sclk_decon_vclk",
-                               "sclk_decon_eclk";
+                               "sclk_decon_eclk", "dsd";
                        power-domains = <&pd_disp>;
                        interrupt-names = "fifo", "vsync", "lcd_sys";
                        interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>,
                                 <&cmu_disp CLK_ACLK_XIU_TV1X>,
                                 <&cmu_disp CLK_PCLK_SMMU_TV1X>,
                                 <&cmu_disp CLK_SCLK_DECON_TV_VCLK>,
-                                <&cmu_disp CLK_SCLK_DECON_TV_ECLK>;
+                                <&cmu_disp CLK_SCLK_DECON_TV_ECLK>,
+                                <&cmu_disp CLK_SCLK_DSD>;
                        clock-names = "pclk", "aclk_decon", "aclk_smmu_decon0x",
                                      "aclk_xiu_decon0x", "pclk_smmu_decon0x",
                                      "aclk_smmu_decon1x", "aclk_xiu_decon1x",
                                      "pclk_smmu_decon1x", "sclk_decon_vclk",
-                                     "sclk_decon_eclk";
+                                     "sclk_decon_eclk", "dsd";
                        samsung,disp-sysreg = <&syscon_disp>;
                        power-domains = <&pd_disp>;
                        interrupt-names = "fifo", "vsync", "lcd_sys";
                        reg = <0x13c00000 0x1000>;
                        interrupts = <GIC_SPI 297 IRQ_TYPE_LEVEL_HIGH>;
                        clock-names = "pclk", "aclk", "aclk_xiu",
-                                     "aclk_gsclbend";
+                                     "aclk_gsclbend", "gsd";
                        clocks = <&cmu_gscl CLK_PCLK_GSCL0>,
                                 <&cmu_gscl CLK_ACLK_GSCL0>,
                                 <&cmu_gscl CLK_ACLK_XIU_GSCLX>,
-                                <&cmu_gscl CLK_ACLK_GSCLBEND_333>;
+                                <&cmu_gscl CLK_ACLK_GSCLBEND_333>,
+                                <&cmu_gscl CLK_ACLK_GSD>;
                        iommus = <&sysmmu_gscl0>;
                        power-domains = <&pd_gscl>;
                };
                        reg = <0x13c10000 0x1000>;
                        interrupts = <GIC_SPI 298 IRQ_TYPE_LEVEL_HIGH>;
                        clock-names = "pclk", "aclk", "aclk_xiu",
-                                     "aclk_gsclbend";
+                                     "aclk_gsclbend", "gsd";
                        clocks = <&cmu_gscl CLK_PCLK_GSCL1>,
                                 <&cmu_gscl CLK_ACLK_GSCL1>,
                                 <&cmu_gscl CLK_ACLK_XIU_GSCLX>,
-                                <&cmu_gscl CLK_ACLK_GSCLBEND_333>;
+                                <&cmu_gscl CLK_ACLK_GSCLBEND_333>,
+                                <&cmu_gscl CLK_ACLK_GSD>;
                        iommus = <&sysmmu_gscl1>;
                        power-domains = <&pd_gscl>;
                };
                        reg = <0x13c20000 0x1000>;
                        interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
                        clock-names = "pclk", "aclk", "aclk_xiu",
-                                     "aclk_gsclbend";
+                                     "aclk_gsclbend", "gsd";
                        clocks = <&cmu_gscl CLK_PCLK_GSCL2>,
                                 <&cmu_gscl CLK_ACLK_GSCL2>,
                                 <&cmu_gscl CLK_ACLK_XIU_GSCLX>,
-                                <&cmu_gscl CLK_ACLK_GSCLBEND_333>;
+                                <&cmu_gscl CLK_ACLK_GSCLBEND_333>,
+                                <&cmu_gscl CLK_ACLK_GSD>;
                        iommus = <&sysmmu_gscl2>;
                        power-domains = <&pd_gscl>;
                };
index 967558a..077d234 100644 (file)
                tmuctrl0 = &tmuctrl_0;
        };
 
+       arm-pmu {
+               compatible = "arm,cortex-a57-pmu", "arm,armv8-pmuv3";
+               interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-affinity = <&cpu_atlas0>, <&cpu_atlas1>,
+                                    <&cpu_atlas2>, <&cpu_atlas3>;
+       };
+
+       fin_pll: clock {
+               /* XXTI */
+               compatible = "fixed-clock";
+               clock-output-names = "fin_pll";
+               #clock-cells = <0>;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
                        reg = <0x10000000 0x100>;
                };
 
-               fin_pll: xxti {
-                       compatible = "fixed-clock";
-                       clock-output-names = "fin_pll";
-                       #clock-cells = <0>;
-               };
-
                gic: interrupt-controller@11001000 {
                        compatible = "arm,gic-400";
                        #interrupt-cells = <3>;
                        status = "disabled";
                };
 
-               arm-pmu {
-                       compatible = "arm,cortex-a57-pmu", "arm,armv8-pmuv3";
-                       interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-affinity = <&cpu_atlas0>, <&cpu_atlas1>,
-                                            <&cpu_atlas2>, <&cpu_atlas3>;
-               };
-
-               timer {
-                       compatible = "arm,armv8-timer";
-                       interrupts = <GIC_PPI 13
-                                       (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
-                                    <GIC_PPI 14
-                                       (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
-                                    <GIC_PPI 11
-                                       (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
-                                    <GIC_PPI 10
-                                       (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
-               };
-
                pmu_system_controller: system-controller@105c0000 {
                        compatible = "samsung,exynos7-pmu", "syscon";
                        reg = <0x105c0000 0x5000>;
                        };
                };
        };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <GIC_PPI 13
+                               (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 14
+                               (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 11
+                               (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 10
+                               (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+       };
 };
 
 #include "exynos7-pinctrl.dtsi"
index 13604e5..0bd122f 100644 (file)
@@ -20,5 +20,8 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-rdb.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-qds.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb
 
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-rmb3.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-zest.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8qxp-mek.dtb
index 7c72626..9927b09 100644 (file)
        status = "okay";
 };
 
+&pcie {
+       status = "okay";
+};
+
 &sai2 {
        status = "okay";
 };
index 1ce0042..ec6257a 100644 (file)
                        interrupts = <0 126 IRQ_TYPE_LEVEL_HIGH>;
                };
 
-               pcie@3400000 {
+               pcie: pcie@3400000 {
                        compatible = "fsl,ls1012a-pcie";
                        reg = <0x00 0x03400000 0x0 0x00100000   /* controller registers */
                               0x40 0x00000000 0x0 0x00002000>; /* configuration space */
index 14c79f4..b359068 100644 (file)
                device_type = "memory";
                reg = <0x0 0x80000000 0x1 0x00000000>;
        };
+
+       sys_mclk: clock-mclk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <25000000>;
+       };
+
+       reg_1p8v: regulator-1p8v {
+               compatible = "regulator-fixed";
+               regulator-name = "1P8V";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-always-on;
+       };
+
+       sound {
+               compatible = "simple-audio-card";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,widgets =
+                       "Microphone", "Microphone Jack",
+                       "Headphone", "Headphone Jack",
+                       "Speaker", "Speaker Ext",
+                       "Line", "Line In Jack";
+               simple-audio-card,routing =
+                       "MIC_IN", "Microphone Jack",
+                       "Microphone Jack", "Mic Bias",
+                       "LINE_IN", "Line In Jack",
+                       "Headphone Jack", "HP_OUT",
+                       "Speaker Ext", "LINE_OUT";
+
+               simple-audio-card,cpu {
+                       sound-dai = <&sai1>;
+                       frame-master;
+                       bitclock-master;
+               };
+
+               simple-audio-card,codec {
+                       sound-dai = <&sgtl5000>;
+                       frame-master;
+                       bitclock-master;
+                       system-clock-frequency = <25000000>;
+               };
+       };
 };
 
 &duart0 {
                                reg = <0x57>;
                        };
                };
+
+               i2c@5 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x5>;
+
+                       sgtl5000: audio-codec@a {
+                               #sound-dai-cells = <0>;
+                               compatible = "fsl,sgtl5000";
+                               reg = <0xa>;
+                               VDDA-supply = <&reg_1p8v>;
+                               VDDIO-supply = <&reg_1p8v>;
+                               clocks = <&sys_mclk>;
+                       };
+               };
        };
 };
+
+&sai1 {
+       status = "okay";
+};
index f86b054..f9c272f 100644 (file)
                device_type = "memory";
                reg = <0x0 0x80000000 0x1 0x0000000>;
        };
+
+       sys_mclk: clock-mclk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <25000000>;
+       };
+
+       reg_1p8v: regulator-1p8v {
+               compatible = "regulator-fixed";
+               regulator-name = "1P8V";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-always-on;
+       };
+
+       sound {
+               compatible = "simple-audio-card";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,widgets =
+                       "Microphone", "Microphone Jack",
+                       "Headphone", "Headphone Jack",
+                       "Speaker", "Speaker Ext",
+                       "Line", "Line In Jack";
+               simple-audio-card,routing =
+                       "MIC_IN", "Microphone Jack",
+                       "Microphone Jack", "Mic Bias",
+                       "LINE_IN", "Line In Jack",
+                       "Headphone Jack", "HP_OUT",
+                       "Speaker Ext", "LINE_OUT";
+
+               simple-audio-card,cpu {
+                       sound-dai = <&sai4>;
+                       frame-master;
+                       bitclock-master;
+               };
+
+               simple-audio-card,codec {
+                       sound-dai = <&sgtl5000>;
+                       frame-master;
+                       bitclock-master;
+                       system-clock-frequency = <25000000>;
+               };
+       };
 };
 
 &i2c0 {
                #address-cells = <1>;
                #size-cells = <0>;
 
+               i2c@1 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x1>;
+
+                       sgtl5000: audio-codec@a {
+                               #sound-dai-cells = <0>;
+                               compatible = "fsl,sgtl5000";
+                               reg = <0xa>;
+                               VDDA-supply = <&reg_1p8v>;
+                               VDDIO-supply = <&reg_1p8v>;
+                               clocks = <&sys_mclk>;
+                               sclk-strength = <3>;
+                       };
+               };
+
                i2c@2 {
                        #address-cells = <1>;
                        #size-cells = <0>;
 &enetc_port1 {
        status = "disabled";
 };
+
+&sai4 {
+       status = "okay";
+};
index 2896bbc..b045812 100644 (file)
                                          IRQ_TYPE_LEVEL_LOW)>;
        };
 
+       pmu {
+               compatible = "arm,cortex-a72-pmu";
+               interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
        gic: interrupt-controller@6000000 {
                compatible= "arm,gic-v3";
                #address-cells = <2>;
                        status = "disabled";
                };
 
+               edma0: dma-controller@22c0000 {
+                       #dma-cells = <2>;
+                       compatible = "fsl,vf610-edma";
+                       reg = <0x0 0x22c0000 0x0 0x10000>,
+                             <0x0 0x22d0000 0x0 0x10000>,
+                             <0x0 0x22e0000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "edma-tx", "edma-err";
+                       dma-channels = <32>;
+                       clock-names = "dmamux0", "dmamux1";
+                       clocks = <&clockgen 4 1>,
+                                <&clockgen 4 1>;
+               };
+
                gpio1: gpio@2300000 {
                        compatible = "fsl,qoriq-gpio";
                        reg = <0x0 0x2300000 0x0 0x10000>;
                sata: sata@3200000 {
                        compatible = "fsl,ls1028a-ahci";
                        reg = <0x0 0x3200000 0x0 0x10000>,
-                               <0x0 0x20140520 0x0 0x4>;
+                               <0x7 0x100520 0x0 0x4>;
                        reg-names = "ahci", "sata-ecc";
                        interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clockgen 4 1>;
                                     <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
                };
 
+               sai1: audio-controller@f100000 {
+                       #sound-dai-cells = <0>;
+                       compatible = "fsl,vf610-sai";
+                       reg = <0x0 0xf100000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clockgen 4 1>, <&clockgen 4 1>,
+                                <&clockgen 4 1>, <&clockgen 4 1>;
+                       clock-names = "bus", "mclk1", "mclk2", "mclk3";
+                       dma-names = "tx", "rx";
+                       dmas = <&edma0 1 4>,
+                              <&edma0 1 3>;
+                       status = "disabled";
+               };
+
+               sai2: audio-controller@f110000 {
+                       #sound-dai-cells = <0>;
+                       compatible = "fsl,vf610-sai";
+                       reg = <0x0 0xf110000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clockgen 4 1>, <&clockgen 4 1>,
+                                <&clockgen 4 1>, <&clockgen 4 1>;
+                       clock-names = "bus", "mclk1", "mclk2", "mclk3";
+                       dma-names = "tx", "rx";
+                       dmas = <&edma0 1 6>,
+                              <&edma0 1 5>;
+                       status = "disabled";
+               };
+
+               sai4: audio-controller@f130000 {
+                       #sound-dai-cells = <0>;
+                       compatible = "fsl,vf610-sai";
+                       reg = <0x0 0xf130000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clockgen 4 1>, <&clockgen 4 1>,
+                                <&clockgen 4 1>, <&clockgen 4 1>;
+                       clock-names = "bus", "mclk1", "mclk2", "mclk3";
+                       dma-names = "tx", "rx";
+                       dmas = <&edma0 1 10>,
+                              <&edma0 1 9>;
+                       status = "disabled";
+               };
+
                pcie@1f0000000 { /* Integrated Endpoint Root Complex */
                        compatible = "pci-host-ecam-generic";
                        reg = <0x01 0xf0000000 0x0 0x100000>;
index 17ca357..4223a23 100644 (file)
@@ -15,7 +15,6 @@
        model = "LS1043A RDB Board";
 
        aliases {
-               crypto = &crypto;
                serial0 = &duart0;
                serial1 = &duart1;
                serial2 = &duart2;
index 6fd6116..71d9ed9 100644 (file)
@@ -18,6 +18,7 @@
        #size-cells = <2>;
 
        aliases {
+               crypto = &crypto;
                fman0 = &fman0;
                ethernet0 = &enet0;
                ethernet1 = &enet1;
                        interrupts = <0 99 0x4>;
                        clock-names = "qspi_en", "qspi";
                        clocks = <&clockgen 4 0>, <&clockgen 4 0>;
-                       big-endian;
                        status = "disabled";
                };
 
index cb71850..b0ef08b 100644 (file)
                        interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
                        clock-names = "qspi_en", "qspi";
                        clocks = <&clockgen 4 1>, <&clockgen 4 1>;
-                       big-endian;
-                       fsl,qspi-has-second-chip;
                        status = "disabled";
                };
 
index 99a22ab..1a5acf6 100644 (file)
        };
 };
 
+&sata0 {
+       status = "okay";
+};
+
+&sata1 {
+       status = "okay";
+};
+
+&sata2 {
+       status = "okay";
+};
+
+&sata3 {
+       status = "okay";
+};
+
 &uart0 {
        status = "okay";
 };
index 9df37b1..c2817b7 100644 (file)
        };
 };
 
+&sata0 {
+       status = "okay";
+};
+
+&sata1 {
+       status = "okay";
+};
+
+&sata2 {
+       status = "okay";
+};
+
+&sata3 {
+       status = "okay";
+};
+
 &uart0 {
        status = "okay";
 };
index fe87204..125a8cc 100644 (file)
@@ -33,6 +33,7 @@
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster0_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@1 {
@@ -48,6 +49,7 @@
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster0_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@100 {
@@ -63,6 +65,7 @@
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster1_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@101 {
@@ -78,6 +81,7 @@
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster1_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@200 {
@@ -93,6 +97,7 @@
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster2_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@201 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster2_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@300 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster3_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@301 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster3_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@400 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster4_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@401 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster4_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@500 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster5_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@501 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster5_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@600 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster6_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@601 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster6_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@700 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster7_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cpu@701 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster7_l2>;
+                       cpu-idle-states = <&cpu_pw20>;
                };
 
                cluster0_l2: l2-cache0 {
                        cache-sets = <1024>;
                        cache-level = <2>;
                };
+
+               cpu_pw20: cpu-pw20 {
+                       compatible = "arm,idle-state";
+                       idle-state-name = "PW20";
+                       arm,psci-suspend-param = <0x0>;
+                       entry-latency-us = <2000>;
+                       exit-latency-us = <2000>;
+                       min-residency-us = <6000>;
+                 };
        };
 
        gic: interrupt-controller@6000000 {
                        status = "disabled";
                };
 
+               sata0: sata@3200000 {
+                       compatible = "fsl,lx2160a-ahci";
+                       reg = <0x0 0x3200000 0x0 0x10000>,
+                             <0x7 0x100520 0x0 0x4>;
+                       reg-names = "ahci", "sata-ecc";
+                       interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clockgen 4 3>;
+                       dma-coherent;
+                       status = "disabled";
+               };
+
+               sata1: sata@3210000 {
+                       compatible = "fsl,lx2160a-ahci";
+                       reg = <0x0 0x3210000 0x0 0x10000>,
+                             <0x7 0x100520 0x0 0x4>;
+                       reg-names = "ahci", "sata-ecc";
+                       interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clockgen 4 3>;
+                       dma-coherent;
+                       status = "disabled";
+               };
+
+               sata2: sata@3220000 {
+                       compatible = "fsl,lx2160a-ahci";
+                       reg = <0x0 0x3220000 0x0 0x10000>,
+                             <0x7 0x100520 0x0 0x4>;
+                       reg-names = "ahci", "sata-ecc";
+                       interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clockgen 4 3>;
+                       dma-coherent;
+                       status = "disabled";
+               };
+
+               sata3: sata@3230000 {
+                       compatible = "fsl,lx2160a-ahci";
+                       reg = <0x0 0x3230000 0x0 0x10000>,
+                             <0x7 0x100520 0x0 0x4>;
+                       reg-names = "ahci", "sata-ecc";
+                       interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clockgen 4 3>;
+                       dma-coherent;
+                       status = "disabled";
+               };
+
                smmu: iommu@5000000 {
                        compatible = "arm,mmu-500";
                        reg = <0 0x5000000 0 0x800000>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk.dts
new file mode 100644 (file)
index 0000000..2d5d894
--- /dev/null
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2019 NXP
+ */
+
+/dts-v1/;
+
+#include "imx8mm.dtsi"
+
+/ {
+       model = "FSL i.MX8MM EVK board";
+       compatible = "fsl,imx8mm-evk", "fsl,imx8mm";
+
+       chosen {
+               stdout-path = &uart2;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpio_led>;
+
+               status {
+                       label = "status";
+                       gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+               };
+       };
+
+       reg_usdhc2_vmmc: regulator-usdhc2 {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>;
+               regulator-name = "VSD_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+};
+
+&fec1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec1>;
+       phy-mode = "rgmii-id";
+       phy-handle = <&ethphy0>;
+       fsl,magic-packet;
+       status = "okay";
+
+       mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               ethphy0: ethernet-phy@0 {
+                       compatible = "ethernet-phy-ieee802.3-c22";
+                       reg = <0>;
+                       at803x,led-act-blind-workaround;
+                       at803x,eee-okay;
+                       at803x,vddio-1p8v;
+               };
+       };
+};
+
+&uart2 { /* console */
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+};
+
+&usdhc2 {
+       pinctrl-names = "default", "state_100mhz", "state_200mhz";
+       pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+       pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+       pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+       cd-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
+       bus-width = <4>;
+       vmmc-supply = <&reg_usdhc2_vmmc>;
+       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>;
+       non-removable;
+       status = "okay";
+};
+
+&wdog1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_wdog>;
+       fsl,ext-reset-output;
+       status = "okay";
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+
+       pinctrl_fec1: fec1grp {
+               fsl,pins = <
+                       MX8MM_IOMUXC_ENET_MDC_ENET1_MDC                 0x3
+                       MX8MM_IOMUXC_ENET_MDIO_ENET1_MDIO               0x3
+                       MX8MM_IOMUXC_ENET_TD3_ENET1_RGMII_TD3           0x1f
+                       MX8MM_IOMUXC_ENET_TD2_ENET1_RGMII_TD2           0x1f
+                       MX8MM_IOMUXC_ENET_TD1_ENET1_RGMII_TD1           0x1f
+                       MX8MM_IOMUXC_ENET_TD0_ENET1_RGMII_TD0           0x1f
+                       MX8MM_IOMUXC_ENET_RD3_ENET1_RGMII_RD3           0x91
+                       MX8MM_IOMUXC_ENET_RD2_ENET1_RGMII_RD2           0x91
+                       MX8MM_IOMUXC_ENET_RD1_ENET1_RGMII_RD1           0x91
+                       MX8MM_IOMUXC_ENET_RD0_ENET1_RGMII_RD0           0x91
+                       MX8MM_IOMUXC_ENET_TXC_ENET1_RGMII_TXC           0x1f
+                       MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC           0x91
+                       MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL     0x91
+                       MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL     0x1f
+                       MX8MM_IOMUXC_SAI2_RXC_GPIO4_IO22                0x19
+               >;
+       };
+
+       pinctrl_gpio_led: gpioledgrp {
+               fsl,pins = <
+                       MX8MM_IOMUXC_NAND_READY_B_GPIO3_IO16    0x19
+               >;
+       };
+
+       pinctrl_reg_usdhc2_vmmc: regusdhc2vmmc {
+               fsl,pins = <
+                       MX8MM_IOMUXC_SD2_RESET_B_GPIO2_IO19     0x41
+               >;
+       };
+
+       pinctrl_uart2: uart2grp {
+               fsl,pins = <
+                       MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX     0x140
+                       MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX     0x140
+               >;
+       };
+
+       pinctrl_usdhc2_gpio: usdhc2grpgpio {
+               fsl,pins = <
+                       MX8MM_IOMUXC_GPIO1_IO15_GPIO1_IO15      0x1c4
+               >;
+       };
+
+       pinctrl_usdhc2: usdhc2grp {
+               fsl,pins = <
+                       MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK         0x190
+                       MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD         0x1d0
+                       MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0     0x1d0
+                       MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1     0x1d0
+                       MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2     0x1d0
+                       MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3     0x1d0
+                       MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT  0x1d0
+               >;
+       };
+
+       pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+               fsl,pins = <
+                       MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK         0x194
+                       MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD         0x1d4
+                       MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0     0x1d4
+                       MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1     0x1d4
+                       MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2     0x1d4
+                       MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3     0x1d4
+                       MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT  0x1d0
+               >;
+       };
+
+       pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+               fsl,pins = <
+                       MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK         0x196
+                       MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD         0x1d6
+                       MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0     0x1d6
+                       MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1     0x1d6
+                       MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2     0x1d6
+                       MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3     0x1d6
+                       MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT  0x1d0
+               >;
+       };
+
+       pinctrl_usdhc3: usdhc3grp {
+               fsl,pins = <
+                       MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK               0x190
+                       MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD               0x1d0
+                       MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0           0x1d0
+                       MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1           0x1d0
+                       MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2           0x1d0
+                       MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3           0x1d0
+                       MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4             0x1d0
+                       MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5            0x1d0
+                       MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6            0x1d0
+                       MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7              0x1d0
+                       MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE           0x190
+               >;
+       };
+
+       pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+               fsl,pins = <
+                       MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK               0x194
+                       MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD               0x1d4
+                       MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0           0x1d4
+                       MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1           0x1d4
+                       MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2           0x1d4
+                       MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3           0x1d4
+                       MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4             0x1d4
+                       MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5            0x1d4
+                       MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6            0x1d4
+                       MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7              0x1d4
+                       MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE           0x194
+               >;
+       };
+
+       pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+               fsl,pins = <
+                       MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK               0x196
+                       MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD               0x1d6
+                       MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0           0x1d6
+                       MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1           0x1d6
+                       MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2           0x1d6
+                       MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3           0x1d6
+                       MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4             0x1d6
+                       MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5            0x1d6
+                       MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6            0x1d6
+                       MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7              0x1d6
+                       MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE           0x196
+               >;
+       };
+
+       pinctrl_wdog: wdoggrp {
+               fsl,pins = <
+                       MX8MM_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B    0xc6
+               >;
+       };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
new file mode 100644 (file)
index 0000000..6b407a9
--- /dev/null
@@ -0,0 +1,733 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <dt-bindings/clock/imx8mm-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/thermal/thermal.h>
+
+#include "imx8mm-pinfunc.h"
+
+/ {
+       compatible = "fsl,imx8mm";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       aliases {
+               ethernet0 = &fec1;
+               i2c0 = &i2c1;
+               i2c1 = &i2c2;
+               i2c2 = &i2c3;
+               i2c3 = &i2c4;
+               serial0 = &uart1;
+               serial1 = &uart2;
+               serial2 = &uart3;
+               serial3 = &uart4;
+               spi0 = &ecspi1;
+               spi1 = &ecspi2;
+               spi2 = &ecspi3;
+               mmc0 = &usdhc1;
+               mmc1 = &usdhc2;
+               mmc2 = &usdhc3;
+               gpio0 = &gpio1;
+               gpio1 = &gpio2;
+               gpio2 = &gpio3;
+               gpio3 = &gpio4;
+               gpio4 = &gpio5;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               A53_0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x0>;
+                       clock-latency = <61036>; /* two CLK32 periods */
+                       clocks = <&clk IMX8MM_CLK_ARM>;
+                       enable-method = "psci";
+                       next-level-cache = <&A53_L2>;
+                       operating-points-v2 = <&a53_opp_table>;
+               };
+
+               A53_1: cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x1>;
+                       clock-latency = <61036>; /* two CLK32 periods */
+                       clocks = <&clk IMX8MM_CLK_ARM>;
+                       enable-method = "psci";
+                       next-level-cache = <&A53_L2>;
+                       operating-points-v2 = <&a53_opp_table>;
+               };
+
+               A53_2: cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x2>;
+                       clock-latency = <61036>; /* two CLK32 periods */
+                       clocks = <&clk IMX8MM_CLK_ARM>;
+                       enable-method = "psci";
+                       next-level-cache = <&A53_L2>;
+                       operating-points-v2 = <&a53_opp_table>;
+               };
+
+               A53_3: cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x3>;
+                       clock-latency = <61036>; /* two CLK32 periods */
+                       clocks = <&clk IMX8MM_CLK_ARM>;
+                       enable-method = "psci";
+                       next-level-cache = <&A53_L2>;
+                       operating-points-v2 = <&a53_opp_table>;
+               };
+
+               A53_L2: l2-cache0 {
+                       compatible = "cache";
+               };
+       };
+
+       a53_opp_table: opp-table {
+               compatible = "operating-points-v2";
+               opp-shared;
+
+               opp-1200000000 {
+                       opp-hz = /bits/ 64 <1200000000>;
+                       opp-microvolt = <850000>;
+                       clock-latency-ns = <150000>;
+               };
+
+               opp-1600000000 {
+                       opp-hz = /bits/ 64 <1600000000>;
+                       opp-microvolt = <900000>;
+                       clock-latency-ns = <150000>;
+                       opp-suspend;
+               };
+       };
+
+       memory@40000000 {
+               device_type = "memory";
+               reg = <0x0 0x40000000 0 0x80000000>;
+       };
+
+       osc_32k: clock-osc-32k {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <32768>;
+               clock-output-names = "osc_32k";
+       };
+
+       osc_24m: clock-osc-24m {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <24000000>;
+               clock-output-names = "osc_24m";
+       };
+
+       clk_ext1: clock-ext1 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <133000000>;
+               clock-output-names = "clk_ext1";
+       };
+
+       clk_ext2: clock-ext2 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <133000000>;
+               clock-output-names = "clk_ext2";
+       };
+
+       clk_ext3: clock-ext3 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <133000000>;
+               clock-output-names = "clk_ext3";
+       };
+
+       clk_ext4: clock-ext4 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency= <133000000>;
+               clock-output-names = "clk_ext4";
+       };
+
+       gic: interrupt-controller@38800000 {
+               compatible = "arm,gic-v3";
+               reg = <0x0 0x38800000 0 0x10000>, /* GIC Dist */
+                     <0x0 0x38880000 0 0xC0000>; /* GICR (RD_base + SGI_base) */
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       psci {
+               compatible = "arm,psci-1.0";
+               method = "smc";
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <GIC_PPI 7
+                            (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_HIGH)>;
+               interrupt-affinity = <&A53_0>, <&A53_1>, <&A53_2>, <&A53_3>;
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>, /* Physical Secure */
+                            <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>, /* Physical Non-Secure */
+                            <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>, /* Virtual */
+                            <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>; /* Hypervisor */
+               clock-frequency = <8000000>;
+               arm,no-tick-in-suspend;
+       };
+
+       soc {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x0 0x0 0x0 0x3e000000>;
+
+               aips1: bus@30000000 {
+                       compatible = "fsl,aips-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       gpio1: gpio@30200000 {
+                               compatible = "fsl,imx8mm-gpio", "fsl,imx35-gpio";
+                               reg = <0x30200000 0x10000>;
+                               interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       gpio2: gpio@30210000 {
+                               compatible = "fsl,imx8mm-gpio", "fsl,imx35-gpio";
+                               reg = <0x30210000 0x10000>;
+                               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>;
+                       };
+
+                       gpio3: gpio@30220000 {
+                               compatible = "fsl,imx8mm-gpio", "fsl,imx35-gpio";
+                               reg = <0x30220000 0x10000>;
+                               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>;
+                       };
+
+                       gpio4: gpio@30230000 {
+                               compatible = "fsl,imx8mm-gpio", "fsl,imx35-gpio";
+                               reg = <0x30230000 0x10000>;
+                               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>;
+                       };
+
+                       gpio5: gpio@30240000 {
+                               compatible = "fsl,imx8mm-gpio", "fsl,imx35-gpio";
+                               reg = <0x30240000 0x10000>;
+                               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>;
+                       };
+
+                       wdog1: watchdog@30280000 {
+                               compatible = "fsl,imx8mm-wdt", "fsl,imx21-wdt";
+                               reg = <0x30280000 0x10000>;
+                               interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_WDOG1_ROOT>;
+                               status = "disabled";
+                       };
+
+                       wdog2: watchdog@30290000 {
+                               compatible = "fsl,imx8mm-wdt", "fsl,imx21-wdt";
+                               reg = <0x30290000 0x10000>;
+                               interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_WDOG2_ROOT>;
+                               status = "disabled";
+                       };
+
+                       wdog3: watchdog@302a0000 {
+                               compatible = "fsl,imx8mm-wdt", "fsl,imx21-wdt";
+                               reg = <0x302a0000 0x10000>;
+                               interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_WDOG3_ROOT>;
+                               status = "disabled";
+                       };
+
+                       sdma2: dma-controller@302c0000 {
+                               compatible = "fsl,imx8mm-sdma", "fsl,imx7d-sdma";
+                               reg = <0x302c0000 0x10000>;
+                               interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_SDMA2_ROOT>,
+                                        <&clk IMX8MM_CLK_SDMA2_ROOT>;
+                               clock-names = "ipg", "ahb";
+                               #dma-cells = <3>;
+                               fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
+                       };
+
+                       sdma3: dma-controller@302b0000 {
+                               compatible = "fsl,imx8mm-sdma", "fsl,imx7d-sdma";
+                               reg = <0x302b0000 0x10000>;
+                               interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_SDMA3_ROOT>,
+                                <&clk IMX8MM_CLK_SDMA3_ROOT>;
+                               clock-names = "ipg", "ahb";
+                               #dma-cells = <3>;
+                               fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
+                       };
+
+                       iomuxc: pinctrl@30330000 {
+                               compatible = "fsl,imx8mm-iomuxc";
+                               reg = <0x30330000 0x10000>;
+                       };
+
+                       gpr: iomuxc-gpr@30340000 {
+                               compatible = "fsl,imx8mm-iomuxc-gpr", "syscon";
+                               reg = <0x30340000 0x10000>;
+                       };
+
+                       ocotp: ocotp-ctrl@30350000 {
+                               compatible = "fsl,imx8mm-ocotp", "fsl,imx7d-ocotp", "syscon";
+                               reg = <0x30350000 0x10000>;
+                               clocks = <&clk IMX8MM_CLK_OCOTP_ROOT>;
+                               /* For nvmem subnodes */
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                       };
+
+                       anatop: anatop@30360000 {
+                               compatible = "fsl,imx8mm-anatop", "syscon", "simple-bus";
+                               reg = <0x30360000 0x10000>;
+                       };
+
+                       snvs: snvs@30370000 {
+                               compatible = "fsl,sec-v4.0-mon","syscon", "simple-mfd";
+                               reg = <0x30370000 0x10000>;
+
+                               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_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;
+                               };
+                       };
+
+                       clk: clock-controller@30380000 {
+                               compatible = "fsl,imx8mm-ccm";
+                               reg = <0x30380000 0x10000>;
+                               #clock-cells = <1>;
+                               clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, <&clk_ext2>,
+                                        <&clk_ext3>, <&clk_ext4>;
+                               clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2",
+                                             "clk_ext3", "clk_ext4";
+                       };
+
+                       src: reset-controller@30390000 {
+                               compatible = "fsl,imx8mm-src", "syscon";
+                               reg = <0x30390000 0x10000>;
+                               interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+                               #reset-cells = <1>;
+                       };
+               };
+
+               aips2: bus@30400000 {
+                       compatible = "fsl,aips-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       pwm1: pwm@30660000 {
+                               compatible = "fsl,imx8mm-pwm", "fsl,imx27-pwm";
+                               reg = <0x30660000 0x10000>;
+                               interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_PWM1_ROOT>,
+                                       <&clk IMX8MM_CLK_PWM1_ROOT>;
+                               clock-names = "ipg", "per";
+                               #pwm-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       pwm2: pwm@30670000 {
+                               compatible = "fsl,imx8mm-pwm", "fsl,imx27-pwm";
+                               reg = <0x30670000 0x10000>;
+                               interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_PWM2_ROOT>,
+                                        <&clk IMX8MM_CLK_PWM2_ROOT>;
+                               clock-names = "ipg", "per";
+                               #pwm-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       pwm3: pwm@30680000 {
+                               compatible = "fsl,imx8mm-pwm", "fsl,imx27-pwm";
+                               reg = <0x30680000 0x10000>;
+                               interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_PWM3_ROOT>,
+                                        <&clk IMX8MM_CLK_PWM3_ROOT>;
+                               clock-names = "ipg", "per";
+                               #pwm-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       pwm4: pwm@30690000 {
+                               compatible = "fsl,imx8mm-pwm", "fsl,imx27-pwm";
+                               reg = <0x30690000 0x10000>;
+                               interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_PWM4_ROOT>,
+                                        <&clk IMX8MM_CLK_PWM4_ROOT>;
+                               clock-names = "ipg", "per";
+                               #pwm-cells = <2>;
+                               status = "disabled";
+                       };
+               };
+
+               aips3: bus@30800000 {
+                       compatible = "fsl,aips-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       ecspi1: spi@30820000 {
+                               compatible = "fsl,imx8mm-ecspi", "fsl,imx51-ecspi";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reg = <0x30820000 0x10000>;
+                               interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_ECSPI1_ROOT>,
+                                        <&clk IMX8MM_CLK_ECSPI1_ROOT>;
+                               clock-names = "ipg", "per";
+                               dmas = <&sdma1 0 7 1>, <&sdma1 1 7 2>;
+                               dma-names = "rx", "tx";
+                               status = "disabled";
+                       };
+
+                       ecspi2: spi@30830000 {
+                               compatible = "fsl,imx8mm-ecspi", "fsl,imx51-ecspi";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reg = <0x30830000 0x10000>;
+                               interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_ECSPI2_ROOT>,
+                                        <&clk IMX8MM_CLK_ECSPI2_ROOT>;
+                               clock-names = "ipg", "per";
+                               dmas = <&sdma1 2 7 1>, <&sdma1 3 7 2>;
+                               dma-names = "rx", "tx";
+                               status = "disabled";
+                       };
+
+                       ecspi3: spi@30840000 {
+                               compatible = "fsl,imx8mm-ecspi", "fsl,imx51-ecspi";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reg = <0x30840000 0x10000>;
+                               interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_ECSPI3_ROOT>,
+                                        <&clk IMX8MM_CLK_ECSPI3_ROOT>;
+                               clock-names = "ipg", "per";
+                               dmas = <&sdma1 4 7 1>, <&sdma1 5 7 2>;
+                               dma-names = "rx", "tx";
+                               status = "disabled";
+                       };
+
+                       uart1: serial@30860000 {
+                               compatible = "fsl,imx8mm-uart", "fsl,imx6q-uart";
+                               reg = <0x30860000 0x10000>;
+                               interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_UART1_ROOT>,
+                                        <&clk IMX8MM_CLK_UART1_ROOT>;
+                               clock-names = "ipg", "per";
+                               dmas = <&sdma1 22 4 0>, <&sdma1 23 4 0>;
+                               dma-names = "rx", "tx";
+                               status = "disabled";
+                       };
+
+                       uart3: serial@30880000 {
+                               compatible = "fsl,imx8mm-uart", "fsl,imx6q-uart";
+                               reg = <0x30880000 0x10000>;
+                               interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_UART3_ROOT>,
+                                        <&clk IMX8MM_CLK_UART3_ROOT>;
+                               clock-names = "ipg", "per";
+                               dmas = <&sdma1 26 4 0>, <&sdma1 27 4 0>;
+                               dma-names = "rx", "tx";
+                               status = "disabled";
+                       };
+
+                       uart2: serial@30890000 {
+                               compatible = "fsl,imx8mm-uart", "fsl,imx6q-uart";
+                               reg = <0x30890000 0x10000>;
+                               interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_UART2_ROOT>,
+                                        <&clk IMX8MM_CLK_UART2_ROOT>;
+                               clock-names = "ipg", "per";
+                               status = "disabled";
+                       };
+
+                       i2c1: i2c@30a20000 {
+                               compatible = "fsl,imx8mm-i2c", "fsl,imx21-i2c";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reg = <0x30a20000 0x10000>;
+                               interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_I2C1_ROOT>;
+                               status = "disabled";
+                       };
+
+                       i2c2: i2c@30a30000 {
+                               compatible = "fsl,imx8mm-i2c", "fsl,imx21-i2c";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reg = <0x30a30000 0x10000>;
+                               interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_I2C2_ROOT>;
+                               status = "disabled";
+                       };
+
+                       i2c3: i2c@30a40000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,imx8mm-i2c", "fsl,imx21-i2c";
+                               reg = <0x30a40000 0x10000>;
+                               interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_I2C3_ROOT>;
+                               status = "disabled";
+                       };
+
+                       i2c4: i2c@30a50000 {
+                               compatible = "fsl,imx8mm-i2c", "fsl,imx21-i2c";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reg = <0x30a50000 0x10000>;
+                               interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_I2C4_ROOT>;
+                               status = "disabled";
+                       };
+
+                       uart4: serial@30a60000 {
+                               compatible = "fsl,imx8mm-uart", "fsl,imx6q-uart";
+                               reg = <0x30a60000 0x10000>;
+                               interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_UART4_ROOT>,
+                                        <&clk IMX8MM_CLK_UART4_ROOT>;
+                               clock-names = "ipg", "per";
+                               dmas = <&sdma1 28 4 0>, <&sdma1 29 4 0>;
+                               dma-names = "rx", "tx";
+                               status = "disabled";
+                       };
+
+                       usdhc1: mmc@30b40000 {
+                               compatible = "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
+                               reg = <0x30b40000 0x10000>;
+                               interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_DUMMY>,
+                                        <&clk IMX8MM_CLK_NAND_USDHC_BUS>,
+                                        <&clk IMX8MM_CLK_USDHC1_ROOT>;
+                               clock-names = "ipg", "ahb", "per";
+                               assigned-clocks = <&clk IMX8MM_CLK_USDHC1>;
+                               assigned-clock-rates = <400000000>;
+                               fsl,tuning-start-tap = <20>;
+                               fsl,tuning-step= <2>;
+                               bus-width = <4>;
+                               status = "disabled";
+                       };
+
+                       usdhc2: mmc@30b50000 {
+                               compatible = "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
+                               reg = <0x30b50000 0x10000>;
+                               interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_DUMMY>,
+                                        <&clk IMX8MM_CLK_NAND_USDHC_BUS>,
+                                        <&clk IMX8MM_CLK_USDHC2_ROOT>;
+                               clock-names = "ipg", "ahb", "per";
+                               fsl,tuning-start-tap = <20>;
+                               fsl,tuning-step= <2>;
+                               bus-width = <4>;
+                               status = "disabled";
+                       };
+
+                       usdhc3: mmc@30b60000 {
+                               compatible = "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
+                               reg = <0x30b60000 0x10000>;
+                               interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_DUMMY>,
+                                        <&clk IMX8MM_CLK_NAND_USDHC_BUS>,
+                                        <&clk IMX8MM_CLK_USDHC3_ROOT>;
+                               clock-names = "ipg", "ahb", "per";
+                               assigned-clocks = <&clk IMX8MM_CLK_USDHC3_ROOT>;
+                               assigned-clock-rates = <400000000>;
+                               fsl,tuning-start-tap = <20>;
+                               fsl,tuning-step= <2>;
+                               bus-width = <4>;
+                               status = "disabled";
+                       };
+
+                       sdma1: dma-controller@30bd0000 {
+                               compatible = "fsl,imx8mm-sdma", "fsl,imx7d-sdma";
+                               reg = <0x30bd0000 0x10000>;
+                               interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_SDMA1_ROOT>,
+                                        <&clk IMX8MM_CLK_SDMA1_ROOT>;
+                               clock-names = "ipg", "ahb";
+                               #dma-cells = <3>;
+                               fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
+                       };
+
+                       fec1: ethernet@30be0000 {
+                               compatible = "fsl,imx8mm-fec", "fsl,imx6sx-fec";
+                               reg = <0x30be0000 0x10000>;
+                               interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_ENET1_ROOT>,
+                                        <&clk IMX8MM_CLK_ENET1_ROOT>,
+                                        <&clk IMX8MM_CLK_ENET_TIMER>,
+                                        <&clk IMX8MM_CLK_ENET_REF>,
+                                        <&clk IMX8MM_CLK_ENET_PHY_REF>;
+                               clock-names = "ipg", "ahb", "ptp",
+                                             "enet_clk_ref", "enet_out";
+                               assigned-clocks = <&clk IMX8MM_CLK_ENET_AXI>,
+                                                 <&clk IMX8MM_CLK_ENET_TIMER>,
+                                                 <&clk IMX8MM_CLK_ENET_REF>,
+                                                 <&clk IMX8MM_CLK_ENET_TIMER>;
+                               assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_266M>,
+                                                        <&clk IMX8MM_SYS_PLL2_100M>,
+                                                        <&clk IMX8MM_SYS_PLL2_125M>;
+                               assigned-clock-rates = <0>, <0>, <125000000>, <100000000>;
+                               fsl,num-tx-queues = <3>;
+                               fsl,num-rx-queues = <3>;
+                               status = "disabled";
+                       };
+
+               };
+
+               aips4: bus@32c00000 {
+                       compatible = "fsl,aips-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       usbotg1: usb@32e40000 {
+                               compatible = "fsl,imx8mm-usb", "fsl,imx7d-usb";
+                               reg = <0x32e40000 0x200>;
+                               interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_USB1_CTRL_ROOT>;
+                               clock-names = "usb1_ctrl_root_clk";
+                               assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>,
+                                                 <&clk IMX8MM_CLK_USB_CORE_REF>;
+                               assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>,
+                                                        <&clk IMX8MM_SYS_PLL1_100M>;
+                               fsl,usbphy = <&usbphynop1>;
+                               fsl,usbmisc = <&usbmisc1 0>;
+                               status = "disabled";
+                       };
+
+                       usbphynop1: usbphynop1 {
+                               compatible = "usb-nop-xceiv";
+                               clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
+                               assigned-clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
+                               assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_100M>;
+                               clock-names = "main_clk";
+                       };
+
+                       usbmisc1: usbmisc@32e40200 {
+                               compatible = "fsl,imx8mm-usbmisc", "fsl,imx7d-usbmisc";
+                               #index-cells = <1>;
+                               reg = <0x32e40200 0x200>;
+                       };
+
+                       usbotg2: usb@32e50000 {
+                               compatible = "fsl,imx8mm-usb", "fsl,imx7d-usb";
+                               reg = <0x32e50000 0x200>;
+                               interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MM_CLK_USB1_CTRL_ROOT>;
+                               clock-names = "usb1_ctrl_root_clk";
+                               assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>,
+                                                 <&clk IMX8MM_CLK_USB_CORE_REF>;
+                               assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>,
+                                                        <&clk IMX8MM_SYS_PLL1_100M>;
+                               fsl,usbphy = <&usbphynop2>;
+                               fsl,usbmisc = <&usbmisc2 0>;
+                               status = "disabled";
+                       };
+
+                       usbphynop2: usbphynop2 {
+                               compatible = "usb-nop-xceiv";
+                               clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
+                               assigned-clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
+                               assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_100M>;
+                               clock-names = "main_clk";
+                       };
+
+                       usbmisc2: usbmisc@32e50200 {
+                               compatible = "fsl,imx8mm-usbmisc", "fsl,imx7d-usbmisc";
+                               #index-cells = <1>;
+                               reg = <0x32e50200 0x200>;
+                       };
+
+               };
+
+               dma_apbh: dma-controller@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 = <&clk IMX8MM_CLK_NAND_USDHC_BUS_RAWNAND_CLK>;
+               };
+
+               gpmi: nand-controller@33002000{
+                       compatible = "fsl,imx8mm-gpmi-nand", "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 = <&clk IMX8MM_CLK_NAND_ROOT>,
+                                <&clk IMX8MM_CLK_NAND_USDHC_BUS_RAWNAND_CLK>;
+                       clock-names = "gpmi_io", "gpmi_bch_apb";
+                       dmas = <&dma_apbh 0>;
+                       dma-names = "rx-tx";
+                       status = "disabled";
+               };
+       };
+};
index 54737bf..b2038be 100644 (file)
                reg = <0x00000000 0x40000000 0 0xc0000000>;
        };
 
+       pcie0_refclk: pcie0-refclk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
+       };
+
        reg_usdhc2_vmmc: regulator-vsd-3v3 {
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_reg_usdhc2>;
                gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
                enable-active-high;
        };
+
+       buck2_reg: regulator-buck2 {
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_buck2>;
+               compatible = "regulator-gpio";
+               regulator-name = "vdd_arm";
+               regulator-min-microvolt = <900000>;
+               regulator-max-microvolt = <1000000>;
+               gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+               states = <1000000 0x0
+                         900000 0x1>;
+       };
+
+       wm8524: audio-codec {
+               #sound-dai-cells = <0>;
+               compatible = "wlf,wm8524";
+               wlf,mute-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
+       };
+
+       sound-wm8524 {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "wm8524-audio";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,frame-master = <&cpudai>;
+               simple-audio-card,bitclock-master = <&cpudai>;
+               simple-audio-card,widgets =
+                       "Line", "Left Line Out Jack",
+                       "Line", "Right Line Out Jack";
+               simple-audio-card,routing =
+                       "Left Line Out Jack", "LINEVOUTL",
+                       "Right Line Out Jack", "LINEVOUTR";
+
+               cpudai: simple-audio-card,cpu {
+                       sound-dai = <&sai2>;
+               };
+
+               link_codec: simple-audio-card,codec {
+                       sound-dai = <&wm8524>;
+                       clocks = <&clk IMX8MQ_CLK_SAI2_ROOT>;
+               };
+       };
+};
+
+&A53_0 {
+       cpu-supply = <&buck2_reg>;
+};
+
+&A53_1 {
+       cpu-supply = <&buck2_reg>;
+};
+
+&A53_2 {
+       cpu-supply = <&buck2_reg>;
+};
+
+&A53_3 {
+       cpu-supply = <&buck2_reg>;
 };
 
 &fec1 {
        };
 };
 
+&sai2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_sai2>;
+       assigned-clocks = <&clk IMX8MQ_CLK_SAI2>;
+       assigned-clock-parents = <&clk IMX8MQ_AUDIO_PLL1_OUT>;
+       assigned-clock-rates = <24576000>;
+       status = "okay";
+};
+
+&gpio5 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_wifi_reset>;
+
+       wl-reg-on {
+               gpio-hog;
+               gpios = <29 GPIO_ACTIVE_HIGH>;
+               output-high;
+       };
+};
+
 &i2c1 {
        clock-frequency = <100000>;
        pinctrl-names = "default";
        };
 };
 
+&pcie0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pcie0>;
+       reset-gpio = <&gpio5 28 GPIO_ACTIVE_LOW>;
+       clocks = <&clk IMX8MQ_CLK_PCIE1_ROOT>,
+                <&clk IMX8MQ_CLK_PCIE1_AUX>,
+                <&clk IMX8MQ_CLK_PCIE1_PHY>,
+                <&pcie0_refclk>;
+       clock-names = "pcie", "pcie_aux", "pcie_phy", "pcie_bus";
+       status = "okay";
+};
+
+&pgc_gpu {
+       power-supply = <&sw1a_reg>;
+};
+
 &uart1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart1>;
 };
 
 &iomuxc {
+       pinctrl_buck2: vddarmgrp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_GPIO1_IO13_GPIO1_IO13              0x19
+               >;
+
+       };
+
        pinctrl_fec1: fec1grp {
                fsl,pins = <
                        MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC                 0x3
                >;
        };
 
+       pinctrl_pcie0: pcie0grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_I2C4_SCL_PCIE1_CLKREQ_B            0x76
+                       MX8MQ_IOMUXC_UART4_RXD_GPIO5_IO28               0x16
+               >;
+       };
+
        pinctrl_qspi: qspigrp {
                fsl,pins = <
                        MX8MQ_IOMUXC_NAND_ALE_QSPI_A_SCLK       0x82
                >;
        };
 
+       pinctrl_sai2: sai2grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_SAI2_TXFS_SAI2_TX_SYNC     0xd6
+                       MX8MQ_IOMUXC_SAI2_TXC_SAI2_TX_BCLK      0xd6
+                       MX8MQ_IOMUXC_SAI2_MCLK_SAI2_MCLK        0xd6
+                       MX8MQ_IOMUXC_SAI2_TXD0_SAI2_TX_DATA0    0xd6
+                       MX8MQ_IOMUXC_GPIO1_IO08_GPIO1_IO8       0xd6
+               >;
+       };
+
        pinctrl_uart1: uart1grp {
                fsl,pins = <
                        MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX             0x49
                        MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B            0xc6
                >;
        };
+
+       pinctrl_wifi_reset: wifiresetgrp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_UART4_TXD_GPIO5_IO29               0x16
+               >;
+       };
 };
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra-rmb3.dts b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra-rmb3.dts
new file mode 100644 (file)
index 0000000..d2a6da4
--- /dev/null
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2019 Zodiac Inflight Innovations
+ */
+
+/dts-v1/;
+
+#include "imx8mq-zii-ultra.dtsi"
+
+/ {
+       model = "ZII i.MX8MQ Ultra RMB3 Board";
+       compatible = "zii,imx8mq-ultra-rmb3", "zii,imx8mq-ultra", "fsl,imx8mq";
+};
+
+&ecspi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ecspi1>;
+       cs-gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       nor_flash: flash@0 {
+               compatible = "st,n25q128a13", "jedec,spi-nor";
+               spi-max-frequency = <20000000>;
+               reg = <0>;
+       };
+};
+
+&i2c2 {
+       temp-sense@48 {
+               compatible = "national,lm75";
+               reg = <0x48>;
+       };
+};
+
+&i2c4 {
+       touchscreen@20 {
+               compatible = "syna,rmi4-i2c";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_ts>;
+               reg = <0x20>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
+
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               rmi4-f01@1 {
+                       reg = <0x1>;
+                       syna,nosleep-mode = <2>;
+               };
+
+               rmi4-f11@11 {
+                       reg = <0x11>;
+                       touchscreen-inverted-x;
+                       touchscreen-swapped-x-y;
+                       syna,sensor-type = <1>;
+               };
+
+               rmi4-f12@12 {
+                       reg = <0x12>;
+                       touchscreen-inverted-x;
+                       touchscreen-swapped-x-y;
+                       syna,sensor-type = <1>;
+               };
+       };
+
+       touchscreen@2a {
+               compatible = "eeti,exc3000";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_ts>;
+               reg = <0x2a>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
+               touchscreen-inverted-x;
+               touchscreen-swapped-x-y;
+               status = "disabled";
+       };
+};
+
+&usbhub {
+       swap-dx-lanes = <0>;
+};
+
+&iomuxc {
+       pinctrl_ecspi1: ecspi1grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_ECSPI1_SS0_GPIO5_IO9       0x19
+                       MX8MQ_IOMUXC_ECSPI1_SCLK_ECSPI1_SCLK    0x82
+                       MX8MQ_IOMUXC_ECSPI1_MISO_ECSPI1_MISO    0x82
+                       MX8MQ_IOMUXC_ECSPI1_MOSI_ECSPI1_MOSI    0x82
+               >;
+       };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra-zest.dts b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra-zest.dts
new file mode 100644 (file)
index 0000000..1084d93
--- /dev/null
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2019 Zodiac Inflight Innovations
+ */
+
+/dts-v1/;
+
+#include "imx8mq-zii-ultra.dtsi"
+
+/ {
+       model = "ZII i.MX8MQ Ultra Zest Board";
+       compatible = "zii,imx8mq-ultra-zest", "zii,imx8mq-ultra", "fsl,imx8mq";
+};
+
+&i2c4 {
+       touchscreen@4a {
+               compatible = "atmel,maxtouch";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_ts>;
+               reg = <0x4a>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
+       };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi
new file mode 100644 (file)
index 0000000..7a1706f
--- /dev/null
@@ -0,0 +1,725 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2019 Zodiac Inflight Innovations
+ */
+
+#include "imx8mq.dtsi"
+
+/ {
+       aliases {
+               mdio-gpio0 = &mdio0;
+               rtc0 = &ds1341;
+       };
+
+       chosen {
+               stdout-path = &uart1;
+       };
+
+       mdio0: bitbang-mdio {
+               compatible = "virtual,mdio-gpio";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_mdio_bitbang>, <&pinctrl_fec1_phy_reset>;
+               gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>, /* MDC */
+                       <&gpio1 14 GPIO_ACTIVE_HIGH>; /* MDIO */
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               phy0: ethernet-phy@0 {
+                       reg = <0>;
+                       reset-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       pcie0_refclk: clock-pcie0-refclk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
+       };
+
+       pcie1_refclk: clock-pcie1-refclk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
+       };
+
+       reg_12p0_main: regulator-12p0-main {
+               compatible = "regulator-fixed";
+               regulator-name = "12V_MAIN";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+
+       reg_5p0_main: regulator-5p0-main {
+               compatible = "regulator-fixed";
+               vin-supply = <&reg_12p0_main>;
+               regulator-name = "5V_MAIN";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+
+       reg_3p3_main: regulator-3p3-main {
+               compatible = "regulator-fixed";
+               vin-supply = <&reg_12p0_main>;
+               regulator-name = "3V3V_MAIN";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       reg_5p0_user_usb: regulator-5p0-user-usb {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_reg_user_usb>;
+               vin-supply = <&reg_5p0_main>;
+               regulator-name = "5V_USER_USB";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio3 12 GPIO_ACTIVE_LOW>;
+               startup-delay-us = <1000>;
+       };
+
+       reg_usdhc2_vmmc: regulator-vsd-3v3 {
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_reg_usdhc2>;
+               compatible = "regulator-fixed";
+               vin-supply = <&reg_3p3_main>;
+               regulator-name = "3V3_SD";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_arm: regulator-arm {
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_reg_arm>;
+               compatible = "regulator-gpio";
+               vin-supply = <&reg_12p0_main>;
+               regulator-name = "0V9_ARM";
+               regulator-min-microvolt = <900000>;
+               regulator-max-microvolt = <1000000>;
+               gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
+               states = <1000000 0x0
+                          900000 0x1>;
+               regulator-always-on;
+       };
+};
+
+&A53_0 {
+       cpu-supply = <&reg_arm>;
+};
+
+&A53_1 {
+       cpu-supply = <&reg_arm>;
+};
+
+&A53_2 {
+       cpu-supply = <&reg_arm>;
+};
+
+&A53_3 {
+       cpu-supply = <&reg_arm>;
+};
+
+&fec1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec1>;
+
+       phy-handle = <&phy0>;
+       phy-mode = "rmii";
+       status = "okay";
+
+       mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "okay";
+
+               switch: switch@0 {
+                       compatible = "marvell,mv88e6085";
+                       pinctrl-0 = <&pinctrl_switch_irq>;
+                       pinctrl-names = "default";
+                       reg = <0>;
+                       dsa,member = <0 0>;
+                       eeprom-length = <512>;
+                       interrupt-parent = <&gpio1>;
+                       interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       label = "gigabit_proc";
+                                       phy-handle = <&switchphy0>;
+                               };
+
+                               port@1 {
+                                       reg = <1>;
+                                       label = "netaux";
+                                       phy-handle = <&switchphy1>;
+                               };
+
+                               port@2 {
+                                       reg = <2>;
+                                       label = "cpu";
+                                       ethernet = <&fec1>;
+
+                                       fixed-link {
+                                               speed = <100>;
+                                               full-duplex;
+                                       };
+                               };
+
+                               port@3 {
+                                       reg = <3>;
+                                       label = "netright";
+                                       phy-handle = <&switchphy3>;
+                               };
+
+                               port@4 {
+                                       reg = <4>;
+                                       label = "netleft";
+                                       phy-handle = <&switchphy4>;
+                               };
+                       };
+
+                       mdio {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               switchphy0: switchphy@0 {
+                                       reg = <0>;
+                                       interrupt-parent = <&switch>;
+                                       interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+
+                               switchphy1: switchphy@1 {
+                                       reg = <1>;
+                                       interrupt-parent = <&switch>;
+                                       interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+
+                               switchphy2: switchphy@2 {
+                                       reg = <2>;
+                                       interrupt-parent = <&switch>;
+                                       interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+
+                               switchphy3: switchphy@3 {
+                                       reg = <3>;
+                                       interrupt-parent = <&switch>;
+                                       interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+
+                               switchphy4: switchphy@4 {
+                                       reg = <4>;
+                                       interrupt-parent = <&switch>;
+                                       interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+                       };
+               };
+       };
+};
+
+&gpio3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_gpio3_hog>;
+
+       usb-emulation {
+               gpio-hog;
+               gpios = <10 GPIO_ACTIVE_HIGH>;
+               output-low;
+               line-name = "usb-emulation";
+       };
+
+       usb-mode1 {
+               gpio-hog;
+               gpios = <11 GPIO_ACTIVE_HIGH>;
+               output-high;
+               line-name = "usb-mode1";
+       };
+
+       usb-mode2 {
+               gpio-hog;
+               gpios = <13 GPIO_ACTIVE_HIGH>;
+               output-high;
+               line-name = "usb-mode2";
+       };
+};
+
+&i2c1 {
+       clock-frequency = <400000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+};
+
+&i2c2 {
+       clock-frequency = <400000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+
+       pmic@8 {
+               compatible = "fsl,pfuze100";
+               reg = <0x8>;
+
+               regulators {
+                       sw1a_reg: sw1ab {
+                               regulator-min-microvolt = <825000>;
+                               regulator-max-microvolt = <1100000>;
+                       };
+
+                       sw1c_reg: sw1c {
+                               regulator-min-microvolt = <825000>;
+                               regulator-max-microvolt = <1100000>;
+                       };
+
+                       sw2_reg: sw2 {
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                       };
+
+                       sw3a_reg: sw3ab {
+                               regulator-min-microvolt = <825000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                       };
+
+                       sw4_reg: sw4 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               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 = <850000>;
+                               regulator-max-microvolt = <975000>;
+                               regulator-always-on;
+                       };
+
+                       vgen3_reg: vgen3 {
+                               regulator-min-microvolt = <1675000>;
+                               regulator-max-microvolt = <1975000>;
+                               regulator-always-on;
+                       };
+
+                       vgen4_reg: vgen4 {
+                               regulator-min-microvolt = <1625000>;
+                               regulator-max-microvolt = <1875000>;
+                               regulator-always-on;
+                       };
+
+                       vgen5_reg: vgen5 {
+                               regulator-min-microvolt = <3075000>;
+                               regulator-max-microvolt = <3625000>;
+                               regulator-always-on;
+                       };
+
+                       vgen6_reg: vgen6 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+               };
+       };
+
+       eeprom@54 {
+               compatible = "atmel,24c128";
+               reg = <0x54>;
+       };
+
+       ds1341: rtc@68 {
+               compatible = "dallas,ds1341";
+               reg = <0x68>;
+       };
+};
+
+&i2c3 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+
+       usbhub: usbhub@2c {
+               compatible ="microchip,usb2513b";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_usbhub>;
+               reg = <0x2c>;
+               reset-gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
+       };
+};
+
+&i2c4 {
+       clock-frequency = <400000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c4>;
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+
+       rave-sp {
+               compatible = "zii,rave-sp-rdu2";
+               current-speed = <1000000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               watchdog {
+                       compatible = "zii,rave-sp-watchdog";
+               };
+
+               backlight {
+                       compatible = "zii,rave-sp-backlight";
+               };
+
+               pwrbutton {
+                       compatible = "zii,rave-sp-pwrbutton";
+               };
+
+               eeprom@a3 {
+                       compatible = "zii,rave-sp-eeprom";
+                       reg = <0xa3 0x4000>;
+                       zii,eeprom-name = "dds-eeprom";
+               };
+
+               eeprom@a4 {
+                       compatible = "zii,rave-sp-eeprom";
+                       reg = <0xa4 0x4000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       zii,eeprom-name = "main-eeprom";
+               };
+       };
+};
+
+&usb3_phy0 {
+       vbus-supply = <&reg_5p0_user_usb>;
+       status = "okay";
+};
+
+&usb_dwc3_0 {
+       dr_mode = "host";
+       status = "okay";
+};
+
+&usb3_phy1 {
+       vbus-supply = <&reg_5p0_main>;
+       status = "okay";
+};
+
+&usb_dwc3_1 {
+       dr_mode = "host";
+       status = "okay";
+};
+
+&pcie0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pcie0>;
+       reset-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
+       clocks = <&clk IMX8MQ_CLK_PCIE1_ROOT>,
+                <&clk IMX8MQ_CLK_PCIE1_AUX>,
+                <&clk IMX8MQ_CLK_PCIE1_PHY>,
+                <&pcie0_refclk>;
+       clock-names = "pcie", "pcie_aux", "pcie_phy", "pcie_bus";
+       status = "okay";
+};
+
+&pcie1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pcie1>;
+       reset-gpio = <&gpio1 6 GPIO_ACTIVE_LOW>;
+       clocks = <&clk IMX8MQ_CLK_PCIE2_ROOT>,
+                <&clk IMX8MQ_CLK_PCIE2_AUX>,
+                <&clk IMX8MQ_CLK_PCIE2_PHY>,
+                <&pcie1_refclk>;
+       clock-names = "pcie", "pcie_aux", "pcie_phy", "pcie_bus";
+       status = "okay";
+};
+
+&pgc_gpu {
+       power-supply = <&sw1a_reg>;
+};
+
+&pgc_vpu {
+       power-supply = <&sw1c_reg>;
+};
+
+&usdhc1 {
+       pinctrl-names = "default", "state_100mhz", "state_200mhz";
+       pinctrl-0 = <&pinctrl_usdhc1>;
+       pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+       vqmmc-supply = <&sw4_reg>;
+       bus-width = <8>;
+       non-removable;
+       no-sd;
+       no-sdio;
+       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 = <&gpio2 12 GPIO_ACTIVE_LOW>;
+       vmmc-supply = <&reg_usdhc2_vmmc>;
+       status = "okay";
+};
+
+&snvs_rtc {
+       status = "disabled";
+};
+
+&iomuxc {
+       pinctrl_fec1: fec1grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC                 0x3
+                       MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO               0x23
+                       MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1           0x1f
+                       MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0           0x1f
+                       MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1           0x91
+                       MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0           0x91
+                       MX8MQ_IOMUXC_ENET_TD2_ENET1_TX_CLK              0x1f
+                       MX8MQ_IOMUXC_ENET_RXC_ENET1_RX_ER               0x91
+                       MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL     0x91
+                       MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL     0x1f
+               >;
+       };
+
+       pinctrl_fec1_phy_reset: fec1phyresetgrp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_ENET_RD3_GPIO1_IO29                0x11
+               >;
+       };
+
+       pinctrl_gpio3_hog: gpio3hoggrp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_NAND_DATA04_GPIO3_IO10             0x6
+                       MX8MQ_IOMUXC_NAND_DATA05_GPIO3_IO11             0x6
+                       MX8MQ_IOMUXC_NAND_DATA07_GPIO3_IO13             0x6
+               >;
+       };
+
+       pinctrl_i2c1: i2c1grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL                  0x4000007f
+                       MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA                  0x4000007f
+               >;
+       };
+
+       pinctrl_i2c2: i2c2grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL                  0x4000007f
+                       MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA                  0x4000007f
+               >;
+       };
+
+       pinctrl_i2c3: i2c3grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_I2C3_SCL_I2C3_SCL                  0x4000007f
+                       MX8MQ_IOMUXC_I2C3_SDA_I2C3_SDA                  0x4000007f
+               >;
+       };
+
+       pinctrl_i2c4: i2c4grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_I2C4_SCL_I2C4_SCL                  0x4000007f
+                       MX8MQ_IOMUXC_I2C4_SDA_I2C4_SDA                  0x4000007f
+               >;
+       };
+
+       pinctrl_mdio_bitbang: bitbangmdiogrp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_GPIO1_IO13_GPIO1_IO13              0x44
+                       MX8MQ_IOMUXC_GPIO1_IO14_GPIO1_IO14              0x64
+               >;
+       };
+
+       pinctrl_pcie0: pcie0grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_UART4_RXD_PCIE1_CLKREQ_B           0x66
+                       MX8MQ_IOMUXC_GPIO1_IO03_GPIO1_IO3               0x6
+               >;
+       };
+
+       pinctrl_pcie1: pcie1grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_UART4_TXD_PCIE2_CLKREQ_B           0x66
+                       MX8MQ_IOMUXC_GPIO1_IO06_GPIO1_IO6               0x6
+               >;
+       };
+
+       pinctrl_reg_arm: regarmgrp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_NAND_READY_B_GPIO3_IO16            0x19
+               >;
+       };
+
+       pinctrl_reg_usdhc2: regusdhc2grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_SD2_RESET_B_GPIO2_IO19             0x41
+               >;
+       };
+
+       pinctrl_reg_user_usb: reguserusbgrp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_NAND_DATA06_GPIO3_IO12             0x6
+               >;
+       };
+
+       pinctrl_switch_irq: switchgrp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_GPIO1_IO15_GPIO1_IO15              0x41
+               >;
+       };
+
+       pinctrl_ts: tsgrp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_GPIO1_IO11_GPIO1_IO11              0x96
+                       MX8MQ_IOMUXC_GPIO1_IO12_GPIO1_IO12              0x96
+               >;
+       };
+
+       pinctrl_uart1: uart1grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX             0x49
+                       MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX             0x49
+               >;
+       };
+
+       pinctrl_uart2: uart2grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX             0x49
+                       MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX             0x49
+               >;
+       };
+
+       pinctrl_usbhub: usbhubgrp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_SAI5_MCLK_GPIO3_IO25               0x41
+               >;
+       };
+
+       pinctrl_usdhc1: usdhc1grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x83
+                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xc3
+                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xc3
+                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xc3
+                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xc3
+                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xc3
+                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xc3
+                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xc3
+                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xc3
+                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xc3
+                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x83
+                       MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B         0xc1
+               >;
+       };
+
+       pinctrl_usdhc1_100mhz: usdhc1-100grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x8d
+                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xcd
+                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xcd
+                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x8d
+                       MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B         0xc1
+               >;
+       };
+
+       pinctrl_usdhc1_200mhz: usdhc1-200grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x9f
+                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xdf
+                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xdf
+                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x9f
+                       MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B         0xc1
+               >;
+       };
+
+       pinctrl_usdhc2: usdhc2grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK                 0x83
+                       MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD                 0xc3
+                       MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0             0xc3
+                       MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1             0xc3
+                       MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2             0xc3
+                       MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3             0xc3
+                       MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT          0xc1
+               >;
+       };
+
+       pinctrl_usdhc2_100mhz: usdhc2-100grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK                 0x85
+                       MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD                 0xc5
+                       MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0             0xc5
+                       MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1             0xc5
+                       MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2             0xc5
+                       MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3             0xc5
+                       MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT          0xc1
+               >;
+       };
+
+       pinctrl_usdhc2_200mhz: usdhc2-200grp {
+               fsl,pins = <
+                       MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK                 0x87
+                       MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD                 0xc7
+                       MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0             0xc7
+                       MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1             0xc7
+                       MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2             0xc7
+                       MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3             0xc7
+                       MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT          0xc1
+               >;
+       };
+};
index 9155bd4..6d635ba 100644 (file)
@@ -6,8 +6,10 @@
 
 #include <dt-bindings/clock/imx8mq-clock.h>
 #include <dt-bindings/power/imx8mq-power.h>
+#include <dt-bindings/reset/imx8mq-reset.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/thermal/thermal.h>
 #include "imx8mq-pinfunc.h"
 
 / {
                        device_type = "cpu";
                        compatible = "arm,cortex-a53";
                        reg = <0x0>;
+                       clock-latency = <61036>; /* two CLK32 periods */
+                       clocks = <&clk IMX8MQ_CLK_ARM>;
                        enable-method = "psci";
                        next-level-cache = <&A53_L2>;
+                       operating-points-v2 = <&a53_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                A53_1: cpu@1 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a53";
                        reg = <0x1>;
+                       clock-latency = <61036>; /* two CLK32 periods */
+                       clocks = <&clk IMX8MQ_CLK_ARM>;
                        enable-method = "psci";
                        next-level-cache = <&A53_L2>;
+                       operating-points-v2 = <&a53_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                A53_2: cpu@2 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a53";
                        reg = <0x2>;
+                       clock-latency = <61036>; /* two CLK32 periods */
+                       clocks = <&clk IMX8MQ_CLK_ARM>;
                        enable-method = "psci";
                        next-level-cache = <&A53_L2>;
+                       operating-points-v2 = <&a53_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                A53_3: cpu@3 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a53";
                        reg = <0x3>;
+                       clock-latency = <61036>; /* two CLK32 periods */
+                       clocks = <&clk IMX8MQ_CLK_ARM>;
                        enable-method = "psci";
                        next-level-cache = <&A53_L2>;
+                       operating-points-v2 = <&a53_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                A53_L2: l2-cache0 {
                };
        };
 
+       a53_opp_table: opp-table {
+               compatible = "operating-points-v2";
+               opp-shared;
+
+               opp-800000000 {
+                       opp-hz = /bits/ 64 <800000000>;
+                       opp-microvolt = <900000>;
+                       clock-latency-ns = <150000>;
+               };
+
+               opp-1300000000 {
+                       opp-hz = /bits/ 64 <1300000000>;
+                       opp-microvolt = <1000000>;
+                       clock-latency-ns = <150000>;
+                       opp-suspend;
+               };
+       };
+
        pmu {
                compatible = "arm,cortex-a53-pmu";
                interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
                method = "smc";
        };
 
+       thermal-zones {
+               cpu-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <2000>;
+                       thermal-sensors = <&tmu 0>;
+
+                       trips {
+                               cpu_alert: cpu-alert {
+                                       temperature = <80000>;
+                                       hysteresis = <2000>;
+                                       type = "passive";
+                               };
+
+                               cpu-crit {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
+
+                       cooling-maps {
+                               map0 {
+                                       trip = <&cpu_alert>;
+                                       cooling-device =
+                                               <&A53_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+                                               <&A53_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+                                               <&A53_2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+                                               <&A53_3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+                               };
+                       };
+               };
+
+               gpu-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <2000>;
+                       thermal-sensors = <&tmu 1>;
+
+                       trips {
+                               gpu-crit {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
+               };
+
+               vpu-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <2000>;
+                       thermal-sensors = <&tmu 2>;
+
+                       trips {
+                               vpu-crit {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
+               };
+       };
+
        timer {
                compatible = "arm,armv8-timer";
                interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, /* Physical Secure */
                                reg = <0x30200000 0x10000>;
                                interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MQ_CLK_GPIO1_ROOT>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                                reg = <0x30210000 0x10000>;
                                interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MQ_CLK_GPIO2_ROOT>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                                reg = <0x30220000 0x10000>;
                                interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MQ_CLK_GPIO3_ROOT>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                                reg = <0x30230000 0x10000>;
                                interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MQ_CLK_GPIO4_ROOT>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                                reg = <0x30240000 0x10000>;
                                interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MQ_CLK_GPIO5_ROOT>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
                        };
 
+                       tmu: tmu@30260000 {
+                               compatible = "fsl,imx8mq-tmu";
+                               reg = <0x30260000 0x10000>;
+                               interrupt = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+                               little-endian;
+                               fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x70061>;
+                               fsl,tmu-calibration = <0x00000000 0x00000023
+                                                      0x00000001 0x00000029
+                                                      0x00000002 0x0000002f
+                                                      0x00000003 0x00000035
+                                                      0x00000004 0x0000003d
+                                                      0x00000005 0x00000043
+                                                      0x00000006 0x0000004b
+                                                      0x00000007 0x00000051
+                                                      0x00000008 0x00000057
+                                                      0x00000009 0x0000005f
+                                                      0x0000000a 0x00000067
+                                                      0x0000000b 0x0000006f
+
+                                                      0x00010000 0x0000001b
+                                                      0x00010001 0x00000023
+                                                      0x00010002 0x0000002b
+                                                      0x00010003 0x00000033
+                                                      0x00010004 0x0000003b
+                                                      0x00010005 0x00000043
+                                                      0x00010006 0x0000004b
+                                                      0x00010007 0x00000055
+                                                      0x00010008 0x0000005d
+                                                      0x00010009 0x00000067
+                                                      0x0001000a 0x00000070
+
+                                                      0x00020000 0x00000017
+                                                      0x00020001 0x00000023
+                                                      0x00020002 0x0000002d
+                                                      0x00020003 0x00000037
+                                                      0x00020004 0x00000041
+                                                      0x00020005 0x0000004b
+                                                      0x00020006 0x00000057
+                                                      0x00020007 0x00000063
+                                                      0x00020008 0x0000006f
+
+                                                      0x00030000 0x00000015
+                                                      0x00030001 0x00000021
+                                                      0x00030002 0x0000002d
+                                                      0x00030003 0x00000039
+                                                      0x00030004 0x00000045
+                                                      0x00030005 0x00000053
+                                                      0x00030006 0x0000005f
+                                                      0x00030007 0x00000071>;
+                               #thermal-sensor-cells =  <1>;
+                       };
+
                        wdog1: watchdog@30280000 {
                                compatible = "fsl,imx8mq-wdt", "fsl,imx21-wdt";
                                reg = <0x30280000 0x10000>;
                                status = "disabled";
                        };
 
+                       sdma2: sdma@302c0000 {
+                               compatible = "fsl,imx8mq-sdma","fsl,imx7d-sdma";
+                               reg = <0x302c0000 0x10000>;
+                               interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MQ_CLK_SDMA2_ROOT>,
+                                        <&clk IMX8MQ_CLK_SDMA2_ROOT>;
+                               clock-names = "ipg", "ahb";
+                               #dma-cells = <3>;
+                               fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
+                       };
+
                        iomuxc: iomuxc@30330000 {
                                compatible = "fsl,imx8mq-iomuxc";
                                reg = <0x30330000 0x10000>;
                        };
 
                        iomuxc_gpr: syscon@30340000 {
-                               compatible = "fsl,imx8mq-iomuxc-gpr", "syscon";
+                               compatible = "fsl,imx8mq-iomuxc-gpr", "fsl,imx6q-iomuxc-gpr", "syscon";
                                reg = <0x30340000 0x10000>;
                        };
 
+                       ocotp: ocotp-ctrl@30350000 {
+                               compatible = "fsl,imx8mq-ocotp", "syscon";
+                               reg = <0x30350000 0x10000>;
+                               clocks = <&clk IMX8MQ_CLK_OCOTP_ROOT>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                       };
+
                        anatop: syscon@30360000 {
                                compatible = "fsl,imx8mq-anatop", "syscon";
                                reg = <0x30360000 0x10000>;
                                              "clk_ext3", "clk_ext4";
                        };
 
+                       src: reset-controller@30390000 {
+                               compatible = "fsl,imx8mq-src", "syscon";
+                               reg = <0x30390000 0x10000>;
+                               #reset-cells = <1>;
+                       };
+
                        gpc: gpc@303a0000 {
                                compatible = "fsl,imx8mq-gpc";
                                reg = <0x303a0000 0x10000>;
                                                reg = <IMX8M_POWER_DOMAIN_MIPI>;
                                        };
 
-                                       pgc_pcie1: power-domain@1 {
+                                       /*
+                                        * As per comment in ATF source code:
+                                        *
+                                        * PCIE1 and PCIE2 share the
+                                        * same reset signal, if we
+                                        * power down PCIE2, PCIE1
+                                        * will be held in reset too.
+                                        *
+                                        * So instead of creating two
+                                        * separate power domains for
+                                        * PCIE1 and PCIE2 we create a
+                                        * link between both and use
+                                        * it as a shared PCIE power
+                                        * domain.
+                                        */
+                                       pgc_pcie: power-domain@1 {
                                                #power-domain-cells = <0>;
                                                reg = <IMX8M_POWER_DOMAIN_PCIE1>;
+                                               power-domains = <&pgc_pcie2>;
                                        };
 
                                        pgc_otg1: power-domain@2 {
                                status = "disabled";
                        };
 
+                       sai2: sai@308b0000 {
+                               #sound-dai-cells = <0>;
+                               compatible = "fsl,imx8mq-sai",
+                                            "fsl,imx6sx-sai";
+                               reg = <0x308b0000 0x10000>;
+                               interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MQ_CLK_SAI2_IPG>,
+                                        <&clk IMX8MQ_CLK_SAI2_ROOT>,
+                                        <&clk IMX8MQ_CLK_DUMMY>, <&clk IMX8MQ_CLK_DUMMY>;
+                               clock-names = "bus", "mclk1", "mclk2", "mclk3";
+                               dmas = <&sdma1 10 24 0>, <&sdma1 11 24 0>;
+                               dma-names = "rx", "tx";
+                               status = "disabled";
+                       };
+
                        i2c1: i2c@30a20000 {
                                compatible = "fsl,imx8mq-i2c", "fsl,imx21-i2c";
                                reg = <0x30a20000 0x10000>;
                                status = "disabled";
                        };
 
+                       sdma1: sdma@30bd0000 {
+                               compatible = "fsl,imx8mq-sdma","fsl,imx7d-sdma";
+                               reg = <0x30bd0000 0x10000>;
+                               interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clk IMX8MQ_CLK_SDMA1_ROOT>,
+                                        <&clk IMX8MQ_CLK_AHB>;
+                               clock-names = "ipg", "ahb";
+                               #dma-cells = <3>;
+                               fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
+                       };
+
                        fec1: ethernet@30be0000 {
                                compatible = "fsl,imx8mq-fec", "fsl,imx6sx-fec";
                                reg = <0x30be0000 0x10000>;
                        };
                };
 
+               gpu: gpu@38000000 {
+                       compatible = "vivante,gc";
+                       reg = <0x38000000 0x40000>;
+                       interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk IMX8MQ_CLK_GPU_ROOT>,
+                                <&clk IMX8MQ_CLK_GPU_SHADER_DIV>,
+                                <&clk IMX8MQ_CLK_GPU_AXI>,
+                                <&clk IMX8MQ_CLK_GPU_AHB>;
+                       clock-names = "core", "shader", "bus", "reg";
+                       assigned-clocks = <&clk IMX8MQ_CLK_GPU_CORE_SRC>,
+                                         <&clk IMX8MQ_CLK_GPU_SHADER_SRC>,
+                                         <&clk IMX8MQ_CLK_GPU_AXI>,
+                                         <&clk IMX8MQ_CLK_GPU_AHB>,
+                                         <&clk IMX8MQ_GPU_PLL_BYPASS>;
+                       assigned-clock-parents = <&clk IMX8MQ_GPU_PLL_OUT>,
+                                                <&clk IMX8MQ_GPU_PLL_OUT>,
+                                                <&clk IMX8MQ_GPU_PLL_OUT>,
+                                                <&clk IMX8MQ_GPU_PLL_OUT>,
+                                                <&clk IMX8MQ_GPU_PLL>;
+                       assigned-clock-rates = <800000000>, <800000000>,
+                                              <800000000>, <800000000>, <0>;
+                       power-domains = <&pgc_gpu>;
+               };
+
                usb_dwc3_0: usb@38100000 {
                        compatible = "fsl,imx8mq-dwc3", "snps,dwc3";
                        reg = <0x38100000 0x10000>;
                        status = "disabled";
                };
 
+
+               pcie0: pcie@33800000 {
+                       compatible = "fsl,imx8mq-pcie";
+                       reg = <0x33800000 0x400000>,
+                             <0x1ff00000 0x80000>;
+                       reg-names = "dbi", "config";
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       device_type = "pci";
+                       bus-range = <0x00 0xff>;
+                       ranges = <0x81000000 0 0x00000000 0x1ff80000 0 0x00010000 /* downstream I/O 64KB */
+                                 0x82000000 0 0x18000000 0x18000000 0 0x07f00000>; /* non-prefetchable memory */
+                       num-lanes = <1>;
+                       num-viewport = <4>;
+                       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 &gic GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+                                       <0 0 0 2 &gic GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+                                       <0 0 0 3 &gic GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+                                       <0 0 0 4 &gic GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+                       fsl,max-link-speed = <2>;
+                       power-domains = <&pgc_pcie>;
+                       resets = <&src IMX8MQ_RESET_PCIEPHY>,
+                                <&src IMX8MQ_RESET_PCIE_CTRL_APPS_EN>,
+                                <&src IMX8MQ_RESET_PCIE_CTRL_APPS_TURNOFF>;
+                       reset-names = "pciephy", "apps", "turnoff";
+                       status = "disabled";
+               };
+
+               pcie1: pcie@33c00000 {
+                       compatible = "fsl,imx8mq-pcie";
+                       reg = <0x33c00000 0x400000>,
+                             <0x27f00000 0x80000>;
+                       reg-names = "dbi", "config";
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       device_type = "pci";
+                       ranges =  <0x81000000 0 0x00000000 0x27f80000 0 0x00010000 /* downstream I/O 64KB */
+                                  0x82000000 0 0x20000000 0x20000000 0 0x07f00000>; /* non-prefetchable memory */
+                       num-lanes = <1>;
+                       num-viewport = <4>;
+                       interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "msi";
+                       #interrupt-cells = <1>;
+                       interrupt-map-mask = <0 0 0 0x7>;
+                       interrupt-map = <0 0 0 1 &gic GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+                                       <0 0 0 2 &gic GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+                                       <0 0 0 3 &gic GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
+                                       <0 0 0 4 &gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+                       fsl,max-link-speed = <2>;
+                       power-domains = <&pgc_pcie>;
+                       resets = <&src IMX8MQ_RESET_PCIEPHY2>,
+                                <&src IMX8MQ_RESET_PCIE2_CTRL_APPS_EN>,
+                                <&src IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF>;
+                       reset-names = "pciephy", "apps", "turnoff";
+                       status = "disabled";
+               };
+
                gic: interrupt-controller@38800000 {
                        compatible = "arm,gic-v3";
                        reg = <0x38800000 0x10000>,     /* GIC Dist */
index 03aad66..bfdada2 100644 (file)
        };
 };
 
+&adma_i2c1 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_lpi2c1 &pinctrl_ioexp_rst>;
+       status = "okay";
+
+       i2c-switch@71 {
+               compatible = "nxp,pca9646", "nxp,pca9546";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0x71>;
+               reset-gpios = <&lsio_gpio1 1 GPIO_ACTIVE_LOW>;
+
+               i2c@0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0>;
+
+                       max7322: gpio@68 {
+                               compatible = "maxim,max7322";
+                               reg = <0x68>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                       };
+               };
+
+               i2c@1 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <1>;
+               };
+
+               i2c@2 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <2>;
+
+                       pressure-sensor@60 {
+                               compatible = "fsl,mpl3115";
+                               reg = <0x60>;
+                       };
+               };
+
+               i2c@3 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <3>;
+
+                       pca9557_a: gpio@1a {
+                               compatible = "nxp,pca9557";
+                               reg = <0x1a>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                       };
+
+                       pca9557_b: gpio@1d {
+                               compatible = "nxp,pca9557";
+                               reg = <0x1d>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                       };
+
+                       light-sensor@44 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_isl29023>;
+                               compatible = "isil,isl29023";
+                               reg = <0x44>;
+                               interrupt-parent = <&lsio_gpio1>;
+                               interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+                       };
+               };
+       };
+};
+
 &usdhc1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usdhc1>;
                >;
        };
 
+       pinctrl_ioexp_rst: ioexp_rst_grp {
+               fsl,pins = <
+                       IMX8QXP_SPI2_SDO_LSIO_GPIO1_IO01                        0x06000021
+               >;
+       };
+
+       pinctrl_isl29023: isl29023grp {
+               fsl,pins = <
+                       IMX8QXP_SPI2_SDI_LSIO_GPIO1_IO02                        0x00000021
+               >;
+       };
+
+       pinctrl_lpi2c1: lpi2c1grp {
+               fsl,pins = <
+                       IMX8QXP_USB_SS3_TC1_ADMA_I2C1_SCL                       0x06000021
+                       IMX8QXP_USB_SS3_TC3_ADMA_I2C1_SDA                       0x06000021
+               >;
+       };
+
        pinctrl_lpuart0: lpuart0grp {
                fsl,pins = <
                        IMX8QXP_UART0_RX_ADMA_UART0_RX                          0x06000020
index 4c3dd95..0683ee2 100644 (file)
@@ -21,6 +21,7 @@
                mmc1 = &usdhc2;
                mmc2 = &usdhc3;
                serial0 = &adma_lpuart0;
+               mu1 = &lsio_mu1;
        };
 
        cpus {
@@ -34,6 +35,9 @@
                        reg = <0x0 0x0>;
                        enable-method = "psci";
                        next-level-cache = <&A35_L2>;
+                       clocks = <&clk IMX_A35_CLK>;
+                       operating-points-v2 = <&a35_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                A35_1: cpu@1 {
@@ -42,6 +46,9 @@
                        reg = <0x0 0x1>;
                        enable-method = "psci";
                        next-level-cache = <&A35_L2>;
+                       clocks = <&clk IMX_A35_CLK>;
+                       operating-points-v2 = <&a35_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                A35_2: cpu@2 {
@@ -50,6 +57,9 @@
                        reg = <0x0 0x2>;
                        enable-method = "psci";
                        next-level-cache = <&A35_L2>;
+                       clocks = <&clk IMX_A35_CLK>;
+                       operating-points-v2 = <&a35_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                A35_3: cpu@3 {
@@ -58,6 +68,9 @@
                        reg = <0x0 0x3>;
                        enable-method = "psci";
                        next-level-cache = <&A35_L2>;
+                       clocks = <&clk IMX_A35_CLK>;
+                       operating-points-v2 = <&a35_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                A35_L2: l2-cache0 {
                };
        };
 
+       a35_opp_table: opp-table {
+               compatible = "operating-points-v2";
+               opp-shared;
+
+               opp-900000000 {
+                       opp-hz = /bits/ 64 <900000000>;
+                       opp-microvolt = <1000000>;
+                       clock-latency-ns = <150000>;
+               };
+
+               opp-1200000000 {
+                       opp-hz = /bits/ 64 <1200000000>;
+                       opp-microvolt = <1100000>;
+                       clock-latency-ns = <150000>;
+                       opp-suspend;
+               };
+       };
+
        gic: interrupt-controller@51a00000 {
                compatible = "arm,gic-v3";
                reg = <0x0 0x51a00000 0 0x10000>, /* GIC Dist */
        scu {
                compatible = "fsl,imx-scu";
                mbox-names = "tx0", "tx1", "tx2", "tx3",
-                            "rx0", "rx1", "rx2", "rx3";
+                            "rx0", "rx1", "rx2", "rx3",
+                            "gip3";
                mboxes = <&lsio_mu1 0 0
                          &lsio_mu1 0 1
                          &lsio_mu1 0 2
                          &lsio_mu1 1 0
                          &lsio_mu1 1 1
                          &lsio_mu1 1 2
-                         &lsio_mu1 1 3>;
+                         &lsio_mu1 1 3
+                         &lsio_mu1 3 3>;
 
                clk: clock-controller {
                        compatible = "fsl,imx8qxp-clk";
                        status = "disabled";
                };
 
+               adma_lpuart1: serial@5a070000 {
+                       compatible = "fsl,imx8qxp-lpuart", "fsl,imx7ulp-lpuart";
+                       reg = <0x5a070000 0x1000>;
+                       interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-parent = <&gic>;
+                       clocks = <&adma_lpcg IMX_ADMA_LPCG_UART1_BAUD_CLK>;
+                       clock-names = "ipg";
+                       power-domains = <&pd IMX_SC_R_UART_1>;
+                       status = "disabled";
+               };
+
+               adma_lpuart2: serial@5a080000 {
+                       compatible = "fsl,imx8qxp-lpuart", "fsl,imx7ulp-lpuart";
+                       reg = <0x5a080000 0x1000>;
+                       interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-parent = <&gic>;
+                       clocks = <&adma_lpcg IMX_ADMA_LPCG_UART2_BAUD_CLK>;
+                       clock-names = "ipg";
+                       power-domains = <&pd IMX_SC_R_UART_2>;
+                       status = "disabled";
+               };
+
+               adma_lpuart3: serial@5a090000 {
+                       compatible = "fsl,imx8qxp-lpuart", "fsl,imx7ulp-lpuart";
+                       reg = <0x5a090000 0x1000>;
+                       interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-parent = <&gic>;
+                       clocks = <&adma_lpcg IMX_ADMA_LPCG_UART3_BAUD_CLK>;
+                       clock-names = "ipg";
+                       power-domains = <&pd IMX_SC_R_UART_3>;
+                       status = "disabled";
+               };
+
                adma_i2c0: i2c@5a800000 {
                        compatible = "fsl,imx8qxp-lpi2c", "fsl,imx7ulp-lpi2c";
                        reg = <0x5a800000 0x4000>;
                        compatible = "fsl,imx8qxp-mu", "fsl,imx6sx-mu";
                        reg = <0x5d1b0000 0x10000>;
                        interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
-                       #mbox-cells = <0>;
+                       #mbox-cells = <2>;
                        status = "disabled";
                };
 
                        #mbox-cells = <2>;
                };
 
+               lsio_mu2: mailbox@5d1d0000 {
+                       compatible = "fsl,imx8qxp-mu", "fsl,imx6sx-mu";
+                       reg = <0x5d1d0000 0x10000>;
+                       interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>;
+                       #mbox-cells = <2>;
+                       status = "disabled";
+               };
+
                lsio_mu3: mailbox@5d1e0000 {
                        compatible = "fsl,imx8qxp-mu", "fsl,imx6sx-mu";
                        reg = <0x5d1e0000 0x10000>;
                        interrupts = <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>;
-                       #mbox-cells = <0>;
+                       #mbox-cells = <2>;
                        status = "disabled";
                };
 
                        compatible = "fsl,imx8qxp-mu", "fsl,imx6sx-mu";
                        reg = <0x5d1f0000 0x10000>;
                        interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
-                       #mbox-cells = <0>;
+                       #mbox-cells = <2>;
                        status = "disabled";
                };
 
                        power-domains = <&pd IMX_SC_R_GPIO_7>;
                };
        };
+
+       watchdog {
+               compatible = "fsl,imx8qxp-sc-wdt", "fsl,imx-sc-wdt";
+               timeout-sec = <60>;
+       };
 };
index 2f19e0e..aa6a8ad 100644 (file)
                        compatible = "arm,pl011", "arm,primecell";
                        reg = <0x0 0xfdf00000 0x0 0x1000>;
                        interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+                       dma-names = "rx", "tx";
+                       dmas =  <&dma0 2 &dma0 3>;
                        clocks = <&crg_ctrl HI3660_CLK_GATE_UART1>,
                                 <&crg_ctrl HI3660_CLK_GATE_UART1>;
                        clock-names = "uartclk", "apb_pclk";
                        compatible = "arm,pl011", "arm,primecell";
                        reg = <0x0 0xfdf03000 0x0 0x1000>;
                        interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+                       dma-names = "rx", "tx";
+                       dmas =  <&dma0 4 &dma0 5>;
                        clocks = <&crg_ctrl HI3660_CLK_GATE_UART2>,
                                 <&crg_ctrl HI3660_PCLK>;
                        clock-names = "uartclk", "apb_pclk";
                        compatible = "arm,pl011", "arm,primecell";
                        reg = <0x0 0xfdf01000 0x0 0x1000>;
                        interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+                       dma-names = "rx", "tx";
+                       dmas =  <&dma0 6 &dma0 7>;
                        clocks = <&crg_ctrl HI3660_CLK_GATE_UART4>,
                                 <&crg_ctrl HI3660_CLK_GATE_UART4>;
                        clock-names = "uartclk", "apb_pclk";
                        compatible = "arm,pl011", "arm,primecell";
                        reg = <0x0 0xfdf05000 0x0 0x1000>;
                        interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+                       dma-names = "rx", "tx";
+                       dmas =  <&dma0 8 &dma0 9>;
                        clocks = <&crg_ctrl HI3660_CLK_GATE_UART5>,
                                 <&crg_ctrl HI3660_CLK_GATE_UART5>;
                        clock-names = "uartclk", "apb_pclk";
                        #dma-cells = <1>;
                        dma-channels = <16>;
                        dma-requests = <32>;
-                       dma-min-chan = <1>;
+                       dma-channel-mask = <0xfffe>;
                        interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&crg_ctrl HI3660_CLK_GATE_DMAC>;
                        dma-no-cci;
                        dma-type = "hi3660_dma";
                };
 
+               asp_dmac: dma-controller@e804b000 {
+                       compatible = "hisilicon,hisi-pcm-asp-dma-1.0";
+                       reg = <0x0 0xe804b000 0x0 0x1000>;
+                       #dma-cells = <1>;
+                       dma-channels = <16>;
+                       dma-requests = <32>;
+                       interrupts = <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "asp_dma_irq";
+               };
+
                rtc0: rtc@fff04000 {
                        compatible = "arm,pl031", "arm,primecell";
                        reg = <0x0 0Xfff04000 0x0 0x1000>;
index c9775b6..7dac33d 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 
 #include "hi3670.dtsi"
 #include "hikey970-pinctrl.dtsi"
@@ -17,6 +18,8 @@
        compatible = "hisilicon,hi3670-hikey970", "hisilicon,hi3670";
 
        aliases {
+               mshc1 = &dwmmc1;
+               mshc2 = &dwmmc2;
                serial0 = &uart0;
                serial1 = &uart1;
                serial2 = &uart2;
                /* expect bootloader to fill in this region */
                reg = <0x0 0x0 0x0 0x0>;
        };
+
+       sd_1v8: regulator-1v8 {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-1.8V";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-always-on;
+       };
+
+       sd_3v3: regulator-3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
+       wlan_en: wlan-en-1-8v {
+               compatible = "regulator-fixed";
+               regulator-name = "wlan-en-regulator";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+
+               /* GPIO_051_WIFI_EN */
+               gpio = <&gpio6 3 0>;
+
+               /* WLAN card specific delay */
+               startup-delay-us = <70000>;
+               enable-active-high;
+       };
 };
 
 /*
                "GPIO_231_HDMI_INT";
 };
 
+&dwmmc1 {
+       bus-width = <0x4>;
+       sd-uhs-sdr12;
+       sd-uhs-sdr25;
+       sd-uhs-sdr50;
+       sd-uhs-sdr104;
+       cap-sd-highspeed;
+       disable-wp;
+       cd-inverted;
+       cd-gpios = <&gpio25 5 GPIO_ACTIVE_HIGH>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sd_pmx_func
+                    &sd_clk_cfg_func
+                    &sd_cfg_func>;
+       vmmc-supply = <&sd_3v3>;
+       vqmmc-supply = <&sd_1v8>;
+       status = "okay";
+};
+
+&dwmmc2 { /* WIFI */
+       bus-width = <0x4>;
+       non-removable;
+       broken-cd;
+       cap-power-off-card;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdio_pmx_func
+                    &sdio_clk_cfg_func
+                    &sdio_cfg_func>;
+       /* WL_EN */
+       vmmc-supply = <&wlan_en>;
+       status = "ok";
+
+       wlcore: wlcore@2 {
+               compatible = "ti,wl1837";
+               reg = <2>;      /* sdio func num */
+               /* WL_IRQ, GPIO_177_WL_WAKEUP_AP */
+               interrupt-parent = <&gpio22>;
+               interrupts = <1 IRQ_TYPE_EDGE_RISING>;
+       };
+};
+
 &uart0 {
        /* On High speed expansion header */
        label = "HS-UART0";
index 2ed06e4..2dcffa3 100644 (file)
                        #clock-cells = <1>;
                };
 
+               crg_rst: crg_rst_controller {
+                       compatible = "hisilicon,hi3670-reset",
+                                    "hisilicon,hi3660-reset";
+                       #reset-cells = <2>;
+                       hisi,rst-syscon = <&crg_ctrl>;
+               };
+
                pctrl: pctrl@e8a09000 {
                        compatible = "hisilicon,hi3670-pctrl", "syscon";
                        reg = <0x0 0xe8a09000 0x0 0x1000>;
                        clocks = <&sctrl HI3670_PCLK_AO_GPIO6>;
                        clock-names = "apb_pclk";
                };
+
+               /* UFS */
+               ufs: ufs@ff3c0000 {
+                       compatible = "hisilicon,hi3670-ufs", "jedec,ufs-2.1";
+                       /* 0: HCI standard */
+                       /* 1: UFS SYS CTRL */
+                       reg = <0x0 0xff3c0000 0x0 0x1000>,
+                               <0x0 0xff3e0000 0x0 0x1000>;
+                       interrupt-parent = <&gic>;
+                       interrupts = <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&crg_ctrl HI3670_CLK_GATE_UFSIO_REF>,
+                               <&crg_ctrl HI3670_CLK_GATE_UFS_SUBSYS>;
+                       clock-names = "ref_clk", "phy_clk";
+                       freq-table-hz = <0 0>, <0 0>;
+                       /* offset: 0x84; bit: 12 */
+                       resets = <&crg_rst 0x84 12>;
+                       reset-names = "rst";
+               };
+
+               /* SD */
+               dwmmc1: dwmmc1@ff37f000 {
+                       compatible = "hisilicon,hi3670-dw-mshc",
+                                    "hisilicon,hi3660-dw-mshc";
+                       reg = <0x0 0xff37f000 0x0 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&crg_ctrl HI3670_CLK_GATE_SD>,
+                               <&crg_ctrl HI3670_HCLK_GATE_SD>;
+                       clock-names = "ciu", "biu";
+                       clock-frequency = <3200000>;
+                       resets = <&crg_rst 0x94 18>;
+                       reset-names = "reset";
+                       hisilicon,peripheral-syscon = <&sctrl>;
+                       card-detect-delay = <200>;
+                       status = "disabled";
+               };
+
+               /* SDIO */
+               dwmmc2: dwmmc2@fc183000 {
+                       compatible = "hisilicon,hi3670-dw-mshc",
+                                    "hisilicon,hi3660-dw-mshc";
+                       reg = <0x0 0xfc183000 0x0 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&crg_ctrl HI3670_CLK_GATE_SDIO>,
+                               <&crg_ctrl HI3670_HCLK_GATE_SDIO>;
+                       clock-names = "ciu", "biu";
+                       clock-frequency = <3200000>;
+                       resets = <&crg_rst 0x94 20>;
+                       reset-names = "reset";
+                       card-detect-delay = <200>;
+                       status = "disabled";
+               };
        };
 };
index 67bb52d..d456b0a 100644 (file)
                        /* pin base, nr pins & gpio function */
                        pinctrl-single,gpio-range = <&range 0 10 0>;
 
+                       sdio_pmx_func: sdio_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x000 MUX_M1 /* SDIO_CLK */
+                                       0x004 MUX_M1 /* SDIO_CMD */
+                                       0x008 MUX_M1 /* SDIO_DATA0 */
+                                       0x00c MUX_M1 /* SDIO_DATA1 */
+                                       0x010 MUX_M1 /* SDIO_DATA2 */
+                                       0x014 MUX_M1 /* SDIO_DATA3 */
+                               >;
+                       };
                };
 
                pmx6: pinmux@fc182800 {
                        reg = <0x0 0xfc182800 0x0 0x028>;
                        #pinctrl-cells = <1>;
                        pinctrl-single,register-width = <0x20>;
+
+                       sdio_clk_cfg_func: sdio_clk_cfg_func {
+                               pinctrl-single,pins = <
+                                       0x000 0x0 /* SDIO_CLK */
+                               >;
+                               pinctrl-single,bias-pulldown = <
+                                       PULL_DIS
+                                       PULL_DOWN
+                                       PULL_DIS
+                                       PULL_DOWN
+                               >;
+                               pinctrl-single,bias-pullup = <
+                                       PULL_DIS
+                                       PULL_UP
+                                       PULL_DIS
+                                       PULL_UP
+                               >;
+                               pinctrl-single,drive-strength = <
+                                       DRIVE6_32MA DRIVE6_MASK
+                               >;
+                       };
+
+                       sdio_cfg_func: sdio_cfg_func {
+                               pinctrl-single,pins = <
+                                       0x004 0x0 /* SDIO_CMD */
+                                       0x008 0x0 /* SDIO_DATA0 */
+                                       0x00c 0x0 /* SDIO_DATA1 */
+                                       0x010 0x0 /* SDIO_DATA2 */
+                                       0x014 0x0 /* SDIO_DATA3 */
+                               >;
+                               pinctrl-single,bias-pulldown = <
+                                       PULL_DIS
+                                       PULL_DOWN
+                                       PULL_DIS
+                                       PULL_DOWN
+                               >;
+                               pinctrl-single,bias-pullup = <
+                                       PULL_UP
+                                       PULL_UP
+                                       PULL_DIS
+                                       PULL_UP
+                               >;
+                               pinctrl-single,drive-strength = <
+                                       DRIVE6_19MA DRIVE6_MASK
+                               >;
+                       };
                };
 
                pmx7: pinmux@ff37e000 {
                        pinctrl-single,function-mask = <7>;
                        /* pin base, nr pins & gpio function */
                        pinctrl-single,gpio-range = <&range 0 12 0>;
+
+                       sd_pmx_func: sd_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x000 MUX_M1 /* SD_CLK */
+                                       0x004 MUX_M1 /* SD_CMD */
+                                       0x008 MUX_M1 /* SD_DATA0 */
+                                       0x00c MUX_M1 /* SD_DATA1 */
+                                       0x010 MUX_M1 /* SD_DATA2 */
+                                       0x014 MUX_M1 /* SD_DATA3 */
+                               >;
+                       };
                };
 
                pmx8: pinmux@ff37e800 {
                        reg = <0x0 0xff37e800 0x0 0x030>;
                        #pinctrl-cells = <1>;
                        pinctrl-single,register-width = <0x20>;
+
+                       sd_clk_cfg_func: sd_clk_cfg_func {
+                               pinctrl-single,pins = <
+                                       0x000 0x0 /* SD_CLK */
+                               >;
+                               pinctrl-single,bias-pulldown = <
+                                       PULL_DIS
+                                       PULL_DOWN
+                                       PULL_DIS
+                                       PULL_DOWN
+                               >;
+                               pinctrl-single,bias-pullup = <
+                                       PULL_DIS
+                                       PULL_UP
+                                       PULL_DIS
+                                       PULL_UP
+                               >;
+                               pinctrl-single,drive-strength = <
+                                       DRIVE6_32MA
+                                       DRIVE6_MASK
+                               >;
+                       };
+
+                       sd_cfg_func: sd_cfg_func {
+                               pinctrl-single,pins = <
+                                       0x004 0x0 /* SD_CMD */
+                                       0x008 0x0 /* SD_DATA0 */
+                                       0x00c 0x0 /* SD_DATA1 */
+                                       0x010 0x0 /* SD_DATA2 */
+                                       0x014 0x0 /* SD_DATA3 */
+                               >;
+                               pinctrl-single,bias-pulldown = <
+                                       PULL_DIS
+                                       PULL_DOWN
+                                       PULL_DIS
+                                       PULL_DOWN
+                               >;
+                               pinctrl-single,bias-pullup = <
+                                       PULL_UP
+                                       PULL_UP
+                                       PULL_DIS
+                                       PULL_UP
+                               >;
+                               pinctrl-single,drive-strength = <
+                                       DRIVE6_19MA
+                                       DRIVE6_MASK
+                               >;
+                       };
                };
 
                pmx1: pinmux@fff11000 {
diff --git a/arch/arm64/boot/dts/intel/Makefile b/arch/arm64/boot/dts/intel/Makefile
new file mode 100644 (file)
index 0000000..9606ac8
--- /dev/null
@@ -0,0 +1 @@
+dtb-$(CONFIG_ARCH_AGILEX) += socfpga_agilex_socdk.dtb
diff --git a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
new file mode 100644 (file)
index 0000000..e4ceb3a
--- /dev/null
@@ -0,0 +1,444 @@
+// SPDX-License-Identifier:     GPL-2.0
+/*
+ * Copyright (C) 2019, Intel Corporation
+ */
+
+/dts-v1/;
+#include <dt-bindings/reset/altr,rst-mgr-s10.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       compatible = "intel,socfpga-agilex";
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: cpu@0 {
+                       compatible = "arm,cortex-a53";
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       reg = <0x0>;
+               };
+
+               cpu1: cpu@1 {
+                       compatible = "arm,cortex-a53";
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       reg = <0x1>;
+               };
+
+               cpu2: cpu@2 {
+                       compatible = "arm,cortex-a53";
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       reg = <0x2>;
+               };
+
+               cpu3: cpu@3 {
+                       compatible = "arm,cortex-a53";
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       reg = <0x3>;
+               };
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <0 120 8>,
+                            <0 121 8>,
+                            <0 122 8>,
+                            <0 123 8>;
+               interrupt-affinity = <&cpu0>,
+                                    <&cpu1>,
+                                    <&cpu2>,
+                                    <&cpu3>;
+               interrupt-parent = <&intc>;
+       };
+
+       psci {
+               compatible = "arm,psci-0.2";
+               method = "smc";
+       };
+
+       intc: intc@fffc1000 {
+               compatible = "arm,gic-400", "arm,cortex-a15-gic";
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               reg = <0x0 0xfffc1000 0x0 0x1000>,
+                     <0x0 0xfffc2000 0x0 0x2000>,
+                     <0x0 0xfffc4000 0x0 0x2000>,
+                     <0x0 0xfffc6000 0x0 0x2000>;
+       };
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               device_type = "soc";
+               interrupt-parent = <&intc>;
+               ranges = <0 0 0 0xffffffff>;
+
+               gmac0: ethernet@ff800000 {
+                       compatible = "altr,socfpga-stmmac", "snps,dwmac-3.74a", "snps,dwmac";
+                       reg = <0xff800000 0x2000>;
+                       interrupts = <0 90 4>;
+                       interrupt-names = "macirq";
+                       mac-address = [00 00 00 00 00 00];
+                       resets = <&rst EMAC0_RESET>, <&rst EMAC0_OCP_RESET>;
+                       reset-names = "stmmaceth", "stmmaceth-ocp";
+                       tx-fifo-depth = <16384>;
+                       rx-fifo-depth = <16384>;
+                       snps,multicast-filter-bins = <256>;
+                       iommus = <&smmu 1>;
+                       status = "disabled";
+               };
+
+               gmac1: ethernet@ff802000 {
+                       compatible = "altr,socfpga-stmmac", "snps,dwmac-3.74a", "snps,dwmac";
+                       reg = <0xff802000 0x2000>;
+                       interrupts = <0 91 4>;
+                       interrupt-names = "macirq";
+                       mac-address = [00 00 00 00 00 00];
+                       resets = <&rst EMAC1_RESET>, <&rst EMAC1_OCP_RESET>;
+                       reset-names = "stmmaceth", "stmmaceth-ocp";
+                       tx-fifo-depth = <16384>;
+                       rx-fifo-depth = <16384>;
+                       snps,multicast-filter-bins = <256>;
+                       iommus = <&smmu 2>;
+                       status = "disabled";
+               };
+
+               gmac2: ethernet@ff804000 {
+                       compatible = "altr,socfpga-stmmac", "snps,dwmac-3.74a", "snps,dwmac";
+                       reg = <0xff804000 0x2000>;
+                       interrupts = <0 92 4>;
+                       interrupt-names = "macirq";
+                       mac-address = [00 00 00 00 00 00];
+                       resets = <&rst EMAC2_RESET>, <&rst EMAC2_OCP_RESET>;
+                       reset-names = "stmmaceth", "stmmaceth-ocp";
+                       tx-fifo-depth = <16384>;
+                       rx-fifo-depth = <16384>;
+                       snps,multicast-filter-bins = <256>;
+                       iommus = <&smmu 3>;
+                       status = "disabled";
+               };
+
+               gpio0: gpio@ffc03200 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,dw-apb-gpio";
+                       reg = <0xffc03200 0x100>;
+                       resets = <&rst GPIO0_RESET>;
+                       status = "disabled";
+
+                       porta: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <24>;
+                               reg = <0>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               interrupts = <0 110 4>;
+                       };
+               };
+
+               gpio1: gpio@ffc03300 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,dw-apb-gpio";
+                       reg = <0xffc03300 0x100>;
+                       resets = <&rst GPIO1_RESET>;
+                       status = "disabled";
+
+                       portb: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <24>;
+                               reg = <0>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               interrupts = <0 111 4>;
+                       };
+               };
+
+               i2c0: i2c@ffc02800 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,designware-i2c";
+                       reg = <0xffc02800 0x100>;
+                       interrupts = <0 103 4>;
+                       resets = <&rst I2C0_RESET>;
+                       status = "disabled";
+               };
+
+               i2c1: i2c@ffc02900 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,designware-i2c";
+                       reg = <0xffc02900 0x100>;
+                       interrupts = <0 104 4>;
+                       resets = <&rst I2C1_RESET>;
+                       status = "disabled";
+               };
+
+               i2c2: i2c@ffc02a00 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,designware-i2c";
+                       reg = <0xffc02a00 0x100>;
+                       interrupts = <0 105 4>;
+                       resets = <&rst I2C2_RESET>;
+                       status = "disabled";
+               };
+
+               i2c3: i2c@ffc02b00 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,designware-i2c";
+                       reg = <0xffc02b00 0x100>;
+                       interrupts = <0 106 4>;
+                       resets = <&rst I2C3_RESET>;
+                       status = "disabled";
+               };
+
+               i2c4: i2c@ffc02c00 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,designware-i2c";
+                       reg = <0xffc02c00 0x100>;
+                       interrupts = <0 107 4>;
+                       resets = <&rst I2C4_RESET>;
+                       status = "disabled";
+               };
+
+               mmc: dwmmc0@ff808000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "altr,socfpga-dw-mshc";
+                       reg = <0xff808000 0x1000>;
+                       interrupts = <0 96 4>;
+                       fifo-depth = <0x400>;
+                       resets = <&rst SDMMC_RESET>;
+                       reset-names = "reset";
+                       iommus = <&smmu 5>;
+                       status = "disabled";
+               };
+
+               ocram: sram@ffe00000 {
+                       compatible = "mmio-sram";
+                       reg = <0xffe00000 0x40000>;
+               };
+
+               pdma: pdma@ffda0000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       reg = <0xffda0000 0x1000>;
+                       interrupts = <0 81 4>,
+                                    <0 82 4>,
+                                    <0 83 4>,
+                                    <0 84 4>,
+                                    <0 85 4>,
+                                    <0 86 4>,
+                                    <0 87 4>,
+                                    <0 88 4>,
+                                    <0 89 4>;
+                       #dma-cells = <1>;
+                       #dma-channels = <8>;
+                       #dma-requests = <32>;
+               };
+
+               rst: rstmgr@ffd11000 {
+                       #reset-cells = <1>;
+                       compatible = "altr,stratix10-rst-mgr";
+                       reg = <0xffd11000 0x100>;
+               };
+
+               smmu: iommu@fa000000 {
+                       compatible = "arm,mmu-500", "arm,smmu-v2";
+                       reg = <0xfa000000 0x40000>;
+                       #global-interrupts = <2>;
+                       #iommu-cells = <1>;
+                       interrupt-parent = <&intc>;
+                       interrupts = <0 128 4>, /* Global Secure Fault */
+                               <0 129 4>, /* Global Non-secure Fault */
+                               /* Non-secure Context Interrupts (32) */
+                               <0 138 4>, <0 139 4>, <0 140 4>, <0 141 4>,
+                               <0 142 4>, <0 143 4>, <0 144 4>, <0 145 4>,
+                               <0 146 4>, <0 147 4>, <0 148 4>, <0 149 4>,
+                               <0 150 4>, <0 151 4>, <0 152 4>, <0 153 4>,
+                               <0 154 4>, <0 155 4>, <0 156 4>, <0 157 4>,
+                               <0 158 4>, <0 159 4>, <0 160 4>, <0 161 4>,
+                               <0 162 4>, <0 163 4>, <0 164 4>, <0 165 4>,
+                               <0 166 4>, <0 167 4>, <0 168 4>, <0 169 4>;
+                       stream-match-mask = <0x7ff0>;
+                       status = "disabled";
+               };
+
+               spi0: spi@ffda4000 {
+                       compatible = "snps,dw-apb-ssi";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0xffda4000 0x1000>;
+                       interrupts = <0 99 4>;
+                       resets = <&rst SPIM0_RESET>;
+                       reg-io-width = <4>;
+                       num-cs = <4>;
+                       status = "disabled";
+               };
+
+               spi1: spi@ffda5000 {
+                       compatible = "snps,dw-apb-ssi";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0xffda5000 0x1000>;
+                       interrupts = <0 100 4>;
+                       resets = <&rst SPIM1_RESET>;
+                       reg-io-width = <4>;
+                       num-cs = <4>;
+                       status = "disabled";
+               };
+
+               sysmgr: sysmgr@ffd12000 {
+                       compatible = "altr,sys-mgr", "syscon";
+                       reg = <0xffd12000 0x500>;
+               };
+
+               /* Local timer */
+               timer {
+                       compatible = "arm,armv8-timer";
+                       interrupts = <1 13 0xf08>,
+                                    <1 14 0xf08>,
+                                    <1 11 0xf08>,
+                                    <1 10 0xf08>;
+               };
+
+               timer0: timer0@ffc03000 {
+                       compatible = "snps,dw-apb-timer";
+                       interrupts = <0 113 4>;
+                       reg = <0xffc03000 0x100>;
+               };
+
+               timer1: timer1@ffc03100 {
+                       compatible = "snps,dw-apb-timer";
+                       interrupts = <0 114 4>;
+                       reg = <0xffc03100 0x100>;
+               };
+
+               timer2: timer2@ffd00000 {
+                       compatible = "snps,dw-apb-timer";
+                       interrupts = <0 115 4>;
+                       reg = <0xffd00000 0x100>;
+               };
+
+               timer3: timer3@ffd00100 {
+                       compatible = "snps,dw-apb-timer";
+                       interrupts = <0 116 4>;
+                       reg = <0xffd00100 0x100>;
+               };
+
+               uart0: serial0@ffc02000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0xffc02000 0x100>;
+                       interrupts = <0 108 4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       resets = <&rst UART0_RESET>;
+                       status = "disabled";
+               };
+
+               uart1: serial1@ffc02100 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0xffc02100 0x100>;
+                       interrupts = <0 109 4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       resets = <&rst UART1_RESET>;
+                       status = "disabled";
+               };
+
+               usbphy0: usbphy@0 {
+                       #phy-cells = <0>;
+                       compatible = "usb-nop-xceiv";
+                       status = "okay";
+               };
+
+               usb0: usb@ffb00000 {
+                       compatible = "snps,dwc2";
+                       reg = <0xffb00000 0x40000>;
+                       interrupts = <0 93 4>;
+                       phys = <&usbphy0>;
+                       phy-names = "usb2-phy";
+                       resets = <&rst USB0_RESET>, <&rst USB0_OCP_RESET>;
+                       reset-names = "dwc2", "dwc2-ecc";
+                       iommus = <&smmu 6>;
+                       status = "disabled";
+               };
+
+               usb1: usb@ffb40000 {
+                       compatible = "snps,dwc2";
+                       reg = <0xffb40000 0x40000>;
+                       interrupts = <0 94 4>;
+                       phys = <&usbphy0>;
+                       phy-names = "usb2-phy";
+                       resets = <&rst USB1_RESET>, <&rst USB1_OCP_RESET>;
+                       reset-names = "dwc2", "dwc2-ecc";
+                       iommus = <&smmu 7>;
+                       status = "disabled";
+               };
+
+               watchdog0: watchdog@ffd00200 {
+                       compatible = "snps,dw-wdt";
+                       reg = <0xffd00200 0x100>;
+                       interrupts = <0 117 4>;
+                       resets = <&rst WATCHDOG0_RESET>;
+                       status = "disabled";
+               };
+
+               watchdog1: watchdog@ffd00300 {
+                       compatible = "snps,dw-wdt";
+                       reg = <0xffd00300 0x100>;
+                       interrupts = <0 118 4>;
+                       resets = <&rst WATCHDOG1_RESET>;
+                       status = "disabled";
+               };
+
+               watchdog2: watchdog@ffd00400 {
+                       compatible = "snps,dw-wdt";
+                       reg = <0xffd00400 0x100>;
+                       interrupts = <0 125 4>;
+                       resets = <&rst WATCHDOG2_RESET>;
+                       status = "disabled";
+               };
+
+               watchdog3: watchdog@ffd00500 {
+                       compatible = "snps,dw-wdt";
+                       reg = <0xffd00500 0x100>;
+                       interrupts = <0 126 4>;
+                       resets = <&rst WATCHDOG3_RESET>;
+                       status = "disabled";
+               };
+
+               sdr: sdr@f8011100 {
+                       compatible = "altr,sdr-ctl", "syscon";
+                       reg = <0xf8011100 0xc0>;
+               };
+
+               qspi: spi@ff8d2000 {
+                       compatible = "cdns,qspi-nor";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0xff8d2000 0x100>,
+                             <0xff900000 0x100000>;
+                       interrupts = <0 3 4>;
+                       cdns,fifo-depth = <128>;
+                       cdns,fifo-width = <4>;
+                       cdns,trigger-address = <0x00000000>;
+
+                       status = "disabled";
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts b/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts
new file mode 100644 (file)
index 0000000..7814a9e
--- /dev/null
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier:     GPL-2.0
+/*
+ * Copyright (C) 2019, Intel Corporation
+ */
+#include "socfpga_agilex.dtsi"
+
+/ {
+       model = "SoCFPGA Agilex SoCDK";
+
+       aliases {
+               serial0 = &uart0;
+               ethernet0 = &gmac0;
+               ethernet1 = &gmac1;
+               ethernet2 = &gmac2;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory {
+               device_type = "memory";
+               /* We expect the bootloader to fill in the reg */
+               reg = <0 0 0 0>;
+       };
+};
+
+&gpio1 {
+       status = "okay";
+};
+
+&gmac0 {
+       status = "okay";
+       phy-mode = "rgmii";
+       phy-handle = <&phy0>;
+
+       max-frame-size = <9000>;
+
+       mdio0 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "snps,dwmac-mdio";
+               phy0: ethernet-phy@0 {
+                       reg = <4>;
+
+                       txd0-skew-ps = <0>; /* -420ps */
+                       txd1-skew-ps = <0>; /* -420ps */
+                       txd2-skew-ps = <0>; /* -420ps */
+                       txd3-skew-ps = <0>; /* -420ps */
+                       rxd0-skew-ps = <420>; /* 0ps */
+                       rxd1-skew-ps = <420>; /* 0ps */
+                       rxd2-skew-ps = <420>; /* 0ps */
+                       rxd3-skew-ps = <420>; /* 0ps */
+                       txen-skew-ps = <0>; /* -420ps */
+                       txc-skew-ps = <900>; /* 0ps */
+                       rxdv-skew-ps = <420>; /* 0ps */
+                       rxc-skew-ps = <1680>; /* 780ps */
+               };
+       };
+};
+
+&mmc {
+       status = "okay";
+       cap-sd-highspeed;
+       broken-cd;
+       bus-width = <4>;
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&watchdog0 {
+       status = "okay";
+};
index 2468762..9143aa1 100644 (file)
                marvell,function = "gpio";
        };
 
+       cp0_wlan_disable_pins: wlan-disable-pins {
+               marvell,pins = "mpp51";
+               marvell,function = "gpio";
+       };
+
        cp0_sdhci_pins: sdhci-pins {
                marvell,pins = "mpp55", "mpp56", "mpp57", "mpp58", "mpp59",
                               "mpp60", "mpp61";
 
 &cp0_pcie0 {
        pinctrl-names = "default";
-       pinctrl-0 = <&cp0_pci0_reset_pins>;
+       pinctrl-0 = <&cp0_pci0_reset_pins &cp0_wlan_disable_pins>;
        reset-gpios = <&cp0_gpio2 0 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
                output-low;
        };
 
+       wlan_disable {
+               gpio-hog;
+               gpios = <19 GPIO_ACTIVE_LOW>;
+               output-low;
+       };
+
        lte_disable {
                gpio-hog;
                gpios = <21 GPIO_ACTIVE_LOW>;
index 976d92a..43307ba 100644 (file)
                        #size-cells = <2>;
                        #interrupt-cells = <1>;
                        ranges;
-                       num-lanes = <1>;
                        interrupt-map-mask = <0 0 0 7>;
                        interrupt-map = <0 0 0 1 &pcie_intc0 0>,
                                        <0 0 0 2 &pcie_intc0 1>,
                        #size-cells = <2>;
                        #interrupt-cells = <1>;
                        ranges;
-                       num-lanes = <1>;
                        interrupt-map-mask = <0 0 0 7>;
                        interrupt-map = <0 0 0 1 &pcie_intc1 0>,
                                        <0 0 0 2 &pcie_intc1 1>,
index c3c3601..15f1842 100644 (file)
 
                cpu2: cpu@100 {
                        device_type = "cpu";
-                       compatible = "arm,cortex-a57";
+                       compatible = "arm,cortex-a72";
                        reg = <0x100>;
                        enable-method = "psci";
                        cpu-idle-states = <&CPU_SLEEP_0>;
                        #cooling-cells = <2>;
-                       clocks = <&infracfg CLK_INFRA_CA57SEL>,
+                       clocks = <&infracfg CLK_INFRA_CA72SEL>,
                                 <&apmixedsys CLK_APMIXED_MAINPLL>;
                        clock-names = "cpu", "intermediate";
                        operating-points-v2 = <&cluster1_opp>;
 
                cpu3: cpu@101 {
                        device_type = "cpu";
-                       compatible = "arm,cortex-a57";
+                       compatible = "arm,cortex-a72";
                        reg = <0x101>;
                        enable-method = "psci";
                        cpu-idle-states = <&CPU_SLEEP_0>;
                        #cooling-cells = <2>;
-                       clocks = <&infracfg CLK_INFRA_CA57SEL>,
+                       clocks = <&infracfg CLK_INFRA_CA72SEL>,
                                 <&apmixedsys CLK_APMIXED_MAINPLL>;
                        clock-names = "cpu", "intermediate";
                        operating-points-v2 = <&cluster1_opp>;
                };
        };
 
+       pmu_a53 {
+               compatible = "arm,cortex-a53-pmu";
+               interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_SPI 9 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-affinity = <&cpu0>, <&cpu1>;
+       };
+
+       pmu_a72 {
+               compatible = "arm,cortex-a72-pmu";
+               interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_SPI 13 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-affinity = <&cpu2>, <&cpu3>;
+       };
+
        psci {
                compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
                method = "smc";
                                      "vencpll",
                                      "venc_lt_sel",
                                      "vdec_bus_clk_src";
+                       assigned-clocks = <&topckgen CLK_TOP_VENC_LT_SEL>,
+                                         <&topckgen CLK_TOP_CCI400_SEL>,
+                                         <&topckgen CLK_TOP_VDEC_SEL>,
+                                         <&apmixedsys CLK_APMIXED_VCODECPLL>,
+                                         <&apmixedsys CLK_APMIXED_VENCPLL>;
+                       assigned-clock-parents = <&topckgen CLK_TOP_VCODECPLL_370P5>,
+                                                <&topckgen CLK_TOP_UNIVPLL_D2>,
+                                                <&topckgen CLK_TOP_VCODECPLL>;
+                       assigned-clock-rates = <0>, <0>, <0>, <1482000000>, <800000000>;
                };
 
                larb1: larb@16010000 {
                                      "venc_sel",
                                      "venc_lt_sel_src",
                                      "venc_lt_sel";
+                       assigned-clocks = <&topckgen CLK_TOP_VENC_SEL>,
+                                         <&topckgen CLK_TOP_VENC_LT_SEL>;
+                       assigned-clock-parents = <&topckgen CLK_TOP_VENCPLL_D2>,
+                                                <&topckgen CLK_TOP_UNIVPLL1_D2>;
                };
 
                vencltsys: clock-controller@19000000 {
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-pinfunc.h b/arch/arm64/boot/dts/mediatek/mt8183-pinfunc.h
new file mode 100644 (file)
index 0000000..6221cd7
--- /dev/null
@@ -0,0 +1,1120 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Zhiyong Tao <zhiyong.tao@mediatek.com>
+ *
+ */
+
+#ifndef __MT8183_PINFUNC_H
+#define __MT8183_PINFUNC_H
+
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+#define PINMUX_GPIO0__FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
+#define PINMUX_GPIO0__FUNC_MRG_SYNC (MTK_PIN_NO(0) | 1)
+#define PINMUX_GPIO0__FUNC_PCM0_SYNC (MTK_PIN_NO(0) | 2)
+#define PINMUX_GPIO0__FUNC_TP_GPIO0_AO (MTK_PIN_NO(0) | 3)
+#define PINMUX_GPIO0__FUNC_SRCLKENAI0 (MTK_PIN_NO(0) | 4)
+#define PINMUX_GPIO0__FUNC_SCP_SPI2_CS (MTK_PIN_NO(0) | 5)
+#define PINMUX_GPIO0__FUNC_I2S3_MCK (MTK_PIN_NO(0) | 6)
+#define PINMUX_GPIO0__FUNC_SPI2_CSB (MTK_PIN_NO(0) | 7)
+
+#define PINMUX_GPIO1__FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
+#define PINMUX_GPIO1__FUNC_MRG_CLK (MTK_PIN_NO(1) | 1)
+#define PINMUX_GPIO1__FUNC_PCM0_CLK (MTK_PIN_NO(1) | 2)
+#define PINMUX_GPIO1__FUNC_TP_GPIO1_AO (MTK_PIN_NO(1) | 3)
+#define PINMUX_GPIO1__FUNC_CLKM3 (MTK_PIN_NO(1) | 4)
+#define PINMUX_GPIO1__FUNC_SCP_SPI2_MO (MTK_PIN_NO(1) | 5)
+#define PINMUX_GPIO1__FUNC_I2S3_BCK (MTK_PIN_NO(1) | 6)
+#define PINMUX_GPIO1__FUNC_SPI2_MO (MTK_PIN_NO(1) | 7)
+
+#define PINMUX_GPIO2__FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
+#define PINMUX_GPIO2__FUNC_MRG_DO (MTK_PIN_NO(2) | 1)
+#define PINMUX_GPIO2__FUNC_PCM0_DO (MTK_PIN_NO(2) | 2)
+#define PINMUX_GPIO2__FUNC_TP_GPIO2_AO (MTK_PIN_NO(2) | 3)
+#define PINMUX_GPIO2__FUNC_SCL6 (MTK_PIN_NO(2) | 4)
+#define PINMUX_GPIO2__FUNC_SCP_SPI2_CK (MTK_PIN_NO(2) | 5)
+#define PINMUX_GPIO2__FUNC_I2S3_LRCK (MTK_PIN_NO(2) | 6)
+#define PINMUX_GPIO2__FUNC_SPI2_CLK (MTK_PIN_NO(2) | 7)
+
+#define PINMUX_GPIO3__FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
+#define PINMUX_GPIO3__FUNC_MRG_DI (MTK_PIN_NO(3) | 1)
+#define PINMUX_GPIO3__FUNC_PCM0_DI (MTK_PIN_NO(3) | 2)
+#define PINMUX_GPIO3__FUNC_TP_GPIO3_AO (MTK_PIN_NO(3) | 3)
+#define PINMUX_GPIO3__FUNC_SDA6 (MTK_PIN_NO(3) | 4)
+#define PINMUX_GPIO3__FUNC_TDM_MCK (MTK_PIN_NO(3) | 5)
+#define PINMUX_GPIO3__FUNC_I2S3_DO (MTK_PIN_NO(3) | 6)
+#define PINMUX_GPIO3__FUNC_SCP_VREQ_VAO (MTK_PIN_NO(3) | 7)
+
+#define PINMUX_GPIO4__FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
+#define PINMUX_GPIO4__FUNC_PWM_B (MTK_PIN_NO(4) | 1)
+#define PINMUX_GPIO4__FUNC_I2S0_MCK (MTK_PIN_NO(4) | 2)
+#define PINMUX_GPIO4__FUNC_SSPM_UTXD_AO (MTK_PIN_NO(4) | 3)
+#define PINMUX_GPIO4__FUNC_MD_URXD1 (MTK_PIN_NO(4) | 4)
+#define PINMUX_GPIO4__FUNC_TDM_BCK (MTK_PIN_NO(4) | 5)
+#define PINMUX_GPIO4__FUNC_TP_GPIO4_AO (MTK_PIN_NO(4) | 6)
+#define PINMUX_GPIO4__FUNC_DAP_MD32_SWD (MTK_PIN_NO(4) | 7)
+
+#define PINMUX_GPIO5__FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
+#define PINMUX_GPIO5__FUNC_PWM_C (MTK_PIN_NO(5) | 1)
+#define PINMUX_GPIO5__FUNC_I2S0_BCK (MTK_PIN_NO(5) | 2)
+#define PINMUX_GPIO5__FUNC_SSPM_URXD_AO (MTK_PIN_NO(5) | 3)
+#define PINMUX_GPIO5__FUNC_MD_UTXD1 (MTK_PIN_NO(5) | 4)
+#define PINMUX_GPIO5__FUNC_TDM_LRCK (MTK_PIN_NO(5) | 5)
+#define PINMUX_GPIO5__FUNC_TP_GPIO5_AO (MTK_PIN_NO(5) | 6)
+#define PINMUX_GPIO5__FUNC_DAP_MD32_SWCK (MTK_PIN_NO(5) | 7)
+
+#define PINMUX_GPIO6__FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
+#define PINMUX_GPIO6__FUNC_PWM_A (MTK_PIN_NO(6) | 1)
+#define PINMUX_GPIO6__FUNC_I2S0_LRCK (MTK_PIN_NO(6) | 2)
+#define PINMUX_GPIO6__FUNC_IDDIG (MTK_PIN_NO(6) | 3)
+#define PINMUX_GPIO6__FUNC_MD_URXD0 (MTK_PIN_NO(6) | 4)
+#define PINMUX_GPIO6__FUNC_TDM_DATA0 (MTK_PIN_NO(6) | 5)
+#define PINMUX_GPIO6__FUNC_TP_GPIO6_AO (MTK_PIN_NO(6) | 6)
+#define PINMUX_GPIO6__FUNC_CMFLASH (MTK_PIN_NO(6) | 7)
+
+#define PINMUX_GPIO7__FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
+#define PINMUX_GPIO7__FUNC_SPI1_B_MI (MTK_PIN_NO(7) | 1)
+#define PINMUX_GPIO7__FUNC_I2S0_DI (MTK_PIN_NO(7) | 2)
+#define PINMUX_GPIO7__FUNC_USB_DRVVBUS (MTK_PIN_NO(7) | 3)
+#define PINMUX_GPIO7__FUNC_MD_UTXD0 (MTK_PIN_NO(7) | 4)
+#define PINMUX_GPIO7__FUNC_TDM_DATA1 (MTK_PIN_NO(7) | 5)
+#define PINMUX_GPIO7__FUNC_TP_GPIO7_AO (MTK_PIN_NO(7) | 6)
+#define PINMUX_GPIO7__FUNC_DVFSRC_EXT_REQ (MTK_PIN_NO(7) | 7)
+
+#define PINMUX_GPIO8__FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
+#define PINMUX_GPIO8__FUNC_SPI1_B_CSB (MTK_PIN_NO(8) | 1)
+#define PINMUX_GPIO8__FUNC_ANT_SEL3 (MTK_PIN_NO(8) | 2)
+#define PINMUX_GPIO8__FUNC_SCL7 (MTK_PIN_NO(8) | 3)
+#define PINMUX_GPIO8__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(8) | 4)
+#define PINMUX_GPIO8__FUNC_TDM_DATA2 (MTK_PIN_NO(8) | 5)
+#define PINMUX_GPIO8__FUNC_MD_INT0 (MTK_PIN_NO(8) | 6)
+#define PINMUX_GPIO8__FUNC_JTRSTN_SEL1 (MTK_PIN_NO(8) | 7)
+
+#define PINMUX_GPIO9__FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
+#define PINMUX_GPIO9__FUNC_SPI1_B_MO (MTK_PIN_NO(9) | 1)
+#define PINMUX_GPIO9__FUNC_ANT_SEL4 (MTK_PIN_NO(9) | 2)
+#define PINMUX_GPIO9__FUNC_CMMCLK2 (MTK_PIN_NO(9) | 3)
+#define PINMUX_GPIO9__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(9) | 4)
+#define PINMUX_GPIO9__FUNC_SSPM_JTAG_TRSTN (MTK_PIN_NO(9) | 5)
+#define PINMUX_GPIO9__FUNC_IO_JTAG_TRSTN (MTK_PIN_NO(9) | 6)
+#define PINMUX_GPIO9__FUNC_DBG_MON_B10 (MTK_PIN_NO(9) | 7)
+
+#define PINMUX_GPIO10__FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
+#define PINMUX_GPIO10__FUNC_SPI1_B_CLK (MTK_PIN_NO(10) | 1)
+#define PINMUX_GPIO10__FUNC_ANT_SEL5 (MTK_PIN_NO(10) | 2)
+#define PINMUX_GPIO10__FUNC_CMMCLK3 (MTK_PIN_NO(10) | 3)
+#define PINMUX_GPIO10__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(10) | 4)
+#define PINMUX_GPIO10__FUNC_TDM_DATA3 (MTK_PIN_NO(10) | 5)
+#define PINMUX_GPIO10__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(10) | 6)
+#define PINMUX_GPIO10__FUNC_DBG_MON_B11 (MTK_PIN_NO(10) | 7)
+
+#define PINMUX_GPIO11__FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
+#define PINMUX_GPIO11__FUNC_TP_URXD1_AO (MTK_PIN_NO(11) | 1)
+#define PINMUX_GPIO11__FUNC_IDDIG (MTK_PIN_NO(11) | 2)
+#define PINMUX_GPIO11__FUNC_SCL6 (MTK_PIN_NO(11) | 3)
+#define PINMUX_GPIO11__FUNC_UCTS1 (MTK_PIN_NO(11) | 4)
+#define PINMUX_GPIO11__FUNC_UCTS0 (MTK_PIN_NO(11) | 5)
+#define PINMUX_GPIO11__FUNC_SRCLKENAI1 (MTK_PIN_NO(11) | 6)
+#define PINMUX_GPIO11__FUNC_I2S5_MCK (MTK_PIN_NO(11) | 7)
+
+#define PINMUX_GPIO12__FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
+#define PINMUX_GPIO12__FUNC_TP_UTXD1_AO (MTK_PIN_NO(12) | 1)
+#define PINMUX_GPIO12__FUNC_USB_DRVVBUS (MTK_PIN_NO(12) | 2)
+#define PINMUX_GPIO12__FUNC_SDA6 (MTK_PIN_NO(12) | 3)
+#define PINMUX_GPIO12__FUNC_URTS1 (MTK_PIN_NO(12) | 4)
+#define PINMUX_GPIO12__FUNC_URTS0 (MTK_PIN_NO(12) | 5)
+#define PINMUX_GPIO12__FUNC_I2S2_DI2 (MTK_PIN_NO(12) | 6)
+#define PINMUX_GPIO12__FUNC_I2S5_BCK (MTK_PIN_NO(12) | 7)
+
+#define PINMUX_GPIO13__FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
+#define PINMUX_GPIO13__FUNC_DBPI_D0 (MTK_PIN_NO(13) | 1)
+#define PINMUX_GPIO13__FUNC_SPI5_MI (MTK_PIN_NO(13) | 2)
+#define PINMUX_GPIO13__FUNC_PCM0_SYNC (MTK_PIN_NO(13) | 3)
+#define PINMUX_GPIO13__FUNC_MD_URXD0 (MTK_PIN_NO(13) | 4)
+#define PINMUX_GPIO13__FUNC_ANT_SEL3 (MTK_PIN_NO(13) | 5)
+#define PINMUX_GPIO13__FUNC_I2S0_MCK (MTK_PIN_NO(13) | 6)
+#define PINMUX_GPIO13__FUNC_DBG_MON_B15 (MTK_PIN_NO(13) | 7)
+
+#define PINMUX_GPIO14__FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
+#define PINMUX_GPIO14__FUNC_DBPI_D1 (MTK_PIN_NO(14) | 1)
+#define PINMUX_GPIO14__FUNC_SPI5_CSB (MTK_PIN_NO(14) | 2)
+#define PINMUX_GPIO14__FUNC_PCM0_CLK (MTK_PIN_NO(14) | 3)
+#define PINMUX_GPIO14__FUNC_MD_UTXD0 (MTK_PIN_NO(14) | 4)
+#define PINMUX_GPIO14__FUNC_ANT_SEL4 (MTK_PIN_NO(14) | 5)
+#define PINMUX_GPIO14__FUNC_I2S0_BCK (MTK_PIN_NO(14) | 6)
+#define PINMUX_GPIO14__FUNC_DBG_MON_B16 (MTK_PIN_NO(14) | 7)
+
+#define PINMUX_GPIO15__FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
+#define PINMUX_GPIO15__FUNC_DBPI_D2 (MTK_PIN_NO(15) | 1)
+#define PINMUX_GPIO15__FUNC_SPI5_MO (MTK_PIN_NO(15) | 2)
+#define PINMUX_GPIO15__FUNC_PCM0_DO (MTK_PIN_NO(15) | 3)
+#define PINMUX_GPIO15__FUNC_MD_URXD1 (MTK_PIN_NO(15) | 4)
+#define PINMUX_GPIO15__FUNC_ANT_SEL5 (MTK_PIN_NO(15) | 5)
+#define PINMUX_GPIO15__FUNC_I2S0_LRCK (MTK_PIN_NO(15) | 6)
+#define PINMUX_GPIO15__FUNC_DBG_MON_B17 (MTK_PIN_NO(15) | 7)
+
+#define PINMUX_GPIO16__FUNC_GPIO16 (MTK_PIN_NO(16) | 0)
+#define PINMUX_GPIO16__FUNC_DBPI_D3 (MTK_PIN_NO(16) | 1)
+#define PINMUX_GPIO16__FUNC_SPI5_CLK (MTK_PIN_NO(16) | 2)
+#define PINMUX_GPIO16__FUNC_PCM0_DI (MTK_PIN_NO(16) | 3)
+#define PINMUX_GPIO16__FUNC_MD_UTXD1 (MTK_PIN_NO(16) | 4)
+#define PINMUX_GPIO16__FUNC_ANT_SEL6 (MTK_PIN_NO(16) | 5)
+#define PINMUX_GPIO16__FUNC_I2S0_DI (MTK_PIN_NO(16) | 6)
+#define PINMUX_GPIO16__FUNC_DBG_MON_B23 (MTK_PIN_NO(16) | 7)
+
+#define PINMUX_GPIO17__FUNC_GPIO17 (MTK_PIN_NO(17) | 0)
+#define PINMUX_GPIO17__FUNC_DBPI_D4 (MTK_PIN_NO(17) | 1)
+#define PINMUX_GPIO17__FUNC_SPI4_MI (MTK_PIN_NO(17) | 2)
+#define PINMUX_GPIO17__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(17) | 3)
+#define PINMUX_GPIO17__FUNC_MD_INT0 (MTK_PIN_NO(17) | 4)
+#define PINMUX_GPIO17__FUNC_ANT_SEL7 (MTK_PIN_NO(17) | 5)
+#define PINMUX_GPIO17__FUNC_I2S3_MCK (MTK_PIN_NO(17) | 6)
+#define PINMUX_GPIO17__FUNC_DBG_MON_A1 (MTK_PIN_NO(17) | 7)
+
+#define PINMUX_GPIO18__FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
+#define PINMUX_GPIO18__FUNC_DBPI_D5 (MTK_PIN_NO(18) | 1)
+#define PINMUX_GPIO18__FUNC_SPI4_CSB (MTK_PIN_NO(18) | 2)
+#define PINMUX_GPIO18__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(18) | 3)
+#define PINMUX_GPIO18__FUNC_MD_INT0 (MTK_PIN_NO(18) | 4)
+#define PINMUX_GPIO18__FUNC_SCP_VREQ_VAO (MTK_PIN_NO(18) | 5)
+#define PINMUX_GPIO18__FUNC_I2S3_BCK (MTK_PIN_NO(18) | 6)
+#define PINMUX_GPIO18__FUNC_DBG_MON_A2 (MTK_PIN_NO(18) | 7)
+
+#define PINMUX_GPIO19__FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
+#define PINMUX_GPIO19__FUNC_DBPI_D6 (MTK_PIN_NO(19) | 1)
+#define PINMUX_GPIO19__FUNC_SPI4_MO (MTK_PIN_NO(19) | 2)
+#define PINMUX_GPIO19__FUNC_CONN_MCU_TDO (MTK_PIN_NO(19) | 3)
+#define PINMUX_GPIO19__FUNC_MD_INT2_C2K_UIM1_HOT_PLUG (MTK_PIN_NO(19) | 4)
+#define PINMUX_GPIO19__FUNC_URXD1 (MTK_PIN_NO(19) | 5)
+#define PINMUX_GPIO19__FUNC_I2S3_LRCK (MTK_PIN_NO(19) | 6)
+#define PINMUX_GPIO19__FUNC_DBG_MON_A3 (MTK_PIN_NO(19) | 7)
+
+#define PINMUX_GPIO20__FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
+#define PINMUX_GPIO20__FUNC_DBPI_D7 (MTK_PIN_NO(20) | 1)
+#define PINMUX_GPIO20__FUNC_SPI4_CLK (MTK_PIN_NO(20) | 2)
+#define PINMUX_GPIO20__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(20) | 3)
+#define PINMUX_GPIO20__FUNC_MD_INT1_C2K_UIM0_HOT_PLUG (MTK_PIN_NO(20) | 4)
+#define PINMUX_GPIO20__FUNC_UTXD1 (MTK_PIN_NO(20) | 5)
+#define PINMUX_GPIO20__FUNC_I2S3_DO (MTK_PIN_NO(20) | 6)
+#define PINMUX_GPIO20__FUNC_DBG_MON_A19 (MTK_PIN_NO(20) | 7)
+
+#define PINMUX_GPIO21__FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
+#define PINMUX_GPIO21__FUNC_DBPI_D8 (MTK_PIN_NO(21) | 1)
+#define PINMUX_GPIO21__FUNC_SPI3_MI (MTK_PIN_NO(21) | 2)
+#define PINMUX_GPIO21__FUNC_CONN_MCU_TMS (MTK_PIN_NO(21) | 3)
+#define PINMUX_GPIO21__FUNC_DAP_MD32_SWD (MTK_PIN_NO(21) | 4)
+#define PINMUX_GPIO21__FUNC_CONN_MCU_AICE_TMSC (MTK_PIN_NO(21) | 5)
+#define PINMUX_GPIO21__FUNC_I2S2_MCK (MTK_PIN_NO(21) | 6)
+#define PINMUX_GPIO21__FUNC_DBG_MON_B5 (MTK_PIN_NO(21) | 7)
+
+#define PINMUX_GPIO22__FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
+#define PINMUX_GPIO22__FUNC_DBPI_D9 (MTK_PIN_NO(22) | 1)
+#define PINMUX_GPIO22__FUNC_SPI3_CSB (MTK_PIN_NO(22) | 2)
+#define PINMUX_GPIO22__FUNC_CONN_MCU_TCK (MTK_PIN_NO(22) | 3)
+#define PINMUX_GPIO22__FUNC_DAP_MD32_SWCK (MTK_PIN_NO(22) | 4)
+#define PINMUX_GPIO22__FUNC_CONN_MCU_AICE_TCKC (MTK_PIN_NO(22) | 5)
+#define PINMUX_GPIO22__FUNC_I2S2_BCK (MTK_PIN_NO(22) | 6)
+#define PINMUX_GPIO22__FUNC_DBG_MON_B6 (MTK_PIN_NO(22) | 7)
+
+#define PINMUX_GPIO23__FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
+#define PINMUX_GPIO23__FUNC_DBPI_D10 (MTK_PIN_NO(23) | 1)
+#define PINMUX_GPIO23__FUNC_SPI3_MO (MTK_PIN_NO(23) | 2)
+#define PINMUX_GPIO23__FUNC_CONN_MCU_TDI (MTK_PIN_NO(23) | 3)
+#define PINMUX_GPIO23__FUNC_UCTS1 (MTK_PIN_NO(23) | 4)
+#define PINMUX_GPIO23__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(23) | 5)
+#define PINMUX_GPIO23__FUNC_I2S2_LRCK (MTK_PIN_NO(23) | 6)
+#define PINMUX_GPIO23__FUNC_DBG_MON_B7 (MTK_PIN_NO(23) | 7)
+
+#define PINMUX_GPIO24__FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
+#define PINMUX_GPIO24__FUNC_DBPI_D11 (MTK_PIN_NO(24) | 1)
+#define PINMUX_GPIO24__FUNC_SPI3_CLK (MTK_PIN_NO(24) | 2)
+#define PINMUX_GPIO24__FUNC_SRCLKENAI0 (MTK_PIN_NO(24) | 3)
+#define PINMUX_GPIO24__FUNC_URTS1 (MTK_PIN_NO(24) | 4)
+#define PINMUX_GPIO24__FUNC_IO_JTAG_TCK (MTK_PIN_NO(24) | 5)
+#define PINMUX_GPIO24__FUNC_I2S2_DI (MTK_PIN_NO(24) | 6)
+#define PINMUX_GPIO24__FUNC_DBG_MON_B31 (MTK_PIN_NO(24) | 7)
+
+#define PINMUX_GPIO25__FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
+#define PINMUX_GPIO25__FUNC_DBPI_HSYNC (MTK_PIN_NO(25) | 1)
+#define PINMUX_GPIO25__FUNC_ANT_SEL0 (MTK_PIN_NO(25) | 2)
+#define PINMUX_GPIO25__FUNC_SCL6 (MTK_PIN_NO(25) | 3)
+#define PINMUX_GPIO25__FUNC_KPCOL2 (MTK_PIN_NO(25) | 4)
+#define PINMUX_GPIO25__FUNC_IO_JTAG_TMS (MTK_PIN_NO(25) | 5)
+#define PINMUX_GPIO25__FUNC_I2S1_MCK (MTK_PIN_NO(25) | 6)
+#define PINMUX_GPIO25__FUNC_DBG_MON_B0 (MTK_PIN_NO(25) | 7)
+
+#define PINMUX_GPIO26__FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
+#define PINMUX_GPIO26__FUNC_DBPI_VSYNC (MTK_PIN_NO(26) | 1)
+#define PINMUX_GPIO26__FUNC_ANT_SEL1 (MTK_PIN_NO(26) | 2)
+#define PINMUX_GPIO26__FUNC_SDA6 (MTK_PIN_NO(26) | 3)
+#define PINMUX_GPIO26__FUNC_KPROW2 (MTK_PIN_NO(26) | 4)
+#define PINMUX_GPIO26__FUNC_IO_JTAG_TDI (MTK_PIN_NO(26) | 5)
+#define PINMUX_GPIO26__FUNC_I2S1_BCK (MTK_PIN_NO(26) | 6)
+#define PINMUX_GPIO26__FUNC_DBG_MON_B1 (MTK_PIN_NO(26) | 7)
+
+#define PINMUX_GPIO27__FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
+#define PINMUX_GPIO27__FUNC_DBPI_DE (MTK_PIN_NO(27) | 1)
+#define PINMUX_GPIO27__FUNC_ANT_SEL2 (MTK_PIN_NO(27) | 2)
+#define PINMUX_GPIO27__FUNC_SCL7 (MTK_PIN_NO(27) | 3)
+#define PINMUX_GPIO27__FUNC_DMIC_CLK (MTK_PIN_NO(27) | 4)
+#define PINMUX_GPIO27__FUNC_IO_JTAG_TDO (MTK_PIN_NO(27) | 5)
+#define PINMUX_GPIO27__FUNC_I2S1_LRCK (MTK_PIN_NO(27) | 6)
+#define PINMUX_GPIO27__FUNC_DBG_MON_B9 (MTK_PIN_NO(27) | 7)
+
+#define PINMUX_GPIO28__FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
+#define PINMUX_GPIO28__FUNC_DBPI_CK (MTK_PIN_NO(28) | 1)
+#define PINMUX_GPIO28__FUNC_DVFSRC_EXT_REQ (MTK_PIN_NO(28) | 2)
+#define PINMUX_GPIO28__FUNC_SDA7 (MTK_PIN_NO(28) | 3)
+#define PINMUX_GPIO28__FUNC_DMIC_DAT (MTK_PIN_NO(28) | 4)
+#define PINMUX_GPIO28__FUNC_IO_JTAG_TRSTN (MTK_PIN_NO(28) | 5)
+#define PINMUX_GPIO28__FUNC_I2S1_DO (MTK_PIN_NO(28) | 6)
+#define PINMUX_GPIO28__FUNC_DBG_MON_B32 (MTK_PIN_NO(28) | 7)
+
+#define PINMUX_GPIO29__FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
+#define PINMUX_GPIO29__FUNC_MSDC1_CLK (MTK_PIN_NO(29) | 1)
+#define PINMUX_GPIO29__FUNC_IO_JTAG_TCK (MTK_PIN_NO(29) | 2)
+#define PINMUX_GPIO29__FUNC_UDI_TCK (MTK_PIN_NO(29) | 3)
+#define PINMUX_GPIO29__FUNC_CONN_DSP_JCK (MTK_PIN_NO(29) | 4)
+#define PINMUX_GPIO29__FUNC_SSPM_JTAG_TCK (MTK_PIN_NO(29) | 5)
+#define PINMUX_GPIO29__FUNC_PCM1_CLK (MTK_PIN_NO(29) | 6)
+#define PINMUX_GPIO29__FUNC_DBG_MON_A6 (MTK_PIN_NO(29) | 7)
+
+#define PINMUX_GPIO30__FUNC_GPIO30 (MTK_PIN_NO(30) | 0)
+#define PINMUX_GPIO30__FUNC_MSDC1_DAT3 (MTK_PIN_NO(30) | 1)
+#define PINMUX_GPIO30__FUNC_DAP_MD32_SWD (MTK_PIN_NO(30) | 2)
+#define PINMUX_GPIO30__FUNC_CONN_MCU_AICE_TMSC (MTK_PIN_NO(30) | 3)
+#define PINMUX_GPIO30__FUNC_CONN_DSP_JINTP (MTK_PIN_NO(30) | 4)
+#define PINMUX_GPIO30__FUNC_SSPM_JTAG_TRSTN (MTK_PIN_NO(30) | 5)
+#define PINMUX_GPIO30__FUNC_PCM1_DI (MTK_PIN_NO(30) | 6)
+#define PINMUX_GPIO30__FUNC_DBG_MON_A7 (MTK_PIN_NO(30) | 7)
+
+#define PINMUX_GPIO31__FUNC_GPIO31 (MTK_PIN_NO(31) | 0)
+#define PINMUX_GPIO31__FUNC_MSDC1_CMD (MTK_PIN_NO(31) | 1)
+#define PINMUX_GPIO31__FUNC_IO_JTAG_TMS (MTK_PIN_NO(31) | 2)
+#define PINMUX_GPIO31__FUNC_UDI_TMS (MTK_PIN_NO(31) | 3)
+#define PINMUX_GPIO31__FUNC_CONN_DSP_JMS (MTK_PIN_NO(31) | 4)
+#define PINMUX_GPIO31__FUNC_SSPM_JTAG_TMS (MTK_PIN_NO(31) | 5)
+#define PINMUX_GPIO31__FUNC_PCM1_SYNC (MTK_PIN_NO(31) | 6)
+#define PINMUX_GPIO31__FUNC_DBG_MON_A8 (MTK_PIN_NO(31) | 7)
+
+#define PINMUX_GPIO32__FUNC_GPIO32 (MTK_PIN_NO(32) | 0)
+#define PINMUX_GPIO32__FUNC_MSDC1_DAT0 (MTK_PIN_NO(32) | 1)
+#define PINMUX_GPIO32__FUNC_IO_JTAG_TDI (MTK_PIN_NO(32) | 2)
+#define PINMUX_GPIO32__FUNC_UDI_TDI (MTK_PIN_NO(32) | 3)
+#define PINMUX_GPIO32__FUNC_CONN_DSP_JDI (MTK_PIN_NO(32) | 4)
+#define PINMUX_GPIO32__FUNC_SSPM_JTAG_TDI (MTK_PIN_NO(32) | 5)
+#define PINMUX_GPIO32__FUNC_PCM1_DO0 (MTK_PIN_NO(32) | 6)
+#define PINMUX_GPIO32__FUNC_DBG_MON_A9 (MTK_PIN_NO(32) | 7)
+
+#define PINMUX_GPIO33__FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
+#define PINMUX_GPIO33__FUNC_MSDC1_DAT2 (MTK_PIN_NO(33) | 1)
+#define PINMUX_GPIO33__FUNC_IO_JTAG_TRSTN (MTK_PIN_NO(33) | 2)
+#define PINMUX_GPIO33__FUNC_UDI_NTRST (MTK_PIN_NO(33) | 3)
+#define PINMUX_GPIO33__FUNC_DAP_MD32_SWCK (MTK_PIN_NO(33) | 4)
+#define PINMUX_GPIO33__FUNC_CONN_MCU_AICE_TCKC (MTK_PIN_NO(33) | 5)
+#define PINMUX_GPIO33__FUNC_PCM1_DO2 (MTK_PIN_NO(33) | 6)
+#define PINMUX_GPIO33__FUNC_DBG_MON_A10 (MTK_PIN_NO(33) | 7)
+
+#define PINMUX_GPIO34__FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
+#define PINMUX_GPIO34__FUNC_MSDC1_DAT1 (MTK_PIN_NO(34) | 1)
+#define PINMUX_GPIO34__FUNC_IO_JTAG_TDO (MTK_PIN_NO(34) | 2)
+#define PINMUX_GPIO34__FUNC_UDI_TDO (MTK_PIN_NO(34) | 3)
+#define PINMUX_GPIO34__FUNC_CONN_DSP_JDO (MTK_PIN_NO(34) | 4)
+#define PINMUX_GPIO34__FUNC_SSPM_JTAG_TDO (MTK_PIN_NO(34) | 5)
+#define PINMUX_GPIO34__FUNC_PCM1_DO1 (MTK_PIN_NO(34) | 6)
+#define PINMUX_GPIO34__FUNC_DBG_MON_A11 (MTK_PIN_NO(34) | 7)
+
+#define PINMUX_GPIO35__FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
+#define PINMUX_GPIO35__FUNC_MD1_SIM2_SIO (MTK_PIN_NO(35) | 1)
+#define PINMUX_GPIO35__FUNC_CCU_JTAG_TDO (MTK_PIN_NO(35) | 2)
+#define PINMUX_GPIO35__FUNC_MD1_SIM1_SIO (MTK_PIN_NO(35) | 3)
+#define PINMUX_GPIO35__FUNC_SCP_JTAG_TDO (MTK_PIN_NO(35) | 5)
+#define PINMUX_GPIO35__FUNC_CONN_DSP_JMS (MTK_PIN_NO(35) | 6)
+#define PINMUX_GPIO35__FUNC_DBG_MON_A28 (MTK_PIN_NO(35) | 7)
+
+#define PINMUX_GPIO36__FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
+#define PINMUX_GPIO36__FUNC_MD1_SIM2_SRST (MTK_PIN_NO(36) | 1)
+#define PINMUX_GPIO36__FUNC_CCU_JTAG_TMS (MTK_PIN_NO(36) | 2)
+#define PINMUX_GPIO36__FUNC_MD1_SIM1_SRST (MTK_PIN_NO(36) | 3)
+#define PINMUX_GPIO36__FUNC_CONN_MCU_AICE_TMSC (MTK_PIN_NO(36) | 4)
+#define PINMUX_GPIO36__FUNC_SCP_JTAG_TMS (MTK_PIN_NO(36) | 5)
+#define PINMUX_GPIO36__FUNC_CONN_DSP_JINTP (MTK_PIN_NO(36) | 6)
+#define PINMUX_GPIO36__FUNC_DBG_MON_A29 (MTK_PIN_NO(36) | 7)
+
+#define PINMUX_GPIO37__FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
+#define PINMUX_GPIO37__FUNC_MD1_SIM2_SCLK (MTK_PIN_NO(37) | 1)
+#define PINMUX_GPIO37__FUNC_CCU_JTAG_TDI (MTK_PIN_NO(37) | 2)
+#define PINMUX_GPIO37__FUNC_MD1_SIM1_SCLK (MTK_PIN_NO(37) | 3)
+#define PINMUX_GPIO37__FUNC_SCP_JTAG_TDI (MTK_PIN_NO(37) | 5)
+#define PINMUX_GPIO37__FUNC_CONN_DSP_JDO (MTK_PIN_NO(37) | 6)
+#define PINMUX_GPIO37__FUNC_DBG_MON_A30 (MTK_PIN_NO(37) | 7)
+
+#define PINMUX_GPIO38__FUNC_GPIO38 (MTK_PIN_NO(38) | 0)
+#define PINMUX_GPIO38__FUNC_MD1_SIM1_SCLK (MTK_PIN_NO(38) | 1)
+#define PINMUX_GPIO38__FUNC_MD1_SIM2_SCLK (MTK_PIN_NO(38) | 3)
+#define PINMUX_GPIO38__FUNC_CONN_MCU_AICE_TCKC (MTK_PIN_NO(38) | 4)
+#define PINMUX_GPIO38__FUNC_DBG_MON_A20 (MTK_PIN_NO(38) | 7)
+
+#define PINMUX_GPIO39__FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
+#define PINMUX_GPIO39__FUNC_MD1_SIM1_SRST (MTK_PIN_NO(39) | 1)
+#define PINMUX_GPIO39__FUNC_CCU_JTAG_TCK (MTK_PIN_NO(39) | 2)
+#define PINMUX_GPIO39__FUNC_MD1_SIM2_SRST (MTK_PIN_NO(39) | 3)
+#define PINMUX_GPIO39__FUNC_SCP_JTAG_TCK (MTK_PIN_NO(39) | 5)
+#define PINMUX_GPIO39__FUNC_CONN_DSP_JCK (MTK_PIN_NO(39) | 6)
+#define PINMUX_GPIO39__FUNC_DBG_MON_A31 (MTK_PIN_NO(39) | 7)
+
+#define PINMUX_GPIO40__FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
+#define PINMUX_GPIO40__FUNC_MD1_SIM1_SIO (MTK_PIN_NO(40) | 1)
+#define PINMUX_GPIO40__FUNC_CCU_JTAG_TRST (MTK_PIN_NO(40) | 2)
+#define PINMUX_GPIO40__FUNC_MD1_SIM2_SIO (MTK_PIN_NO(40) | 3)
+#define PINMUX_GPIO40__FUNC_SCP_JTAG_TRSTN (MTK_PIN_NO(40) | 5)
+#define PINMUX_GPIO40__FUNC_CONN_DSP_JDI (MTK_PIN_NO(40) | 6)
+#define PINMUX_GPIO40__FUNC_DBG_MON_A32 (MTK_PIN_NO(40) | 7)
+
+#define PINMUX_GPIO41__FUNC_GPIO41 (MTK_PIN_NO(41) | 0)
+#define PINMUX_GPIO41__FUNC_IDDIG (MTK_PIN_NO(41) | 1)
+#define PINMUX_GPIO41__FUNC_URXD1 (MTK_PIN_NO(41) | 2)
+#define PINMUX_GPIO41__FUNC_UCTS0 (MTK_PIN_NO(41) | 3)
+#define PINMUX_GPIO41__FUNC_SSPM_UTXD_AO (MTK_PIN_NO(41) | 4)
+#define PINMUX_GPIO41__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(41) | 5)
+#define PINMUX_GPIO41__FUNC_DMIC_CLK (MTK_PIN_NO(41) | 6)
+
+#define PINMUX_GPIO42__FUNC_GPIO42 (MTK_PIN_NO(42) | 0)
+#define PINMUX_GPIO42__FUNC_USB_DRVVBUS (MTK_PIN_NO(42) | 1)
+#define PINMUX_GPIO42__FUNC_UTXD1 (MTK_PIN_NO(42) | 2)
+#define PINMUX_GPIO42__FUNC_URTS0 (MTK_PIN_NO(42) | 3)
+#define PINMUX_GPIO42__FUNC_SSPM_URXD_AO (MTK_PIN_NO(42) | 4)
+#define PINMUX_GPIO42__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(42) | 5)
+#define PINMUX_GPIO42__FUNC_DMIC_DAT (MTK_PIN_NO(42) | 6)
+
+#define PINMUX_GPIO43__FUNC_GPIO43 (MTK_PIN_NO(43) | 0)
+#define PINMUX_GPIO43__FUNC_DISP_PWM (MTK_PIN_NO(43) | 1)
+
+#define PINMUX_GPIO44__FUNC_GPIO44 (MTK_PIN_NO(44) | 0)
+#define PINMUX_GPIO44__FUNC_DSI_TE (MTK_PIN_NO(44) | 1)
+
+#define PINMUX_GPIO45__FUNC_GPIO45 (MTK_PIN_NO(45) | 0)
+#define PINMUX_GPIO45__FUNC_LCM_RST (MTK_PIN_NO(45) | 1)
+
+#define PINMUX_GPIO46__FUNC_GPIO46 (MTK_PIN_NO(46) | 0)
+#define PINMUX_GPIO46__FUNC_MD_INT2_C2K_UIM1_HOT_PLUG (MTK_PIN_NO(46) | 1)
+#define PINMUX_GPIO46__FUNC_URXD1 (MTK_PIN_NO(46) | 2)
+#define PINMUX_GPIO46__FUNC_UCTS1 (MTK_PIN_NO(46) | 3)
+#define PINMUX_GPIO46__FUNC_CCU_UTXD_AO (MTK_PIN_NO(46) | 4)
+#define PINMUX_GPIO46__FUNC_TP_UCTS1_AO (MTK_PIN_NO(46) | 5)
+#define PINMUX_GPIO46__FUNC_IDDIG (MTK_PIN_NO(46) | 6)
+#define PINMUX_GPIO46__FUNC_I2S5_LRCK (MTK_PIN_NO(46) | 7)
+
+#define PINMUX_GPIO47__FUNC_GPIO47 (MTK_PIN_NO(47) | 0)
+#define PINMUX_GPIO47__FUNC_MD_INT1_C2K_UIM0_HOT_PLUG (MTK_PIN_NO(47) | 1)
+#define PINMUX_GPIO47__FUNC_UTXD1 (MTK_PIN_NO(47) | 2)
+#define PINMUX_GPIO47__FUNC_URTS1 (MTK_PIN_NO(47) | 3)
+#define PINMUX_GPIO47__FUNC_CCU_URXD_AO (MTK_PIN_NO(47) | 4)
+#define PINMUX_GPIO47__FUNC_TP_URTS1_AO (MTK_PIN_NO(47) | 5)
+#define PINMUX_GPIO47__FUNC_USB_DRVVBUS (MTK_PIN_NO(47) | 6)
+#define PINMUX_GPIO47__FUNC_I2S5_DO (MTK_PIN_NO(47) | 7)
+
+#define PINMUX_GPIO48__FUNC_GPIO48 (MTK_PIN_NO(48) | 0)
+#define PINMUX_GPIO48__FUNC_SCL5 (MTK_PIN_NO(48) | 1)
+
+#define PINMUX_GPIO49__FUNC_GPIO49 (MTK_PIN_NO(49) | 0)
+#define PINMUX_GPIO49__FUNC_SDA5 (MTK_PIN_NO(49) | 1)
+
+#define PINMUX_GPIO50__FUNC_GPIO50 (MTK_PIN_NO(50) | 0)
+#define PINMUX_GPIO50__FUNC_SCL3 (MTK_PIN_NO(50) | 1)
+
+#define PINMUX_GPIO51__FUNC_GPIO51 (MTK_PIN_NO(51) | 0)
+#define PINMUX_GPIO51__FUNC_SDA3 (MTK_PIN_NO(51) | 1)
+
+#define PINMUX_GPIO52__FUNC_GPIO52 (MTK_PIN_NO(52) | 0)
+#define PINMUX_GPIO52__FUNC_BPI_ANT2 (MTK_PIN_NO(52) | 1)
+
+#define PINMUX_GPIO53__FUNC_GPIO53 (MTK_PIN_NO(53) | 0)
+#define PINMUX_GPIO53__FUNC_BPI_ANT0 (MTK_PIN_NO(53) | 1)
+
+#define PINMUX_GPIO54__FUNC_GPIO54 (MTK_PIN_NO(54) | 0)
+#define PINMUX_GPIO54__FUNC_BPI_OLAT1 (MTK_PIN_NO(54) | 1)
+
+#define PINMUX_GPIO55__FUNC_GPIO55 (MTK_PIN_NO(55) | 0)
+#define PINMUX_GPIO55__FUNC_BPI_BUS8 (MTK_PIN_NO(55) | 1)
+
+#define PINMUX_GPIO56__FUNC_GPIO56 (MTK_PIN_NO(56) | 0)
+#define PINMUX_GPIO56__FUNC_BPI_BUS9 (MTK_PIN_NO(56) | 1)
+#define PINMUX_GPIO56__FUNC_SCL_6306 (MTK_PIN_NO(56) | 2)
+
+#define PINMUX_GPIO57__FUNC_GPIO57 (MTK_PIN_NO(57) | 0)
+#define PINMUX_GPIO57__FUNC_BPI_BUS10 (MTK_PIN_NO(57) | 1)
+#define PINMUX_GPIO57__FUNC_SDA_6306 (MTK_PIN_NO(57) | 2)
+
+#define PINMUX_GPIO58__FUNC_GPIO58 (MTK_PIN_NO(58) | 0)
+#define PINMUX_GPIO58__FUNC_RFIC0_BSI_D2 (MTK_PIN_NO(58) | 1)
+#define PINMUX_GPIO58__FUNC_SPM_BSI_D2 (MTK_PIN_NO(58) | 2)
+#define PINMUX_GPIO58__FUNC_PWM_B (MTK_PIN_NO(58) | 3)
+
+#define PINMUX_GPIO59__FUNC_GPIO59 (MTK_PIN_NO(59) | 0)
+#define PINMUX_GPIO59__FUNC_RFIC0_BSI_D1 (MTK_PIN_NO(59) | 1)
+#define PINMUX_GPIO59__FUNC_SPM_BSI_D1 (MTK_PIN_NO(59) | 2)
+
+#define PINMUX_GPIO60__FUNC_GPIO60 (MTK_PIN_NO(60) | 0)
+#define PINMUX_GPIO60__FUNC_RFIC0_BSI_D0 (MTK_PIN_NO(60) | 1)
+#define PINMUX_GPIO60__FUNC_SPM_BSI_D0 (MTK_PIN_NO(60) | 2)
+
+#define PINMUX_GPIO61__FUNC_GPIO61 (MTK_PIN_NO(61) | 0)
+#define PINMUX_GPIO61__FUNC_MIPI1_SDATA (MTK_PIN_NO(61) | 1)
+
+#define PINMUX_GPIO62__FUNC_GPIO62 (MTK_PIN_NO(62) | 0)
+#define PINMUX_GPIO62__FUNC_MIPI1_SCLK (MTK_PIN_NO(62) | 1)
+
+#define PINMUX_GPIO63__FUNC_GPIO63 (MTK_PIN_NO(63) | 0)
+#define PINMUX_GPIO63__FUNC_MIPI0_SDATA (MTK_PIN_NO(63) | 1)
+
+#define PINMUX_GPIO64__FUNC_GPIO64 (MTK_PIN_NO(64) | 0)
+#define PINMUX_GPIO64__FUNC_MIPI0_SCLK (MTK_PIN_NO(64) | 1)
+
+#define PINMUX_GPIO65__FUNC_GPIO65 (MTK_PIN_NO(65) | 0)
+#define PINMUX_GPIO65__FUNC_MIPI3_SDATA (MTK_PIN_NO(65) | 1)
+#define PINMUX_GPIO65__FUNC_BPI_OLAT2 (MTK_PIN_NO(65) | 2)
+
+#define PINMUX_GPIO66__FUNC_GPIO66 (MTK_PIN_NO(66) | 0)
+#define PINMUX_GPIO66__FUNC_MIPI3_SCLK (MTK_PIN_NO(66) | 1)
+#define PINMUX_GPIO66__FUNC_BPI_OLAT3 (MTK_PIN_NO(66) | 2)
+
+#define PINMUX_GPIO67__FUNC_GPIO67 (MTK_PIN_NO(67) | 0)
+#define PINMUX_GPIO67__FUNC_MIPI2_SDATA (MTK_PIN_NO(67) | 1)
+
+#define PINMUX_GPIO68__FUNC_GPIO68 (MTK_PIN_NO(68) | 0)
+#define PINMUX_GPIO68__FUNC_MIPI2_SCLK (MTK_PIN_NO(68) | 1)
+
+#define PINMUX_GPIO69__FUNC_GPIO69 (MTK_PIN_NO(69) | 0)
+#define PINMUX_GPIO69__FUNC_BPI_BUS7 (MTK_PIN_NO(69) | 1)
+
+#define PINMUX_GPIO70__FUNC_GPIO70 (MTK_PIN_NO(70) | 0)
+#define PINMUX_GPIO70__FUNC_BPI_BUS6 (MTK_PIN_NO(70) | 1)
+
+#define PINMUX_GPIO71__FUNC_GPIO71 (MTK_PIN_NO(71) | 0)
+#define PINMUX_GPIO71__FUNC_BPI_BUS5 (MTK_PIN_NO(71) | 1)
+
+#define PINMUX_GPIO72__FUNC_GPIO72 (MTK_PIN_NO(72) | 0)
+#define PINMUX_GPIO72__FUNC_BPI_BUS4 (MTK_PIN_NO(72) | 1)
+
+#define PINMUX_GPIO73__FUNC_GPIO73 (MTK_PIN_NO(73) | 0)
+#define PINMUX_GPIO73__FUNC_BPI_BUS3 (MTK_PIN_NO(73) | 1)
+
+#define PINMUX_GPIO74__FUNC_GPIO74 (MTK_PIN_NO(74) | 0)
+#define PINMUX_GPIO74__FUNC_BPI_BUS2 (MTK_PIN_NO(74) | 1)
+
+#define PINMUX_GPIO75__FUNC_GPIO75 (MTK_PIN_NO(75) | 0)
+#define PINMUX_GPIO75__FUNC_BPI_BUS1 (MTK_PIN_NO(75) | 1)
+
+#define PINMUX_GPIO76__FUNC_GPIO76 (MTK_PIN_NO(76) | 0)
+#define PINMUX_GPIO76__FUNC_BPI_BUS0 (MTK_PIN_NO(76) | 1)
+
+#define PINMUX_GPIO77__FUNC_GPIO77 (MTK_PIN_NO(77) | 0)
+#define PINMUX_GPIO77__FUNC_BPI_ANT1 (MTK_PIN_NO(77) | 1)
+
+#define PINMUX_GPIO78__FUNC_GPIO78 (MTK_PIN_NO(78) | 0)
+#define PINMUX_GPIO78__FUNC_BPI_OLAT0 (MTK_PIN_NO(78) | 1)
+
+#define PINMUX_GPIO79__FUNC_GPIO79 (MTK_PIN_NO(79) | 0)
+#define PINMUX_GPIO79__FUNC_BPI_PA_VM1 (MTK_PIN_NO(79) | 1)
+#define PINMUX_GPIO79__FUNC_MIPI4_SDATA (MTK_PIN_NO(79) | 2)
+
+#define PINMUX_GPIO80__FUNC_GPIO80 (MTK_PIN_NO(80) | 0)
+#define PINMUX_GPIO80__FUNC_BPI_PA_VM0 (MTK_PIN_NO(80) | 1)
+#define PINMUX_GPIO80__FUNC_MIPI4_SCLK (MTK_PIN_NO(80) | 2)
+
+#define PINMUX_GPIO81__FUNC_GPIO81 (MTK_PIN_NO(81) | 0)
+#define PINMUX_GPIO81__FUNC_SDA1 (MTK_PIN_NO(81) | 1)
+
+#define PINMUX_GPIO82__FUNC_GPIO82 (MTK_PIN_NO(82) | 0)
+#define PINMUX_GPIO82__FUNC_SDA0 (MTK_PIN_NO(82) | 1)
+
+#define PINMUX_GPIO83__FUNC_GPIO83 (MTK_PIN_NO(83) | 0)
+#define PINMUX_GPIO83__FUNC_SCL0 (MTK_PIN_NO(83) | 1)
+
+#define PINMUX_GPIO84__FUNC_GPIO84 (MTK_PIN_NO(84) | 0)
+#define PINMUX_GPIO84__FUNC_SCL1 (MTK_PIN_NO(84) | 1)
+
+#define PINMUX_GPIO85__FUNC_GPIO85 (MTK_PIN_NO(85) | 0)
+#define PINMUX_GPIO85__FUNC_SPI0_MI (MTK_PIN_NO(85) | 1)
+#define PINMUX_GPIO85__FUNC_SCP_SPI0_MI (MTK_PIN_NO(85) | 2)
+#define PINMUX_GPIO85__FUNC_CLKM3 (MTK_PIN_NO(85) | 3)
+#define PINMUX_GPIO85__FUNC_I2S1_BCK (MTK_PIN_NO(85) | 4)
+#define PINMUX_GPIO85__FUNC_MFG_DFD_JTAG_TDO (MTK_PIN_NO(85) | 5)
+#define PINMUX_GPIO85__FUNC_DFD_TDO (MTK_PIN_NO(85) | 6)
+#define PINMUX_GPIO85__FUNC_JTDO_SEL1 (MTK_PIN_NO(85) | 7)
+
+#define PINMUX_GPIO86__FUNC_GPIO86 (MTK_PIN_NO(86) | 0)
+#define PINMUX_GPIO86__FUNC_SPI0_CSB (MTK_PIN_NO(86) | 1)
+#define PINMUX_GPIO86__FUNC_SCP_SPI0_CS (MTK_PIN_NO(86) | 2)
+#define PINMUX_GPIO86__FUNC_CLKM0 (MTK_PIN_NO(86) | 3)
+#define PINMUX_GPIO86__FUNC_I2S1_LRCK (MTK_PIN_NO(86) | 4)
+#define PINMUX_GPIO86__FUNC_MFG_DFD_JTAG_TMS (MTK_PIN_NO(86) | 5)
+#define PINMUX_GPIO86__FUNC_DFD_TMS (MTK_PIN_NO(86) | 6)
+#define PINMUX_GPIO86__FUNC_JTMS_SEL1 (MTK_PIN_NO(86) | 7)
+
+#define PINMUX_GPIO87__FUNC_GPIO87 (MTK_PIN_NO(87) | 0)
+#define PINMUX_GPIO87__FUNC_SPI0_MO (MTK_PIN_NO(87) | 1)
+#define PINMUX_GPIO87__FUNC_SCP_SPI0_MO (MTK_PIN_NO(87) | 2)
+#define PINMUX_GPIO87__FUNC_SDA1 (MTK_PIN_NO(87) | 3)
+#define PINMUX_GPIO87__FUNC_I2S1_DO (MTK_PIN_NO(87) | 4)
+#define PINMUX_GPIO87__FUNC_MFG_DFD_JTAG_TDI (MTK_PIN_NO(87) | 5)
+#define PINMUX_GPIO87__FUNC_DFD_TDI (MTK_PIN_NO(87) | 6)
+#define PINMUX_GPIO87__FUNC_JTDI_SEL1 (MTK_PIN_NO(87) | 7)
+
+#define PINMUX_GPIO88__FUNC_GPIO88 (MTK_PIN_NO(88) | 0)
+#define PINMUX_GPIO88__FUNC_SPI0_CLK (MTK_PIN_NO(88) | 1)
+#define PINMUX_GPIO88__FUNC_SCP_SPI0_CK (MTK_PIN_NO(88) | 2)
+#define PINMUX_GPIO88__FUNC_SCL1 (MTK_PIN_NO(88) | 3)
+#define PINMUX_GPIO88__FUNC_I2S1_MCK (MTK_PIN_NO(88) | 4)
+#define PINMUX_GPIO88__FUNC_MFG_DFD_JTAG_TCK (MTK_PIN_NO(88) | 5)
+#define PINMUX_GPIO88__FUNC_DFD_TCK_XI (MTK_PIN_NO(88) | 6)
+#define PINMUX_GPIO88__FUNC_JTCK_SEL1 (MTK_PIN_NO(88) | 7)
+
+#define PINMUX_GPIO89__FUNC_GPIO89 (MTK_PIN_NO(89) | 0)
+#define PINMUX_GPIO89__FUNC_SRCLKENAI0 (MTK_PIN_NO(89) | 1)
+#define PINMUX_GPIO89__FUNC_PWM_C (MTK_PIN_NO(89) | 2)
+#define PINMUX_GPIO89__FUNC_I2S5_BCK (MTK_PIN_NO(89) | 3)
+#define PINMUX_GPIO89__FUNC_ANT_SEL6 (MTK_PIN_NO(89) | 4)
+#define PINMUX_GPIO89__FUNC_SDA8 (MTK_PIN_NO(89) | 5)
+#define PINMUX_GPIO89__FUNC_CMVREF0 (MTK_PIN_NO(89) | 6)
+#define PINMUX_GPIO89__FUNC_DBG_MON_A21 (MTK_PIN_NO(89) | 7)
+
+#define PINMUX_GPIO90__FUNC_GPIO90 (MTK_PIN_NO(90) | 0)
+#define PINMUX_GPIO90__FUNC_PWM_A (MTK_PIN_NO(90) | 1)
+#define PINMUX_GPIO90__FUNC_CMMCLK2 (MTK_PIN_NO(90) | 2)
+#define PINMUX_GPIO90__FUNC_I2S5_LRCK (MTK_PIN_NO(90) | 3)
+#define PINMUX_GPIO90__FUNC_SCP_VREQ_VAO (MTK_PIN_NO(90) | 4)
+#define PINMUX_GPIO90__FUNC_SCL8 (MTK_PIN_NO(90) | 5)
+#define PINMUX_GPIO90__FUNC_PTA_RXD (MTK_PIN_NO(90) | 6)
+#define PINMUX_GPIO90__FUNC_DBG_MON_A22 (MTK_PIN_NO(90) | 7)
+
+#define PINMUX_GPIO91__FUNC_GPIO91 (MTK_PIN_NO(91) | 0)
+#define PINMUX_GPIO91__FUNC_KPROW1 (MTK_PIN_NO(91) | 1)
+#define PINMUX_GPIO91__FUNC_PWM_B (MTK_PIN_NO(91) | 2)
+#define PINMUX_GPIO91__FUNC_I2S5_DO (MTK_PIN_NO(91) | 3)
+#define PINMUX_GPIO91__FUNC_ANT_SEL7 (MTK_PIN_NO(91) | 4)
+#define PINMUX_GPIO91__FUNC_CMMCLK3 (MTK_PIN_NO(91) | 5)
+#define PINMUX_GPIO91__FUNC_PTA_TXD (MTK_PIN_NO(91) | 6)
+
+#define PINMUX_GPIO92__FUNC_GPIO92 (MTK_PIN_NO(92) | 0)
+#define PINMUX_GPIO92__FUNC_KPROW0 (MTK_PIN_NO(92) | 1)
+
+#define PINMUX_GPIO93__FUNC_GPIO93 (MTK_PIN_NO(93) | 0)
+#define PINMUX_GPIO93__FUNC_KPCOL0 (MTK_PIN_NO(93) | 1)
+#define PINMUX_GPIO93__FUNC_DBG_MON_B27 (MTK_PIN_NO(93) | 7)
+
+#define PINMUX_GPIO94__FUNC_GPIO94 (MTK_PIN_NO(94) | 0)
+#define PINMUX_GPIO94__FUNC_KPCOL1 (MTK_PIN_NO(94) | 1)
+#define PINMUX_GPIO94__FUNC_I2S2_DI2 (MTK_PIN_NO(94) | 2)
+#define PINMUX_GPIO94__FUNC_I2S5_MCK (MTK_PIN_NO(94) | 3)
+#define PINMUX_GPIO94__FUNC_CMMCLK2 (MTK_PIN_NO(94) | 4)
+#define PINMUX_GPIO94__FUNC_SCP_SPI2_MI (MTK_PIN_NO(94) | 5)
+#define PINMUX_GPIO94__FUNC_SRCLKENAI1 (MTK_PIN_NO(94) | 6)
+#define PINMUX_GPIO94__FUNC_SPI2_MI (MTK_PIN_NO(94) | 7)
+
+#define PINMUX_GPIO95__FUNC_GPIO95 (MTK_PIN_NO(95) | 0)
+#define PINMUX_GPIO95__FUNC_URXD0 (MTK_PIN_NO(95) | 1)
+#define PINMUX_GPIO95__FUNC_UTXD0 (MTK_PIN_NO(95) | 2)
+#define PINMUX_GPIO95__FUNC_MD_URXD0 (MTK_PIN_NO(95) | 3)
+#define PINMUX_GPIO95__FUNC_MD_URXD1 (MTK_PIN_NO(95) | 4)
+#define PINMUX_GPIO95__FUNC_SSPM_URXD_AO (MTK_PIN_NO(95) | 5)
+#define PINMUX_GPIO95__FUNC_CCU_URXD_AO (MTK_PIN_NO(95) | 6)
+
+#define PINMUX_GPIO96__FUNC_GPIO96 (MTK_PIN_NO(96) | 0)
+#define PINMUX_GPIO96__FUNC_UTXD0 (MTK_PIN_NO(96) | 1)
+#define PINMUX_GPIO96__FUNC_URXD0 (MTK_PIN_NO(96) | 2)
+#define PINMUX_GPIO96__FUNC_MD_UTXD0 (MTK_PIN_NO(96) | 3)
+#define PINMUX_GPIO96__FUNC_MD_UTXD1 (MTK_PIN_NO(96) | 4)
+#define PINMUX_GPIO96__FUNC_SSPM_UTXD_AO (MTK_PIN_NO(96) | 5)
+#define PINMUX_GPIO96__FUNC_CCU_UTXD_AO (MTK_PIN_NO(96) | 6)
+#define PINMUX_GPIO96__FUNC_DBG_MON_B2 (MTK_PIN_NO(96) | 7)
+
+#define PINMUX_GPIO97__FUNC_GPIO97 (MTK_PIN_NO(97) | 0)
+#define PINMUX_GPIO97__FUNC_UCTS0 (MTK_PIN_NO(97) | 1)
+#define PINMUX_GPIO97__FUNC_I2S2_MCK (MTK_PIN_NO(97) | 2)
+#define PINMUX_GPIO97__FUNC_IDDIG (MTK_PIN_NO(97) | 3)
+#define PINMUX_GPIO97__FUNC_CONN_MCU_TDO (MTK_PIN_NO(97) | 4)
+#define PINMUX_GPIO97__FUNC_SSPM_JTAG_TDO (MTK_PIN_NO(97) | 5)
+#define PINMUX_GPIO97__FUNC_IO_JTAG_TDO (MTK_PIN_NO(97) | 6)
+#define PINMUX_GPIO97__FUNC_DBG_MON_B3 (MTK_PIN_NO(97) | 7)
+
+#define PINMUX_GPIO98__FUNC_GPIO98 (MTK_PIN_NO(98) | 0)
+#define PINMUX_GPIO98__FUNC_URTS0 (MTK_PIN_NO(98) | 1)
+#define PINMUX_GPIO98__FUNC_I2S2_BCK (MTK_PIN_NO(98) | 2)
+#define PINMUX_GPIO98__FUNC_USB_DRVVBUS (MTK_PIN_NO(98) | 3)
+#define PINMUX_GPIO98__FUNC_CONN_MCU_TMS (MTK_PIN_NO(98) | 4)
+#define PINMUX_GPIO98__FUNC_SSPM_JTAG_TMS (MTK_PIN_NO(98) | 5)
+#define PINMUX_GPIO98__FUNC_IO_JTAG_TMS (MTK_PIN_NO(98) | 6)
+#define PINMUX_GPIO98__FUNC_DBG_MON_B4 (MTK_PIN_NO(98) | 7)
+
+#define PINMUX_GPIO99__FUNC_GPIO99 (MTK_PIN_NO(99) | 0)
+#define PINMUX_GPIO99__FUNC_CMMCLK0 (MTK_PIN_NO(99) | 1)
+#define PINMUX_GPIO99__FUNC_CONN_MCU_AICE_TMSC (MTK_PIN_NO(99) | 4)
+#define PINMUX_GPIO99__FUNC_DBG_MON_B28 (MTK_PIN_NO(99) | 7)
+
+#define PINMUX_GPIO100__FUNC_GPIO100 (MTK_PIN_NO(100) | 0)
+#define PINMUX_GPIO100__FUNC_CMMCLK1 (MTK_PIN_NO(100) | 1)
+#define PINMUX_GPIO100__FUNC_PWM_C (MTK_PIN_NO(100) | 2)
+#define PINMUX_GPIO100__FUNC_MD_INT1_C2K_UIM0_HOT_PLUG (MTK_PIN_NO(100) | 3)
+#define PINMUX_GPIO100__FUNC_CONN_MCU_AICE_TCKC (MTK_PIN_NO(100) | 4)
+#define PINMUX_GPIO100__FUNC_DBG_MON_B29 (MTK_PIN_NO(100) | 7)
+
+#define PINMUX_GPIO101__FUNC_GPIO101 (MTK_PIN_NO(101) | 0)
+#define PINMUX_GPIO101__FUNC_CLKM2 (MTK_PIN_NO(101) | 1)
+#define PINMUX_GPIO101__FUNC_I2S2_LRCK (MTK_PIN_NO(101) | 2)
+#define PINMUX_GPIO101__FUNC_CMVREF1 (MTK_PIN_NO(101) | 3)
+#define PINMUX_GPIO101__FUNC_CONN_MCU_TCK (MTK_PIN_NO(101) | 4)
+#define PINMUX_GPIO101__FUNC_SSPM_JTAG_TCK (MTK_PIN_NO(101) | 5)
+#define PINMUX_GPIO101__FUNC_IO_JTAG_TCK (MTK_PIN_NO(101) | 6)
+
+#define PINMUX_GPIO102__FUNC_GPIO102 (MTK_PIN_NO(102) | 0)
+#define PINMUX_GPIO102__FUNC_CLKM1 (MTK_PIN_NO(102) | 1)
+#define PINMUX_GPIO102__FUNC_I2S2_DI (MTK_PIN_NO(102) | 2)
+#define PINMUX_GPIO102__FUNC_DVFSRC_EXT_REQ (MTK_PIN_NO(102) | 3)
+#define PINMUX_GPIO102__FUNC_CONN_MCU_TDI (MTK_PIN_NO(102) | 4)
+#define PINMUX_GPIO102__FUNC_SSPM_JTAG_TDI (MTK_PIN_NO(102) | 5)
+#define PINMUX_GPIO102__FUNC_IO_JTAG_TDI (MTK_PIN_NO(102) | 6)
+#define PINMUX_GPIO102__FUNC_DBG_MON_B8 (MTK_PIN_NO(102) | 7)
+
+#define PINMUX_GPIO103__FUNC_GPIO103 (MTK_PIN_NO(103) | 0)
+#define PINMUX_GPIO103__FUNC_SCL2 (MTK_PIN_NO(103) | 1)
+
+#define PINMUX_GPIO104__FUNC_GPIO104 (MTK_PIN_NO(104) | 0)
+#define PINMUX_GPIO104__FUNC_SDA2 (MTK_PIN_NO(104) | 1)
+
+#define PINMUX_GPIO105__FUNC_GPIO105 (MTK_PIN_NO(105) | 0)
+#define PINMUX_GPIO105__FUNC_SCL4 (MTK_PIN_NO(105) | 1)
+
+#define PINMUX_GPIO106__FUNC_GPIO106 (MTK_PIN_NO(106) | 0)
+#define PINMUX_GPIO106__FUNC_SDA4 (MTK_PIN_NO(106) | 1)
+
+#define PINMUX_GPIO107__FUNC_GPIO107 (MTK_PIN_NO(107) | 0)
+#define PINMUX_GPIO107__FUNC_DMIC_CLK (MTK_PIN_NO(107) | 1)
+#define PINMUX_GPIO107__FUNC_ANT_SEL0 (MTK_PIN_NO(107) | 2)
+#define PINMUX_GPIO107__FUNC_CLKM0 (MTK_PIN_NO(107) | 3)
+#define PINMUX_GPIO107__FUNC_SDA7 (MTK_PIN_NO(107) | 4)
+#define PINMUX_GPIO107__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(107) | 5)
+#define PINMUX_GPIO107__FUNC_PWM_A (MTK_PIN_NO(107) | 6)
+#define PINMUX_GPIO107__FUNC_DBG_MON_B12 (MTK_PIN_NO(107) | 7)
+
+#define PINMUX_GPIO108__FUNC_GPIO108 (MTK_PIN_NO(108) | 0)
+#define PINMUX_GPIO108__FUNC_CMMCLK2 (MTK_PIN_NO(108) | 1)
+#define PINMUX_GPIO108__FUNC_ANT_SEL1 (MTK_PIN_NO(108) | 2)
+#define PINMUX_GPIO108__FUNC_CLKM1 (MTK_PIN_NO(108) | 3)
+#define PINMUX_GPIO108__FUNC_SCL8 (MTK_PIN_NO(108) | 4)
+#define PINMUX_GPIO108__FUNC_DAP_MD32_SWD (MTK_PIN_NO(108) | 5)
+#define PINMUX_GPIO108__FUNC_PWM_B (MTK_PIN_NO(108) | 6)
+#define PINMUX_GPIO108__FUNC_DBG_MON_B13 (MTK_PIN_NO(108) | 7)
+
+#define PINMUX_GPIO109__FUNC_GPIO109 (MTK_PIN_NO(109) | 0)
+#define PINMUX_GPIO109__FUNC_DMIC_DAT (MTK_PIN_NO(109) | 1)
+#define PINMUX_GPIO109__FUNC_ANT_SEL2 (MTK_PIN_NO(109) | 2)
+#define PINMUX_GPIO109__FUNC_CLKM2 (MTK_PIN_NO(109) | 3)
+#define PINMUX_GPIO109__FUNC_SDA8 (MTK_PIN_NO(109) | 4)
+#define PINMUX_GPIO109__FUNC_DAP_MD32_SWCK (MTK_PIN_NO(109) | 5)
+#define PINMUX_GPIO109__FUNC_PWM_C (MTK_PIN_NO(109) | 6)
+#define PINMUX_GPIO109__FUNC_DBG_MON_B14 (MTK_PIN_NO(109) | 7)
+
+#define PINMUX_GPIO110__FUNC_GPIO110 (MTK_PIN_NO(110) | 0)
+#define PINMUX_GPIO110__FUNC_SCL7 (MTK_PIN_NO(110) | 1)
+#define PINMUX_GPIO110__FUNC_ANT_SEL0 (MTK_PIN_NO(110) | 2)
+#define PINMUX_GPIO110__FUNC_TP_URXD1_AO (MTK_PIN_NO(110) | 3)
+#define PINMUX_GPIO110__FUNC_USB_DRVVBUS (MTK_PIN_NO(110) | 4)
+#define PINMUX_GPIO110__FUNC_SRCLKENAI1 (MTK_PIN_NO(110) | 5)
+#define PINMUX_GPIO110__FUNC_KPCOL2 (MTK_PIN_NO(110) | 6)
+#define PINMUX_GPIO110__FUNC_URXD1 (MTK_PIN_NO(110) | 7)
+
+#define PINMUX_GPIO111__FUNC_GPIO111 (MTK_PIN_NO(111) | 0)
+#define PINMUX_GPIO111__FUNC_CMMCLK3 (MTK_PIN_NO(111) | 1)
+#define PINMUX_GPIO111__FUNC_ANT_SEL1 (MTK_PIN_NO(111) | 2)
+#define PINMUX_GPIO111__FUNC_SRCLKENAI0 (MTK_PIN_NO(111) | 3)
+#define PINMUX_GPIO111__FUNC_SCP_VREQ_VAO (MTK_PIN_NO(111) | 4)
+#define PINMUX_GPIO111__FUNC_MD_INT2_C2K_UIM1_HOT_PLUG (MTK_PIN_NO(111) | 5)
+#define PINMUX_GPIO111__FUNC_DVFSRC_EXT_REQ (MTK_PIN_NO(111) | 7)
+
+#define PINMUX_GPIO112__FUNC_GPIO112 (MTK_PIN_NO(112) | 0)
+#define PINMUX_GPIO112__FUNC_SDA7 (MTK_PIN_NO(112) | 1)
+#define PINMUX_GPIO112__FUNC_ANT_SEL2 (MTK_PIN_NO(112) | 2)
+#define PINMUX_GPIO112__FUNC_TP_UTXD1_AO (MTK_PIN_NO(112) | 3)
+#define PINMUX_GPIO112__FUNC_IDDIG (MTK_PIN_NO(112) | 4)
+#define PINMUX_GPIO112__FUNC_AGPS_SYNC (MTK_PIN_NO(112) | 5)
+#define PINMUX_GPIO112__FUNC_KPROW2 (MTK_PIN_NO(112) | 6)
+#define PINMUX_GPIO112__FUNC_UTXD1 (MTK_PIN_NO(112) | 7)
+
+#define PINMUX_GPIO113__FUNC_GPIO113 (MTK_PIN_NO(113) | 0)
+#define PINMUX_GPIO113__FUNC_CONN_TOP_CLK (MTK_PIN_NO(113) | 1)
+#define PINMUX_GPIO113__FUNC_SCL6 (MTK_PIN_NO(113) | 3)
+#define PINMUX_GPIO113__FUNC_AUXIF_CLK0 (MTK_PIN_NO(113) | 4)
+#define PINMUX_GPIO113__FUNC_TP_UCTS1_AO (MTK_PIN_NO(113) | 6)
+
+#define PINMUX_GPIO114__FUNC_GPIO114 (MTK_PIN_NO(114) | 0)
+#define PINMUX_GPIO114__FUNC_CONN_TOP_DATA (MTK_PIN_NO(114) | 1)
+#define PINMUX_GPIO114__FUNC_SDA6 (MTK_PIN_NO(114) | 3)
+#define PINMUX_GPIO114__FUNC_AUXIF_ST0 (MTK_PIN_NO(114) | 4)
+#define PINMUX_GPIO114__FUNC_TP_URTS1_AO (MTK_PIN_NO(114) | 6)
+
+#define PINMUX_GPIO115__FUNC_GPIO115 (MTK_PIN_NO(115) | 0)
+#define PINMUX_GPIO115__FUNC_CONN_BT_CLK (MTK_PIN_NO(115) | 1)
+#define PINMUX_GPIO115__FUNC_UTXD1 (MTK_PIN_NO(115) | 2)
+#define PINMUX_GPIO115__FUNC_PTA_TXD (MTK_PIN_NO(115) | 3)
+#define PINMUX_GPIO115__FUNC_AUXIF_CLK1 (MTK_PIN_NO(115) | 4)
+#define PINMUX_GPIO115__FUNC_DAP_MD32_SWD (MTK_PIN_NO(115) | 5)
+#define PINMUX_GPIO115__FUNC_TP_UTXD1_AO (MTK_PIN_NO(115) | 6)
+
+#define PINMUX_GPIO116__FUNC_GPIO116 (MTK_PIN_NO(116) | 0)
+#define PINMUX_GPIO116__FUNC_CONN_BT_DATA (MTK_PIN_NO(116) | 1)
+#define PINMUX_GPIO116__FUNC_IPU_JTAG_TRST (MTK_PIN_NO(116) | 2)
+#define PINMUX_GPIO116__FUNC_AUXIF_ST1 (MTK_PIN_NO(116) | 4)
+#define PINMUX_GPIO116__FUNC_DAP_MD32_SWCK (MTK_PIN_NO(116) | 5)
+#define PINMUX_GPIO116__FUNC_TP_URXD2_AO (MTK_PIN_NO(116) | 6)
+#define PINMUX_GPIO116__FUNC_DBG_MON_A0 (MTK_PIN_NO(116) | 7)
+
+#define PINMUX_GPIO117__FUNC_GPIO117 (MTK_PIN_NO(117) | 0)
+#define PINMUX_GPIO117__FUNC_CONN_WF_HB0 (MTK_PIN_NO(117) | 1)
+#define PINMUX_GPIO117__FUNC_IPU_JTAG_TDO (MTK_PIN_NO(117) | 2)
+#define PINMUX_GPIO117__FUNC_TP_UTXD2_AO (MTK_PIN_NO(117) | 6)
+#define PINMUX_GPIO117__FUNC_DBG_MON_A4 (MTK_PIN_NO(117) | 7)
+
+#define PINMUX_GPIO118__FUNC_GPIO118 (MTK_PIN_NO(118) | 0)
+#define PINMUX_GPIO118__FUNC_CONN_WF_HB1 (MTK_PIN_NO(118) | 1)
+#define PINMUX_GPIO118__FUNC_IPU_JTAG_TDI (MTK_PIN_NO(118) | 2)
+#define PINMUX_GPIO118__FUNC_SSPM_URXD_AO (MTK_PIN_NO(118) | 5)
+#define PINMUX_GPIO118__FUNC_TP_UCTS2_AO (MTK_PIN_NO(118) | 6)
+#define PINMUX_GPIO118__FUNC_DBG_MON_A5 (MTK_PIN_NO(118) | 7)
+
+#define PINMUX_GPIO119__FUNC_GPIO119 (MTK_PIN_NO(119) | 0)
+#define PINMUX_GPIO119__FUNC_CONN_WF_HB2 (MTK_PIN_NO(119) | 1)
+#define PINMUX_GPIO119__FUNC_IPU_JTAG_TCK (MTK_PIN_NO(119) | 2)
+#define PINMUX_GPIO119__FUNC_SSPM_UTXD_AO (MTK_PIN_NO(119) | 5)
+#define PINMUX_GPIO119__FUNC_TP_URTS2_AO (MTK_PIN_NO(119) | 6)
+
+#define PINMUX_GPIO120__FUNC_GPIO120 (MTK_PIN_NO(120) | 0)
+#define PINMUX_GPIO120__FUNC_CONN_WB_PTA (MTK_PIN_NO(120) | 1)
+#define PINMUX_GPIO120__FUNC_IPU_JTAG_TMS (MTK_PIN_NO(120) | 2)
+#define PINMUX_GPIO120__FUNC_CCU_URXD_AO (MTK_PIN_NO(120) | 5)
+
+#define PINMUX_GPIO121__FUNC_GPIO121 (MTK_PIN_NO(121) | 0)
+#define PINMUX_GPIO121__FUNC_CONN_HRST_B (MTK_PIN_NO(121) | 1)
+#define PINMUX_GPIO121__FUNC_URXD1 (MTK_PIN_NO(121) | 2)
+#define PINMUX_GPIO121__FUNC_PTA_RXD (MTK_PIN_NO(121) | 3)
+#define PINMUX_GPIO121__FUNC_CCU_UTXD_AO (MTK_PIN_NO(121) | 5)
+#define PINMUX_GPIO121__FUNC_TP_URXD1_AO (MTK_PIN_NO(121) | 6)
+
+#define PINMUX_GPIO122__FUNC_GPIO122 (MTK_PIN_NO(122) | 0)
+#define PINMUX_GPIO122__FUNC_MSDC0_CMD (MTK_PIN_NO(122) | 1)
+#define PINMUX_GPIO122__FUNC_SSPM_URXD2_AO (MTK_PIN_NO(122) | 2)
+#define PINMUX_GPIO122__FUNC_ANT_SEL1 (MTK_PIN_NO(122) | 3)
+#define PINMUX_GPIO122__FUNC_DBG_MON_A12 (MTK_PIN_NO(122) | 7)
+
+#define PINMUX_GPIO123__FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
+#define PINMUX_GPIO123__FUNC_MSDC0_DAT0 (MTK_PIN_NO(123) | 1)
+#define PINMUX_GPIO123__FUNC_ANT_SEL0 (MTK_PIN_NO(123) | 3)
+#define PINMUX_GPIO123__FUNC_DBG_MON_A13 (MTK_PIN_NO(123) | 7)
+
+#define PINMUX_GPIO124__FUNC_GPIO124 (MTK_PIN_NO(124) | 0)
+#define PINMUX_GPIO124__FUNC_MSDC0_CLK (MTK_PIN_NO(124) | 1)
+#define PINMUX_GPIO124__FUNC_DBG_MON_A14 (MTK_PIN_NO(124) | 7)
+
+#define PINMUX_GPIO125__FUNC_GPIO125 (MTK_PIN_NO(125) | 0)
+#define PINMUX_GPIO125__FUNC_MSDC0_DAT2 (MTK_PIN_NO(125) | 1)
+#define PINMUX_GPIO125__FUNC_MRG_CLK (MTK_PIN_NO(125) | 3)
+#define PINMUX_GPIO125__FUNC_DBG_MON_A15 (MTK_PIN_NO(125) | 7)
+
+#define PINMUX_GPIO126__FUNC_GPIO126 (MTK_PIN_NO(126) | 0)
+#define PINMUX_GPIO126__FUNC_MSDC0_DAT4 (MTK_PIN_NO(126) | 1)
+#define PINMUX_GPIO126__FUNC_ANT_SEL5 (MTK_PIN_NO(126) | 3)
+#define PINMUX_GPIO126__FUNC_UFS_MPHY_SCL (MTK_PIN_NO(126) | 6)
+#define PINMUX_GPIO126__FUNC_DBG_MON_A16 (MTK_PIN_NO(126) | 7)
+
+#define PINMUX_GPIO127__FUNC_GPIO127 (MTK_PIN_NO(127) | 0)
+#define PINMUX_GPIO127__FUNC_MSDC0_DAT6 (MTK_PIN_NO(127) | 1)
+#define PINMUX_GPIO127__FUNC_ANT_SEL4 (MTK_PIN_NO(127) | 3)
+#define PINMUX_GPIO127__FUNC_UFS_MPHY_SDA (MTK_PIN_NO(127) | 6)
+#define PINMUX_GPIO127__FUNC_DBG_MON_A17 (MTK_PIN_NO(127) | 7)
+
+#define PINMUX_GPIO128__FUNC_GPIO128 (MTK_PIN_NO(128) | 0)
+#define PINMUX_GPIO128__FUNC_MSDC0_DAT1 (MTK_PIN_NO(128) | 1)
+#define PINMUX_GPIO128__FUNC_ANT_SEL2 (MTK_PIN_NO(128) | 3)
+#define PINMUX_GPIO128__FUNC_UFS_UNIPRO_SDA (MTK_PIN_NO(128) | 6)
+#define PINMUX_GPIO128__FUNC_DBG_MON_A18 (MTK_PIN_NO(128) | 7)
+
+#define PINMUX_GPIO129__FUNC_GPIO129 (MTK_PIN_NO(129) | 0)
+#define PINMUX_GPIO129__FUNC_MSDC0_DAT5 (MTK_PIN_NO(129) | 1)
+#define PINMUX_GPIO129__FUNC_ANT_SEL3 (MTK_PIN_NO(129) | 3)
+#define PINMUX_GPIO129__FUNC_UFS_UNIPRO_SCL (MTK_PIN_NO(129) | 6)
+#define PINMUX_GPIO129__FUNC_DBG_MON_A23 (MTK_PIN_NO(129) | 7)
+
+#define PINMUX_GPIO130__FUNC_GPIO130 (MTK_PIN_NO(130) | 0)
+#define PINMUX_GPIO130__FUNC_MSDC0_DAT7 (MTK_PIN_NO(130) | 1)
+#define PINMUX_GPIO130__FUNC_MRG_DO (MTK_PIN_NO(130) | 3)
+#define PINMUX_GPIO130__FUNC_DBG_MON_A24 (MTK_PIN_NO(130) | 7)
+
+#define PINMUX_GPIO131__FUNC_GPIO131 (MTK_PIN_NO(131) | 0)
+#define PINMUX_GPIO131__FUNC_MSDC0_DSL (MTK_PIN_NO(131) | 1)
+#define PINMUX_GPIO131__FUNC_MRG_SYNC (MTK_PIN_NO(131) | 3)
+#define PINMUX_GPIO131__FUNC_DBG_MON_A25 (MTK_PIN_NO(131) | 7)
+
+#define PINMUX_GPIO132__FUNC_GPIO132 (MTK_PIN_NO(132) | 0)
+#define PINMUX_GPIO132__FUNC_MSDC0_DAT3 (MTK_PIN_NO(132) | 1)
+#define PINMUX_GPIO132__FUNC_MRG_DI (MTK_PIN_NO(132) | 3)
+#define PINMUX_GPIO132__FUNC_DBG_MON_A26 (MTK_PIN_NO(132) | 7)
+
+#define PINMUX_GPIO133__FUNC_GPIO133 (MTK_PIN_NO(133) | 0)
+#define PINMUX_GPIO133__FUNC_MSDC0_RSTB (MTK_PIN_NO(133) | 1)
+#define PINMUX_GPIO133__FUNC_AGPS_SYNC (MTK_PIN_NO(133) | 3)
+#define PINMUX_GPIO133__FUNC_DBG_MON_A27 (MTK_PIN_NO(133) | 7)
+
+#define PINMUX_GPIO134__FUNC_GPIO134 (MTK_PIN_NO(134) | 0)
+#define PINMUX_GPIO134__FUNC_RTC32K_CK (MTK_PIN_NO(134) | 1)
+
+#define PINMUX_GPIO135__FUNC_GPIO135 (MTK_PIN_NO(135) | 0)
+#define PINMUX_GPIO135__FUNC_WATCHDOG (MTK_PIN_NO(135) | 1)
+
+#define PINMUX_GPIO136__FUNC_GPIO136 (MTK_PIN_NO(136) | 0)
+#define PINMUX_GPIO136__FUNC_AUD_CLK_MOSI (MTK_PIN_NO(136) | 1)
+#define PINMUX_GPIO136__FUNC_AUD_CLK_MISO (MTK_PIN_NO(136) | 2)
+#define PINMUX_GPIO136__FUNC_I2S1_MCK (MTK_PIN_NO(136) | 3)
+#define PINMUX_GPIO136__FUNC_UFS_UNIPRO_SCL (MTK_PIN_NO(136) | 6)
+
+#define PINMUX_GPIO137__FUNC_GPIO137 (MTK_PIN_NO(137) | 0)
+#define PINMUX_GPIO137__FUNC_AUD_SYNC_MOSI (MTK_PIN_NO(137) | 1)
+#define PINMUX_GPIO137__FUNC_AUD_SYNC_MISO (MTK_PIN_NO(137) | 2)
+#define PINMUX_GPIO137__FUNC_I2S1_BCK (MTK_PIN_NO(137) | 3)
+
+#define PINMUX_GPIO138__FUNC_GPIO138 (MTK_PIN_NO(138) | 0)
+#define PINMUX_GPIO138__FUNC_AUD_DAT_MOSI0 (MTK_PIN_NO(138) | 1)
+#define PINMUX_GPIO138__FUNC_AUD_DAT_MISO0 (MTK_PIN_NO(138) | 2)
+#define PINMUX_GPIO138__FUNC_I2S1_LRCK (MTK_PIN_NO(138) | 3)
+#define PINMUX_GPIO138__FUNC_DBG_MON_B24 (MTK_PIN_NO(138) | 7)
+
+#define PINMUX_GPIO139__FUNC_GPIO139 (MTK_PIN_NO(139) | 0)
+#define PINMUX_GPIO139__FUNC_AUD_DAT_MOSI1 (MTK_PIN_NO(139) | 1)
+#define PINMUX_GPIO139__FUNC_AUD_DAT_MISO1 (MTK_PIN_NO(139) | 2)
+#define PINMUX_GPIO139__FUNC_I2S1_DO (MTK_PIN_NO(139) | 3)
+#define PINMUX_GPIO139__FUNC_UFS_MPHY_SDA (MTK_PIN_NO(139) | 6)
+
+#define PINMUX_GPIO140__FUNC_GPIO140 (MTK_PIN_NO(140) | 0)
+#define PINMUX_GPIO140__FUNC_AUD_CLK_MISO (MTK_PIN_NO(140) | 1)
+#define PINMUX_GPIO140__FUNC_AUD_CLK_MOSI (MTK_PIN_NO(140) | 2)
+#define PINMUX_GPIO140__FUNC_I2S0_MCK (MTK_PIN_NO(140) | 3)
+#define PINMUX_GPIO140__FUNC_UFS_UNIPRO_SDA (MTK_PIN_NO(140) | 6)
+
+#define PINMUX_GPIO141__FUNC_GPIO141 (MTK_PIN_NO(141) | 0)
+#define PINMUX_GPIO141__FUNC_AUD_SYNC_MISO (MTK_PIN_NO(141) | 1)
+#define PINMUX_GPIO141__FUNC_AUD_SYNC_MOSI (MTK_PIN_NO(141) | 2)
+#define PINMUX_GPIO141__FUNC_I2S0_BCK (MTK_PIN_NO(141) | 3)
+
+#define PINMUX_GPIO142__FUNC_GPIO142 (MTK_PIN_NO(142) | 0)
+#define PINMUX_GPIO142__FUNC_AUD_DAT_MISO0 (MTK_PIN_NO(142) | 1)
+#define PINMUX_GPIO142__FUNC_AUD_DAT_MOSI0 (MTK_PIN_NO(142) | 2)
+#define PINMUX_GPIO142__FUNC_I2S0_LRCK (MTK_PIN_NO(142) | 3)
+#define PINMUX_GPIO142__FUNC_VOW_DAT_MISO (MTK_PIN_NO(142) | 4)
+#define PINMUX_GPIO142__FUNC_DBG_MON_B25 (MTK_PIN_NO(142) | 7)
+
+#define PINMUX_GPIO143__FUNC_GPIO143 (MTK_PIN_NO(143) | 0)
+#define PINMUX_GPIO143__FUNC_AUD_DAT_MISO1 (MTK_PIN_NO(143) | 1)
+#define PINMUX_GPIO143__FUNC_AUD_DAT_MOSI1 (MTK_PIN_NO(143) | 2)
+#define PINMUX_GPIO143__FUNC_I2S0_DI (MTK_PIN_NO(143) | 3)
+#define PINMUX_GPIO143__FUNC_VOW_CLK_MISO (MTK_PIN_NO(143) | 4)
+#define PINMUX_GPIO143__FUNC_UFS_MPHY_SCL (MTK_PIN_NO(143) | 6)
+#define PINMUX_GPIO143__FUNC_DBG_MON_B26 (MTK_PIN_NO(143) | 7)
+
+#define PINMUX_GPIO144__FUNC_GPIO144 (MTK_PIN_NO(144) | 0)
+#define PINMUX_GPIO144__FUNC_PWRAP_SPI0_MI (MTK_PIN_NO(144) | 1)
+#define PINMUX_GPIO144__FUNC_PWRAP_SPI0_MO (MTK_PIN_NO(144) | 2)
+
+#define PINMUX_GPIO145__FUNC_GPIO145 (MTK_PIN_NO(145) | 0)
+#define PINMUX_GPIO145__FUNC_PWRAP_SPI0_CSN (MTK_PIN_NO(145) | 1)
+
+#define PINMUX_GPIO146__FUNC_GPIO146 (MTK_PIN_NO(146) | 0)
+#define PINMUX_GPIO146__FUNC_PWRAP_SPI0_MO (MTK_PIN_NO(146) | 1)
+#define PINMUX_GPIO146__FUNC_PWRAP_SPI0_MI (MTK_PIN_NO(146) | 2)
+
+#define PINMUX_GPIO147__FUNC_GPIO147 (MTK_PIN_NO(147) | 0)
+#define PINMUX_GPIO147__FUNC_PWRAP_SPI0_CK (MTK_PIN_NO(147) | 1)
+
+#define PINMUX_GPIO148__FUNC_GPIO148 (MTK_PIN_NO(148) | 0)
+#define PINMUX_GPIO148__FUNC_SRCLKENA0 (MTK_PIN_NO(148) | 1)
+
+#define PINMUX_GPIO149__FUNC_GPIO149 (MTK_PIN_NO(149) | 0)
+#define PINMUX_GPIO149__FUNC_SRCLKENA1 (MTK_PIN_NO(149) | 1)
+
+#define PINMUX_GPIO150__FUNC_GPIO150 (MTK_PIN_NO(150) | 0)
+#define PINMUX_GPIO150__FUNC_PWM_A (MTK_PIN_NO(150) | 1)
+#define PINMUX_GPIO150__FUNC_CMFLASH (MTK_PIN_NO(150) | 2)
+#define PINMUX_GPIO150__FUNC_CLKM0 (MTK_PIN_NO(150) | 3)
+#define PINMUX_GPIO150__FUNC_DBG_MON_B30 (MTK_PIN_NO(150) | 7)
+
+#define PINMUX_GPIO151__FUNC_GPIO151 (MTK_PIN_NO(151) | 0)
+#define PINMUX_GPIO151__FUNC_PWM_B (MTK_PIN_NO(151) | 1)
+#define PINMUX_GPIO151__FUNC_CMVREF0 (MTK_PIN_NO(151) | 2)
+#define PINMUX_GPIO151__FUNC_CLKM1 (MTK_PIN_NO(151) | 3)
+#define PINMUX_GPIO151__FUNC_DBG_MON_B20 (MTK_PIN_NO(151) | 7)
+
+#define PINMUX_GPIO152__FUNC_GPIO152 (MTK_PIN_NO(152) | 0)
+#define PINMUX_GPIO152__FUNC_PWM_C (MTK_PIN_NO(152) | 1)
+#define PINMUX_GPIO152__FUNC_CMFLASH (MTK_PIN_NO(152) | 2)
+#define PINMUX_GPIO152__FUNC_CLKM2 (MTK_PIN_NO(152) | 3)
+#define PINMUX_GPIO152__FUNC_DBG_MON_B21 (MTK_PIN_NO(152) | 7)
+
+#define PINMUX_GPIO153__FUNC_GPIO153 (MTK_PIN_NO(153) | 0)
+#define PINMUX_GPIO153__FUNC_PWM_A (MTK_PIN_NO(153) | 1)
+#define PINMUX_GPIO153__FUNC_CMVREF0 (MTK_PIN_NO(153) | 2)
+#define PINMUX_GPIO153__FUNC_CLKM3 (MTK_PIN_NO(153) | 3)
+#define PINMUX_GPIO153__FUNC_DBG_MON_B22 (MTK_PIN_NO(153) | 7)
+
+#define PINMUX_GPIO154__FUNC_GPIO154 (MTK_PIN_NO(154) | 0)
+#define PINMUX_GPIO154__FUNC_SCP_VREQ_VAO (MTK_PIN_NO(154) | 1)
+#define PINMUX_GPIO154__FUNC_DVFSRC_EXT_REQ (MTK_PIN_NO(154) | 2)
+#define PINMUX_GPIO154__FUNC_DBG_MON_B18 (MTK_PIN_NO(154) | 7)
+
+#define PINMUX_GPIO155__FUNC_GPIO155 (MTK_PIN_NO(155) | 0)
+#define PINMUX_GPIO155__FUNC_ANT_SEL0 (MTK_PIN_NO(155) | 1)
+#define PINMUX_GPIO155__FUNC_DVFSRC_EXT_REQ (MTK_PIN_NO(155) | 2)
+#define PINMUX_GPIO155__FUNC_CMVREF1 (MTK_PIN_NO(155) | 3)
+#define PINMUX_GPIO155__FUNC_SCP_JTAG_TDI (MTK_PIN_NO(155) | 7)
+
+#define PINMUX_GPIO156__FUNC_GPIO156 (MTK_PIN_NO(156) | 0)
+#define PINMUX_GPIO156__FUNC_ANT_SEL1 (MTK_PIN_NO(156) | 1)
+#define PINMUX_GPIO156__FUNC_SRCLKENAI0 (MTK_PIN_NO(156) | 2)
+#define PINMUX_GPIO156__FUNC_SCL6 (MTK_PIN_NO(156) | 3)
+#define PINMUX_GPIO156__FUNC_KPCOL2 (MTK_PIN_NO(156) | 4)
+#define PINMUX_GPIO156__FUNC_IDDIG (MTK_PIN_NO(156) | 5)
+#define PINMUX_GPIO156__FUNC_SCP_JTAG_TCK (MTK_PIN_NO(156) | 7)
+
+#define PINMUX_GPIO157__FUNC_GPIO157 (MTK_PIN_NO(157) | 0)
+#define PINMUX_GPIO157__FUNC_ANT_SEL2 (MTK_PIN_NO(157) | 1)
+#define PINMUX_GPIO157__FUNC_SRCLKENAI1 (MTK_PIN_NO(157) | 2)
+#define PINMUX_GPIO157__FUNC_SDA6 (MTK_PIN_NO(157) | 3)
+#define PINMUX_GPIO157__FUNC_KPROW2 (MTK_PIN_NO(157) | 4)
+#define PINMUX_GPIO157__FUNC_USB_DRVVBUS (MTK_PIN_NO(157) | 5)
+#define PINMUX_GPIO157__FUNC_SCP_JTAG_TRSTN (MTK_PIN_NO(157) | 7)
+
+#define PINMUX_GPIO158__FUNC_GPIO158 (MTK_PIN_NO(158) | 0)
+#define PINMUX_GPIO158__FUNC_ANT_SEL3 (MTK_PIN_NO(158) | 1)
+
+#define PINMUX_GPIO159__FUNC_GPIO159 (MTK_PIN_NO(159) | 0)
+#define PINMUX_GPIO159__FUNC_ANT_SEL4 (MTK_PIN_NO(159) | 1)
+
+#define PINMUX_GPIO160__FUNC_GPIO160 (MTK_PIN_NO(160) | 0)
+#define PINMUX_GPIO160__FUNC_ANT_SEL5 (MTK_PIN_NO(160) | 1)
+
+#define PINMUX_GPIO161__FUNC_GPIO161 (MTK_PIN_NO(161) | 0)
+#define PINMUX_GPIO161__FUNC_SPI1_A_MI (MTK_PIN_NO(161) | 1)
+#define PINMUX_GPIO161__FUNC_SCP_SPI1_MI (MTK_PIN_NO(161) | 2)
+#define PINMUX_GPIO161__FUNC_IDDIG (MTK_PIN_NO(161) | 3)
+#define PINMUX_GPIO161__FUNC_ANT_SEL6 (MTK_PIN_NO(161) | 4)
+#define PINMUX_GPIO161__FUNC_KPCOL2 (MTK_PIN_NO(161) | 5)
+#define PINMUX_GPIO161__FUNC_PTA_RXD (MTK_PIN_NO(161) | 6)
+#define PINMUX_GPIO161__FUNC_DBG_MON_B19 (MTK_PIN_NO(161) | 7)
+
+#define PINMUX_GPIO162__FUNC_GPIO162 (MTK_PIN_NO(162) | 0)
+#define PINMUX_GPIO162__FUNC_SPI1_A_CSB (MTK_PIN_NO(162) | 1)
+#define PINMUX_GPIO162__FUNC_SCP_SPI1_CS (MTK_PIN_NO(162) | 2)
+#define PINMUX_GPIO162__FUNC_USB_DRVVBUS (MTK_PIN_NO(162) | 3)
+#define PINMUX_GPIO162__FUNC_ANT_SEL5 (MTK_PIN_NO(162) | 4)
+#define PINMUX_GPIO162__FUNC_KPROW2 (MTK_PIN_NO(162) | 5)
+#define PINMUX_GPIO162__FUNC_PTA_TXD (MTK_PIN_NO(162) | 6)
+
+#define PINMUX_GPIO163__FUNC_GPIO163 (MTK_PIN_NO(163) | 0)
+#define PINMUX_GPIO163__FUNC_SPI1_A_MO (MTK_PIN_NO(163) | 1)
+#define PINMUX_GPIO163__FUNC_SCP_SPI1_MO (MTK_PIN_NO(163) | 2)
+#define PINMUX_GPIO163__FUNC_SDA1 (MTK_PIN_NO(163) | 3)
+#define PINMUX_GPIO163__FUNC_ANT_SEL4 (MTK_PIN_NO(163) | 4)
+#define PINMUX_GPIO163__FUNC_CMMCLK2 (MTK_PIN_NO(163) | 5)
+#define PINMUX_GPIO163__FUNC_DMIC_CLK (MTK_PIN_NO(163) | 6)
+
+#define PINMUX_GPIO164__FUNC_GPIO164 (MTK_PIN_NO(164) | 0)
+#define PINMUX_GPIO164__FUNC_SPI1_A_CLK (MTK_PIN_NO(164) | 1)
+#define PINMUX_GPIO164__FUNC_SCP_SPI1_CK (MTK_PIN_NO(164) | 2)
+#define PINMUX_GPIO164__FUNC_SCL1 (MTK_PIN_NO(164) | 3)
+#define PINMUX_GPIO164__FUNC_ANT_SEL3 (MTK_PIN_NO(164) | 4)
+#define PINMUX_GPIO164__FUNC_CMMCLK3 (MTK_PIN_NO(164) | 5)
+#define PINMUX_GPIO164__FUNC_DMIC_DAT (MTK_PIN_NO(164) | 6)
+
+#define PINMUX_GPIO165__FUNC_GPIO165 (MTK_PIN_NO(165) | 0)
+#define PINMUX_GPIO165__FUNC_PWM_B (MTK_PIN_NO(165) | 1)
+#define PINMUX_GPIO165__FUNC_CMMCLK2 (MTK_PIN_NO(165) | 2)
+#define PINMUX_GPIO165__FUNC_SCP_VREQ_VAO (MTK_PIN_NO(165) | 3)
+#define PINMUX_GPIO165__FUNC_TDM_MCK_2ND (MTK_PIN_NO(165) | 6)
+#define PINMUX_GPIO165__FUNC_SCP_JTAG_TDO (MTK_PIN_NO(165) | 7)
+
+#define PINMUX_GPIO166__FUNC_GPIO166 (MTK_PIN_NO(166) | 0)
+#define PINMUX_GPIO166__FUNC_ANT_SEL6 (MTK_PIN_NO(166) | 1)
+
+#define PINMUX_GPIO167__FUNC_GPIO167 (MTK_PIN_NO(167) | 0)
+#define PINMUX_GPIO167__FUNC_RFIC0_BSI_EN (MTK_PIN_NO(167) | 1)
+#define PINMUX_GPIO167__FUNC_SPM_BSI_EN (MTK_PIN_NO(167) | 2)
+
+#define PINMUX_GPIO168__FUNC_GPIO168 (MTK_PIN_NO(168) | 0)
+#define PINMUX_GPIO168__FUNC_RFIC0_BSI_CK (MTK_PIN_NO(168) | 1)
+#define PINMUX_GPIO168__FUNC_SPM_BSI_CK (MTK_PIN_NO(168) | 2)
+
+#define PINMUX_GPIO169__FUNC_GPIO169 (MTK_PIN_NO(169) | 0)
+#define PINMUX_GPIO169__FUNC_PWM_C (MTK_PIN_NO(169) | 1)
+#define PINMUX_GPIO169__FUNC_CMMCLK3 (MTK_PIN_NO(169) | 2)
+#define PINMUX_GPIO169__FUNC_CMVREF1 (MTK_PIN_NO(169) | 3)
+#define PINMUX_GPIO169__FUNC_ANT_SEL7 (MTK_PIN_NO(169) | 4)
+#define PINMUX_GPIO169__FUNC_AGPS_SYNC (MTK_PIN_NO(169) | 5)
+#define PINMUX_GPIO169__FUNC_TDM_BCK_2ND (MTK_PIN_NO(169) | 6)
+#define PINMUX_GPIO169__FUNC_SCP_JTAG_TMS (MTK_PIN_NO(169) | 7)
+
+#define PINMUX_GPIO170__FUNC_GPIO170 (MTK_PIN_NO(170) | 0)
+#define PINMUX_GPIO170__FUNC_I2S1_BCK (MTK_PIN_NO(170) | 1)
+#define PINMUX_GPIO170__FUNC_I2S3_BCK (MTK_PIN_NO(170) | 2)
+#define PINMUX_GPIO170__FUNC_SCL7 (MTK_PIN_NO(170) | 3)
+#define PINMUX_GPIO170__FUNC_I2S5_BCK (MTK_PIN_NO(170) | 4)
+#define PINMUX_GPIO170__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(170) | 5)
+#define PINMUX_GPIO170__FUNC_TDM_LRCK_2ND (MTK_PIN_NO(170) | 6)
+#define PINMUX_GPIO170__FUNC_ANT_SEL3 (MTK_PIN_NO(170) | 7)
+
+#define PINMUX_GPIO171__FUNC_GPIO171 (MTK_PIN_NO(171) | 0)
+#define PINMUX_GPIO171__FUNC_I2S1_LRCK (MTK_PIN_NO(171) | 1)
+#define PINMUX_GPIO171__FUNC_I2S3_LRCK (MTK_PIN_NO(171) | 2)
+#define PINMUX_GPIO171__FUNC_SDA7 (MTK_PIN_NO(171) | 3)
+#define PINMUX_GPIO171__FUNC_I2S5_LRCK (MTK_PIN_NO(171) | 4)
+#define PINMUX_GPIO171__FUNC_URXD1 (MTK_PIN_NO(171) | 5)
+#define PINMUX_GPIO171__FUNC_TDM_DATA0_2ND (MTK_PIN_NO(171) | 6)
+#define PINMUX_GPIO171__FUNC_ANT_SEL4 (MTK_PIN_NO(171) | 7)
+
+#define PINMUX_GPIO172__FUNC_GPIO172 (MTK_PIN_NO(172) | 0)
+#define PINMUX_GPIO172__FUNC_I2S1_DO (MTK_PIN_NO(172) | 1)
+#define PINMUX_GPIO172__FUNC_I2S3_DO (MTK_PIN_NO(172) | 2)
+#define PINMUX_GPIO172__FUNC_SCL8 (MTK_PIN_NO(172) | 3)
+#define PINMUX_GPIO172__FUNC_I2S5_DO (MTK_PIN_NO(172) | 4)
+#define PINMUX_GPIO172__FUNC_UTXD1 (MTK_PIN_NO(172) | 5)
+#define PINMUX_GPIO172__FUNC_TDM_DATA1_2ND (MTK_PIN_NO(172) | 6)
+#define PINMUX_GPIO172__FUNC_ANT_SEL5 (MTK_PIN_NO(172) | 7)
+
+#define PINMUX_GPIO173__FUNC_GPIO173 (MTK_PIN_NO(173) | 0)
+#define PINMUX_GPIO173__FUNC_I2S1_MCK (MTK_PIN_NO(173) | 1)
+#define PINMUX_GPIO173__FUNC_I2S3_MCK (MTK_PIN_NO(173) | 2)
+#define PINMUX_GPIO173__FUNC_SDA8 (MTK_PIN_NO(173) | 3)
+#define PINMUX_GPIO173__FUNC_I2S5_MCK (MTK_PIN_NO(173) | 4)
+#define PINMUX_GPIO173__FUNC_UCTS0 (MTK_PIN_NO(173) | 5)
+#define PINMUX_GPIO173__FUNC_TDM_DATA2_2ND (MTK_PIN_NO(173) | 6)
+#define PINMUX_GPIO173__FUNC_ANT_SEL6 (MTK_PIN_NO(173) | 7)
+
+#define PINMUX_GPIO174__FUNC_GPIO174 (MTK_PIN_NO(174) | 0)
+#define PINMUX_GPIO174__FUNC_I2S2_DI (MTK_PIN_NO(174) | 1)
+#define PINMUX_GPIO174__FUNC_I2S0_DI (MTK_PIN_NO(174) | 2)
+#define PINMUX_GPIO174__FUNC_DVFSRC_EXT_REQ (MTK_PIN_NO(174) | 3)
+#define PINMUX_GPIO174__FUNC_I2S2_DI2 (MTK_PIN_NO(174) | 4)
+#define PINMUX_GPIO174__FUNC_URTS0 (MTK_PIN_NO(174) | 5)
+#define PINMUX_GPIO174__FUNC_TDM_DATA3_2ND (MTK_PIN_NO(174) | 6)
+#define PINMUX_GPIO174__FUNC_ANT_SEL7 (MTK_PIN_NO(174) | 7)
+
+#define PINMUX_GPIO175__FUNC_GPIO175 (MTK_PIN_NO(175) | 0)
+#define PINMUX_GPIO175__FUNC_ANT_SEL7 (MTK_PIN_NO(175) | 1)
+
+#define PINMUX_GPIO176__FUNC_GPIO176 (MTK_PIN_NO(176) | 0)
+
+#define PINMUX_GPIO177__FUNC_GPIO177 (MTK_PIN_NO(177) | 0)
+
+#define PINMUX_GPIO178__FUNC_GPIO178 (MTK_PIN_NO(178) | 0)
+
+#define PINMUX_GPIO179__FUNC_GPIO179 (MTK_PIN_NO(179) | 0)
+
+#endif /* __MT8183-PINFUNC_H */
index 6b8ab55..bcd018c 100644 (file)
@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra132-norrin.dtb
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-0000.dtb
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-2180.dtb
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571.dtb
+dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p3450-0000.dtb
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-smaug.dtb
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2894-0050-a08.dtb
 dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p2771-0000.dtb
index 31457f3..75ee6cf 100644 (file)
                status = "okay";
        };
 
+       padctl@3520000 {
+               status = "okay";
+
+               avdd-pll-erefeut-supply = <&vdd_1v8_pll>;
+               avdd-usb-supply = <&vdd_3v3_sys>;
+               dvdd-pex-supply = <&vdd_pex>;
+               dvdd-pex-pll-supply = <&vdd_pex>;
+               hvdd-pex-supply = <&vdd_1v8>;
+               hvdd-pex-pll-supply = <&vdd_1v8>;
+               vclamp-usb-supply = <&vdd_1v8>;
+               vddio-hsic-supply = <&gnd>;
+
+               pads {
+                       usb2 {
+                               status = "okay";
+
+                               lanes {
+                                       usb2-0 {
+                                               nvidia,function = "xusb";
+                                               status = "okay";
+                                       };
+
+                                       usb2-1 {
+                                               nvidia,function = "xusb";
+                                               status = "okay";
+                                       };
+
+                                       usb2-2 {
+                                               nvidia,function = "xusb";
+                                               status = "okay";
+                                       };
+                               };
+                       };
+
+                       usb3 {
+                               status = "okay";
+
+                               lanes {
+                                       usb3-0 {
+                                               nvidia,function = "xusb";
+                                               status = "okay";
+                                       };
+
+                                       usb3-1 {
+                                               nvidia,function = "xusb";
+                                               status = "okay";
+                                       };
+
+                                       usb3-2 {
+                                               nvidia,function = "xusb";
+                                               status = "okay";
+                                       };
+                               };
+                       };
+               };
+
+               ports {
+                       usb2-0 {
+                               status = "okay";
+                               mode = "otg";
+
+                               vbus-supply = <&vdd_usb0>;
+                       };
+
+                       usb2-1 {
+                               status = "okay";
+                               mode = "host";
+
+                               vbus-supply = <&vdd_usb1>;
+                       };
+
+                       usb3-0 {
+                               nvidia,usb2-companion = <1>;
+                               status = "okay";
+                       };
+               };
+       };
+
+       usb@3530000 {
+               status = "okay";
+
+               phys = <&{/padctl@3520000/pads/usb2/lanes/usb2-0}>,
+                      <&{/padctl@3520000/pads/usb2/lanes/usb2-1}>,
+                      <&{/padctl@3520000/pads/usb3/lanes/usb3-0}>;
+               phy-names = "usb2-0", "usb2-1", "usb3-0";
+       };
+
        pcie@10003000 {
                status = "okay";
 
 
                        vin-supply = <&vdd_5v0_sys>;
                };
+
+               vdd_usb0: regulator@102 {
+                       compatible = "regulator-fixed";
+                       reg = <102>;
+
+                       regulator-name = "VDD_USB0";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+
+                       gpio = <&gpio TEGRA_MAIN_GPIO(L, 4) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+
+               vdd_usb1: regulator@103 {
+                       compatible = "regulator-fixed";
+                       reg = <103>;
+
+                       regulator-name = "VDD_USB1";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+
+                       gpio = <&gpio TEGRA_MAIN_GPIO(L, 5) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+
+                       vin-supply = <&vdd_5v0_sys>;
+               };
        };
 };
index 89a2da4..64686b0 100644 (file)
                                                regulator-name = "AVDD_DSI_CSI_1V2";
                                                regulator-min-microvolt = <1200000>;
                                                regulator-max-microvolt = <1200000>;
-                                               /* XXX */
-                                               regulator-always-on;
-                                               regulator-boot-on;
                                        };
 
                                        vdd_1v8: sd2 {
                                                regulator-name = "VDD_1V8";
                                                regulator-min-microvolt = <1800000>;
                                                regulator-max-microvolt = <1800000>;
-                                               /* XXX */
-                                               regulator-always-on;
-                                               regulator-boot-on;
                                        };
 
                                        vdd_3v3_sys: sd3 {
                                                regulator-name = "VDD_3V3_SYS";
                                                regulator-min-microvolt = <3300000>;
                                                regulator-max-microvolt = <3300000>;
-                                               /* XXX */
-                                               regulator-always-on;
-                                               regulator-boot-on;
                                        };
 
-                                       ldo0 {
+                                       vdd_1v8_pll: ldo0 {
                                                regulator-name = "VDD_1V8_AP_PLL";
                                                regulator-min-microvolt = <1800000>;
                                                regulator-max-microvolt = <1800000>;
-                                               /* XXX */
-                                               regulator-always-on;
-                                               regulator-boot-on;
                                        };
 
                                        ldo2 {
                                                regulator-name = "VDDIO_3V3_AOHV";
                                                regulator-min-microvolt = <3300000>;
                                                regulator-max-microvolt = <3300000>;
-                                               /* XXX */
                                                regulator-always-on;
                                                regulator-boot-on;
                                        };
                                                regulator-name = "VDD_HDMI_1V05";
                                                regulator-min-microvolt = <1050000>;
                                                regulator-max-microvolt = <1050000>;
-                                               /* XXX */
-                                               regulator-always-on;
-                                               regulator-boot-on;
                                        };
 
                                        vdd_pex: ldo8 {
                                                regulator-name = "VDD_PEX_1V05";
                                                regulator-min-microvolt = <1050000>;
                                                regulator-max-microvolt = <1050000>;
-                                               /* XXX */
-                                               regulator-always-on;
-                                               regulator-boot-on;
                                        };
                                };
                        };
                #address-cells = <1>;
                #size-cells = <0>;
 
-               vdd_5v0_sys: regulator@0 {
+               gnd: regulator@0 {
                        compatible = "regulator-fixed";
                        reg = <0>;
 
+                       regulator-name = "GND";
+                       regulator-min-microvolt = <0>;
+                       regulator-max-microvolt = <0>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+
+               vdd_5v0_sys: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+
                        regulator-name = "VDD_5V0_SYS";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
                        regulator-boot-on;
                };
 
-               vdd_1v8_ap: regulator@1 {
+               vdd_1v8_ap: regulator@2 {
                        compatible = "regulator-fixed";
-                       reg = <1>;
+                       reg = <2>;
 
                        regulator-name = "VDD_1V8_AP";
                        regulator-min-microvolt = <1800000>;
                        regulator-max-microvolt = <1800000>;
 
-                       /* XXX */
-                       regulator-always-on;
-                       regulator-boot-on;
-
                        gpio = <&pmic 1 GPIO_ACTIVE_HIGH>;
                        enable-active-high;
 
index 97aeb94..f0bb6ce 100644 (file)
                nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x0a>;
                nvidia,pad-autocal-pull-up-offset-3v3-timeout = <0x0a>;
                nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x0a>;
-               nvidia,default-tap = <0x5>;
-               nvidia,default-trim = <0x9>;
+               nvidia,default-tap = <0x9>;
+               nvidia,default-trim = <0x5>;
                nvidia,dqs-trim = <63>;
                mmc-hs400-1_8v;
+               supports-cqe;
                status = "disabled";
        };
 
                status = "disabled";
        };
 
+       padctl: padctl@3520000 {
+               compatible = "nvidia,tegra186-xusb-padctl";
+               reg = <0x0 0x03520000 0x0 0x1000>,
+                     <0x0 0x03540000 0x0 0x1000>;
+               reg-names = "padctl", "ao";
+
+               resets = <&bpmp TEGRA186_RESET_XUSB_PADCTL>;
+               reset-names = "padctl";
+
+               status = "disabled";
+
+               pads {
+                       usb2 {
+                               clocks = <&bpmp TEGRA186_CLK_USB2_TRK>;
+                               clock-names = "trk";
+                               status = "disabled";
+
+                               lanes {
+                                       usb2-0 {
+                                               status = "disabled";
+                                               #phy-cells = <0>;
+                                       };
+
+                                       usb2-1 {
+                                               status = "disabled";
+                                               #phy-cells = <0>;
+                                       };
+
+                                       usb2-2 {
+                                               status = "disabled";
+                                               #phy-cells = <0>;
+                                       };
+                               };
+                       };
+
+                       hsic {
+                               clocks = <&bpmp TEGRA186_CLK_HSIC_TRK>;
+                               clock-names = "trk";
+                               status = "disabled";
+
+                               lanes {
+                                       hsic-0 {
+                                               status = "disabled";
+                                               #phy-cells = <0>;
+                                       };
+                               };
+                       };
+
+                       usb3 {
+                               status = "disabled";
+
+                               lanes {
+                                       usb3-0 {
+                                               status = "disabled";
+                                               #phy-cells = <0>;
+                                       };
+
+                                       usb3-1 {
+                                               status = "disabled";
+                                               #phy-cells = <0>;
+                                       };
+
+                                       usb3-2 {
+                                               status = "disabled";
+                                               #phy-cells = <0>;
+                                       };
+                               };
+                       };
+               };
+
+               ports {
+                       usb2-0 {
+                               status = "disabled";
+                       };
+
+                       usb2-1 {
+                               status = "disabled";
+                       };
+
+                       usb2-2 {
+                               status = "disabled";
+                       };
+
+                       hsic-0 {
+                               status = "disabled";
+                       };
+
+                       usb3-0 {
+                               status = "disabled";
+                       };
+
+                       usb3-1 {
+                               status = "disabled";
+                       };
+
+                       usb3-2 {
+                               status = "disabled";
+                       };
+               };
+       };
+
+       usb@3530000 {
+               compatible = "nvidia,tegra186-xusb";
+               reg = <0x0 0x03530000 0x0 0x8000>,
+                     <0x0 0x03538000 0x0 0x1000>;
+               reg-names = "hcd", "fpci";
+
+               interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
+
+               clocks = <&bpmp TEGRA186_CLK_XUSB_HOST>,
+                        <&bpmp TEGRA186_CLK_XUSB_FALCON>,
+                        <&bpmp TEGRA186_CLK_XUSB_SS>,
+                        <&bpmp TEGRA186_CLK_XUSB_CORE_SS>,
+                        <&bpmp TEGRA186_CLK_CLK_M>,
+                        <&bpmp TEGRA186_CLK_XUSB_FS>,
+                        <&bpmp TEGRA186_CLK_PLLU>,
+                        <&bpmp TEGRA186_CLK_CLK_M>,
+                        <&bpmp TEGRA186_CLK_PLLE>;
+               clock-names = "xusb_host", "xusb_falcon_src", "xusb_ss",
+                             "xusb_ss_src", "xusb_hs_src", "xusb_fs_src",
+                             "pll_u_480m", "clk_m", "pll_e";
+
+               power-domains = <&bpmp TEGRA186_POWER_DOMAIN_XUSBC>,
+                               <&bpmp TEGRA186_POWER_DOMAIN_XUSBA>;
+               power-domain-names = "xusb_host", "xusb_ss";
+               nvidia,xusb-padctl = <&padctl>;
+
+               status = "disabled";
+
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
        fuse@3820000 {
                compatible = "nvidia,tegra186-efuse";
                reg = <0x0 0x03820000 0x0 0x10000>;
index 246c1eb..0fd5bd2 100644 (file)
                                interrupt-parent = <&gpio>;
                                interrupts = <TEGRA194_MAIN_GPIO(H, 2)
                                              IRQ_TYPE_LEVEL_LOW>;
+                               vcc-supply = <&vdd_1v8ls>;
 
                                #thermal-sensor-cells = <1>;
                        };
index b62e969..73801b4 100644 (file)
@@ -57,8 +57,6 @@
                pwms = <&pwm4 0 45334>;
 
                cooling-levels = <0 64 128 255>;
-               cooling-min-state = <0>;
-               cooling-max-state = <3>;
                #cooling-cells = <2>;
        };
 
index 053458a..4dcd0d3 100644 (file)
                cpu@3 {
                        enable-method = "psci";
                };
+
+               idle-states {
+                       cpu-sleep {
+                               status = "okay";
+                       };
+               };
        };
 
        psci {
index 9fad0d2..5a57396 100644 (file)
                pinctrl-0 = <&dvfs_pwm_active_state>;
                pinctrl-1 = <&dvfs_pwm_inactive_state>;
        };
+
+       aconnect@702c0000 {
+               status = "okay";
+
+               dma@702e2000 {
+                       status = "okay";
+               };
+
+               agic@702f9000 {
+                       status = "okay";
+               };
+       };
 };
index 95e890d..a7dc319 100644 (file)
        padctl@7009f000 {
                status = "okay";
 
+               avdd-pll-utmip-supply = <&vdd_1v8>;
+               avdd-pll-uerefe-supply = <&avdd_1v05_pll>;
+               dvdd-pex-pll-supply = <&vdd_pex_1v05>;
+               hvdd-pex-pll-e-supply = <&vdd_1v8>;
+
                pads {
                        usb2 {
                                status = "okay";
index 3ddf173..88a4b93 100644 (file)
                cpu@3 {
                        enable-method = "psci";
                };
+
+               idle-states {
+                       cpu-sleep {
+                               status = "okay";
+                       };
+               };
        };
 
        psci {
diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts b/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts
new file mode 100644 (file)
index 0000000..5d01819
--- /dev/null
@@ -0,0 +1,650 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+#include <dt-bindings/input/gpio-keys.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/mfd/max77620.h>
+
+#include "tegra210.dtsi"
+
+/ {
+       model = "NVIDIA Jetson Nano Developer Kit";
+       compatible = "nvidia,p3450-0000", "nvidia,tegra210";
+
+       aliases {
+               ethernet = "/pcie@1003000/pci@2,0/ethernet@0,0";
+               rtc0 = "/i2c@7000d000/pmic@3c";
+               rtc1 = "/rtc@7000e000";
+               serial0 = &uarta;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x80000000 0x1 0x0>;
+       };
+
+       pcie@1003000 {
+               status = "okay";
+
+               avdd-pll-uerefe-supply = <&vdd_pex_1v05>;
+               hvddio-pex-supply = <&vdd_1v8>;
+               dvddio-pex-supply = <&vdd_pex_1v05>;
+               dvdd-pex-pll-supply = <&vdd_pex_1v05>;
+               hvdd-pex-pll-e-supply = <&vdd_1v8>;
+               vddio-pex-ctl-supply = <&vdd_1v8>;
+
+               pci@1,0 {
+                       phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-1}>,
+                              <&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>,
+                              <&{/padctl@7009f000/pads/pcie/lanes/pcie-3}>,
+                              <&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>;
+                       phy-names = "pcie-0", "pcie-1", "pcie-2", "pcie-3";
+                       nvidia,num-lanes = <4>;
+                       status = "okay";
+               };
+
+               pci@2,0 {
+                       phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>;
+                       phy-names = "pcie-0";
+                       status = "okay";
+
+                       ethernet@0,0 {
+                               reg = <0x000000 0 0 0 0>;
+                               local-mac-address = [ 00 00 00 00 00 00 ];
+                       };
+               };
+       };
+
+       host1x@50000000 {
+               dpaux@54040000 {
+                       status = "okay";
+               };
+
+               sor@54580000 {
+                       status = "okay";
+
+                       avdd-io-supply = <&avdd_1v05>;
+                       vdd-pll-supply = <&vdd_1v8>;
+                       hdmi-supply = <&vdd_hdmi>;
+
+                       nvidia,ddc-i2c-bus = <&hdmi_ddc>;
+                       nvidia,hpd-gpio = <&gpio TEGRA_GPIO(CC, 1)
+                                          GPIO_ACTIVE_LOW>;
+                       nvidia,xbar-cfg = <0 1 2 3 4>;
+               };
+       };
+
+       gpu@57000000 {
+               vdd-supply = <&vdd_gpu>;
+               status = "okay";
+       };
+
+       /* debug port */
+       serial@70006000 {
+               status = "okay";
+       };
+
+       hdmi_ddc: i2c@7000c700 {
+               status = "okay";
+               clock-frequency = <100000>;
+       };
+
+       i2c@7000d000 {
+               status = "okay";
+               clock-frequency = <400000>;
+
+               pmic: pmic@3c {
+                       compatible = "maxim,max77620";
+                       reg = <0x3c>;
+                       interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+
+                       #gpio-cells = <2>;
+                       gpio-controller;
+
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&max77620_default>;
+
+                       max77620_default: pinmux {
+                               gpio0 {
+                                       pins = "gpio0";
+                                       function = "gpio";
+                               };
+
+                               gpio1 {
+                                       pins = "gpio1";
+                                       function = "fps-out";
+                                       drive-push-pull = <1>;
+                                       maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
+                                       maxim,active-fps-power-up-slot = <0>;
+                                       maxim,active-fps-power-down-slot = <7>;
+                               };
+
+                               gpio2 {
+                                       pins = "gpio2";
+                                       function = "fps-out";
+                                       drive-open-drain = <1>;
+                                       maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
+                                       maxim,active-fps-power-up-slot = <0>;
+                                       maxim,active-fps-power-down-slot = <7>;
+                               };
+
+                               gpio3 {
+                                       pins = "gpio3";
+                                       function = "fps-out";
+                                       drive-open-drain = <1>;
+                                       maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
+                                       maxim,active-fps-power-up-slot = <4>;
+                                       maxim,active-fps-power-down-slot = <3>;
+                               };
+
+                               gpio4 {
+                                       pins = "gpio4";
+                                       function = "32k-out1";
+                               };
+
+                               gpio5_6_7 {
+                                       pins = "gpio5", "gpio6", "gpio7";
+                                       function = "gpio";
+                                       drive-push-pull = <1>;
+                               };
+                       };
+
+                       fps {
+                               fps0 {
+                                       maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
+                                       maxim,suspend-fps-time-period-us = <5120>;
+                               };
+
+                               fps1 {
+                                       maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN1>;
+                                       maxim,suspend-fps-time-period-us = <5120>;
+                               };
+
+                               fps2 {
+                                       maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
+                               };
+                       };
+
+                       regulators {
+                               in-ldo0-1-supply = <&vdd_pre>;
+                               in-ldo2-supply = <&vdd_3v3_sys>;
+                               in-ldo3-5-supply = <&vdd_1v8>;
+                               in-ldo4-6-supply = <&vdd_5v0_sys>;
+                               in-ldo7-8-supply = <&vdd_pre>;
+                               in-sd0-supply = <&vdd_5v0_sys>;
+                               in-sd1-supply = <&vdd_5v0_sys>;
+                               in-sd2-supply = <&vdd_5v0_sys>;
+                               in-sd3-supply = <&vdd_5v0_sys>;
+
+                               vdd_soc: sd0 {
+                                       regulator-name = "VDD_SOC";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1170000>;
+                                       regulator-enable-ramp-delay = <146>;
+                                       regulator-disable-ramp-delay = <4080>;
+                                       regulator-ramp-delay = <27500>;
+                                       regulator-ramp-delay-scale = <300>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+
+                                       maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
+                                       maxim,active-fps-power-up-slot = <1>;
+                                       maxim,active-fps-power-down-slot = <6>;
+                               };
+
+                               vdd_ddr: sd1 {
+                                       regulator-name = "VDD_DDR_1V1_PMIC";
+                                       regulator-min-microvolt = <1150000>;
+                                       regulator-max-microvolt = <1150000>;
+                                       regulator-enable-ramp-delay = <176>;
+                                       regulator-disable-ramp-delay = <145800>;
+                                       regulator-ramp-delay = <27500>;
+                                       regulator-ramp-delay-scale = <300>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+
+                                       maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
+                                       maxim,active-fps-power-up-slot = <5>;
+                                       maxim,active-fps-power-down-slot = <2>;
+                               };
+
+                               vdd_pre: sd2 {
+                                       regulator-name = "VDD_PRE_REG_1V35";
+                                       regulator-min-microvolt = <1350000>;
+                                       regulator-max-microvolt = <1350000>;
+                                       regulator-enable-ramp-delay = <176>;
+                                       regulator-disable-ramp-delay = <32000>;
+                                       regulator-ramp-delay = <27500>;
+                                       regulator-ramp-delay-scale = <350>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+
+                                       maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
+                                       maxim,active-fps-power-up-slot = <2>;
+                                       maxim,active-fps-power-down-slot = <5>;
+                               };
+
+                               vdd_1v8: sd3 {
+                                       regulator-name = "VDD_1V8";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-enable-ramp-delay = <242>;
+                                       regulator-disable-ramp-delay = <118000>;
+                                       regulator-ramp-delay = <27500>;
+                                       regulator-ramp-delay-scale = <360>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+
+                                       maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
+                                       maxim,active-fps-power-up-slot = <3>;
+                                       maxim,active-fps-power-down-slot = <4>;
+                               };
+
+                               vdd_sys_1v2: ldo0 {
+                                       regulator-name = "AVDD_SYS_1V2";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-enable-ramp-delay = <26>;
+                                       regulator-disable-ramp-delay = <626>;
+                                       regulator-ramp-delay = <100000>;
+                                       regulator-ramp-delay-scale = <200>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+
+                                       maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
+                                       maxim,active-fps-power-up-slot = <0>;
+                                       maxim,active-fps-power-down-slot = <7>;
+                               };
+
+                               vdd_pex_1v05: ldo1 {
+                                       regulator-name = "VDD_PEX_1V05";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                                       regulator-enable-ramp-delay = <22>;
+                                       regulator-disable-ramp-delay = <650>;
+                                       regulator-ramp-delay = <100000>;
+                                       regulator-ramp-delay-scale = <200>;
+
+                                       maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
+                                       maxim,active-fps-power-up-slot = <0>;
+                                       maxim,active-fps-power-down-slot = <7>;
+                               };
+
+                               vddio_sdmmc: ldo2 {
+                                       regulator-name = "VDDIO_SDMMC";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <3300000>;
+                                       regulator-enable-ramp-delay = <62>;
+                                       regulator-disable-ramp-delay = <650>;
+                                       regulator-ramp-delay = <100000>;
+                                       regulator-ramp-delay-scale = <200>;
+
+                                       maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
+                                       maxim,active-fps-power-up-slot = <0>;
+                                       maxim,active-fps-power-down-slot = <7>;
+                               };
+
+                               ldo3 {
+                                       status = "disabled";
+                               };
+
+                               vdd_rtc: ldo4 {
+                                       regulator-name = "VDD_RTC";
+                                       regulator-min-microvolt = <850000>;
+                                       regulator-max-microvolt = <1100000>;
+                                       regulator-enable-ramp-delay = <22>;
+                                       regulator-disable-ramp-delay = <610>;
+                                       regulator-ramp-delay = <100000>;
+                                       regulator-ramp-delay-scale = <200>;
+                                       regulator-disable-active-discharge;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+
+                                       maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
+                                       maxim,active-fps-power-up-slot = <1>;
+                                       maxim,active-fps-power-down-slot = <6>;
+                               };
+
+                               ldo5 {
+                                       status = "disabled";
+                               };
+
+                               ldo6 {
+                                       status = "disabled";
+                               };
+
+                               avdd_1v05_pll: ldo7 {
+                                       regulator-name = "AVDD_1V05_PLL";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                                       regulator-enable-ramp-delay = <24>;
+                                       regulator-disable-ramp-delay = <2768>;
+                                       regulator-ramp-delay = <100000>;
+                                       regulator-ramp-delay-scale = <200>;
+
+                                       maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
+                                       maxim,active-fps-power-up-slot = <3>;
+                                       maxim,active-fps-power-down-slot = <4>;
+                               };
+
+                               avdd_1v05: ldo8 {
+                                       regulator-name = "AVDD_SATA_HDMI_DP_1V05";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                                       regulator-enable-ramp-delay = <22>;
+                                       regulator-disable-ramp-delay = <1160>;
+                                       regulator-ramp-delay = <100000>;
+                                       regulator-ramp-delay-scale = <200>;
+
+                                       maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
+                                       maxim,active-fps-power-up-slot = <6>;
+                                       maxim,active-fps-power-down-slot = <1>;
+                               };
+                       };
+               };
+       };
+
+       pmc@7000e400 {
+               nvidia,invert-interrupt;
+       };
+
+       hda@70030000 {
+               nvidia,model = "jetson-nano-hda";
+
+               status = "okay";
+       };
+
+       usb@70090000 {
+               phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
+                      <&{/padctl@7009f000/pads/usb2/lanes/usb2-1}>,
+                      <&{/padctl@7009f000/pads/usb2/lanes/usb2-2}>,
+                      <&{/padctl@7009f000/pads/pcie/lanes/pcie-6}>;
+               phy-names = "usb2-0", "usb2-1", "usb2-2", "usb3-0";
+
+               avdd-usb-supply = <&vdd_3v3_sys>;
+               dvddio-pex-supply = <&vdd_pex_1v05>;
+               hvddio-pex-supply = <&vdd_1v8>;
+               /* these really belong to the XUSB pad controller */
+               avdd-pll-utmip-supply = <&vdd_1v8>;
+               avdd-pll-uerefe-supply = <&vdd_pex_1v05>;
+               dvdd-usb-ss-pll-supply = <&vdd_pex_1v05>;
+               hvdd-usb-ss-pll-e-supply = <&vdd_1v8>;
+
+               status = "okay";
+       };
+
+       padctl@7009f000 {
+               status = "okay";
+
+               avdd-pll-utmip-supply = <&vdd_1v8>;
+               avdd-pll-uerefe-supply = <&vdd_pex_1v05>;
+               dvdd-pex-pll-supply = <&vdd_pex_1v05>;
+               hvdd-pex-pll-e-supply = <&vdd_1v8>;
+
+               pads {
+                       usb2 {
+                               status = "okay";
+
+                               lanes {
+                                       usb2-0 {
+                                               nvidia,function = "xusb";
+                                               status = "okay";
+                                       };
+
+                                       usb2-1 {
+                                               nvidia,function = "xusb";
+                                               status = "okay";
+                                       };
+
+                                       usb2-2 {
+                                               nvidia,function = "xusb";
+                                               status = "okay";
+                                       };
+                               };
+                       };
+
+                       pcie {
+                               status = "okay";
+
+                               lanes {
+                                       pcie-0 {
+                                               nvidia,function = "pcie-x1";
+                                               status = "okay";
+                                       };
+
+                                       pcie-1 {
+                                               nvidia,function = "pcie-x4";
+                                               status = "okay";
+                                       };
+
+                                       pcie-2 {
+                                               nvidia,function = "pcie-x4";
+                                               status = "okay";
+                                       };
+
+                                       pcie-3 {
+                                               nvidia,function = "pcie-x4";
+                                               status = "okay";
+                                       };
+
+                                       pcie-4 {
+                                               nvidia,function = "pcie-x4";
+                                               status = "okay";
+                                       };
+
+                                       pcie-5 {
+                                               nvidia,function = "usb3-ss";
+                                               status = "okay";
+                                       };
+
+                                       pcie-6 {
+                                               nvidia,function = "usb3-ss";
+                                               status = "okay";
+                                       };
+                               };
+                       };
+               };
+
+               ports {
+                       usb2-0 {
+                               status = "okay";
+                               mode = "otg";
+                       };
+
+                       usb2-1 {
+                               status = "okay";
+                               mode = "host";
+                       };
+
+                       usb2-2 {
+                               status = "okay";
+                               mode = "host";
+                       };
+
+                       usb3-0 {
+                               status = "okay";
+                               nvidia,usb2-companion = <1>;
+                               vbus-supply = <&vdd_hub_3v3>;
+                       };
+               };
+       };
+
+       sdhci@700b0000 {
+               status = "okay";
+               bus-width = <4>;
+
+               cd-gpios = <&gpio TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
+
+               vqmmc-supply = <&vddio_sdmmc>;
+               vmmc-supply = <&vdd_3v3_sd>;
+       };
+
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock@0 {
+                       compatible = "fixed-clock";
+                       reg = <0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
+       cpus {
+               cpu@0 {
+                       enable-method = "psci";
+               };
+
+               cpu@1 {
+                       enable-method = "psci";
+               };
+
+               cpu@2 {
+                       enable-method = "psci";
+               };
+
+               cpu@3 {
+                       enable-method = "psci";
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               power {
+                       label = "Power";
+                       gpios = <&gpio TEGRA_GPIO(X, 5) GPIO_ACTIVE_LOW>;
+                       linux,input-type = <EV_KEY>;
+                       linux,code = <KEY_POWER>;
+                       debounce-interval = <30>;
+                       wakeup-event-action = <EV_ACT_ASSERTED>;
+                       wakeup-source;
+               };
+
+               force-recovery {
+                       label = "Force Recovery";
+                       gpios = <&gpio TEGRA_GPIO(X, 6) GPIO_ACTIVE_LOW>;
+                       linux,input-type = <EV_KEY>;
+                       linux,code = <BTN_1>;
+                       debounce-interval = <30>;
+               };
+       };
+
+       psci {
+               compatible = "arm,psci-1.0";
+               method = "smc";
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               vdd_5v0_sys: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+
+                       regulator-name = "VDD_5V0_SYS";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+
+               vdd_3v3_sys: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "VDD_3V3_SYS";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-enable-ramp-delay = <240>;
+                       regulator-disable-ramp-delay = <11340>;
+                       regulator-always-on;
+                       regulator-boot-on;
+
+                       gpio = <&pmic 3 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+
+               vdd_3v3_sd: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+
+                       regulator-name = "VDD_3V3_SD";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+
+                       gpio = <&gpio TEGRA_GPIO(Z, 3) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+
+                       vin-supply = <&vdd_3v3_sys>;
+               };
+
+               vdd_hdmi: regulator@3 {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+
+                       regulator-name = "VDD_HDMI_5V0";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+
+               vdd_hub_3v3: regulator@4 {
+                       compatible = "regulator-fixed";
+                       reg = <4>;
+
+                       regulator-name = "VDD_HUB_3V3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+
+                       gpio = <&gpio TEGRA_GPIO(A, 6) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+
+               vdd_cpu: regulator@5 {
+                       compatible = "regulator-fixed";
+                       reg = <5>;
+
+                       regulator-name = "VDD_CPU";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+
+                       gpio = <&pmic 5 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+
+               vdd_gpu: regulator@6 {
+                       compatible = "regulator-fixed";
+                       reg = <6>;
+
+                       regulator-name = "VDD_GPU";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-enable-ramp-delay = <250>;
+
+                       gpio = <&pmic 6 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+       };
+};
index a4b8f66..72c7a04 100644 (file)
        padctl@7009f000 {
                status = "okay";
 
+               avdd-pll-utmip-supply = <&pp1800>;
+               avdd-pll-uerefe-supply = <&pp1050_avdd>;
+               dvdd-pex-pll-supply = <&avddio_1v05>;
+               hvdd-pex-pll-e-supply = <&pp1800>;
+
                pads {
                        usb2 {
                                status = "okay";
                cpu@3 {
                        enable-method = "psci";
                };
+
+               idle-states {
+                       cpu-sleep {
+                               arm,psci-suspend-param = <0x00010007>;
+                               status = "okay";
+                       };
+               };
        };
 
        gpio-keys {
index 6574396..a550c0a 100644 (file)
        };
 
        timer@60005000 {
-               compatible = "nvidia,tegra210-timer", "nvidia,tegra20-timer";
+               compatible = "nvidia,tegra210-timer";
                reg = <0x0 0x60005000 0x0 0x400>;
-               interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+               interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
-                            <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+                            <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&tegra_car TEGRA210_CLK_TIMER>;
                clock-names = "timer";
        };
                                 <&dfll>;
                        clock-names = "cpu_g", "pll_x", "pll_p", "dfll";
                        clock-latency = <300000>;
+                       cpu-idle-states = <&CPU_SLEEP>;
+                       next-level-cache = <&L2>;
                };
 
                cpu@1 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a57";
                        reg = <1>;
+                       cpu-idle-states = <&CPU_SLEEP>;
+                       next-level-cache = <&L2>;
                };
 
                cpu@2 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a57";
                        reg = <2>;
+                       cpu-idle-states = <&CPU_SLEEP>;
+                       next-level-cache = <&L2>;
                };
 
                cpu@3 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a57";
                        reg = <3>;
+                       cpu-idle-states = <&CPU_SLEEP>;
+                       next-level-cache = <&L2>;
+               };
+
+               idle-states {
+                       entry-method = "psci";
+
+                       CPU_SLEEP: cpu-sleep {
+                               compatible = "arm,idle-state";
+                               arm,psci-suspend-param = <0x40000007>;
+                               entry-latency-us = <100>;
+                               exit-latency-us = <30>;
+                               min-residency-us = <1000>;
+                               wakeup-latency-us = <130>;
+                               idle-state-name = "cpu-sleep";
+                               status = "disabled";
+                       };
+               };
+
+               L2: l2-cache {
+                       compatible = "cache";
                };
        };
 
index 6a57387..1c0d06f 100644 (file)
                        bias-disable;
                };
        };
+
+       hdmi_hpd_active: hdmi_hpd_active {
+               mux {
+                       pins = "gpio34";
+                       function = "hdmi_hot";
+               };
+
+               config {
+                       pins = "gpio34";
+                       bias-pull-down;
+                       drive-strength = <16>;
+               };
+       };
+
+       hdmi_hpd_suspend: hdmi_hpd_suspend {
+               mux {
+                       pins = "gpio34";
+                       function = "hdmi_hot";
+               };
+
+               config {
+                       pins = "gpio34";
+                       bias-pull-down;
+                       drive-strength = <2>;
+               };
+       };
+
+       hdmi_ddc_active: hdmi_ddc_active {
+               mux {
+                       pins = "gpio32", "gpio33";
+                       function = "hdmi_ddc";
+               };
+
+               config {
+                       pins = "gpio32", "gpio33";
+                       drive-strength = <2>;
+                       bias-pull-up;
+               };
+       };
+
+       hdmi_ddc_suspend: hdmi_ddc_suspend {
+               mux {
+                       pins = "gpio32", "gpio33";
+                       function = "hdmi_ddc";
+               };
+
+               config {
+                       pins = "gpio32", "gpio33";
+                       drive-strength = <2>;
+                       bias-pull-down;
+               };
+       };
 };
index a6ad3d7..31a3e33 100644 (file)
                };
        };
 
+       audio_mclk: clk_div1 {
+               pinconf {
+                       pins = "gpio15";
+                       function = "func1";
+                       power-source = <PM8994_GPIO_S4>; // 1.8V
+               };
+       };
+
        volume_up_gpio: pm8996_gpio2 {
                pinconf {
                        pins = "gpio2";
index 6d50449..943f699 100644 (file)
@@ -18,6 +18,8 @@
 #include "apq8096-db820c-pmic-pins.dtsi"
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6asm.h>
 
 /*
  * GPIO name legend: proper name = the GPIO line is used as GPIO
@@ -63,6 +65,7 @@
        };
 
        clocks {
+               compatible = "simple-bus";
                divclk4: divclk4 {
                        compatible = "fixed-clock";
                        #clock-cells = <0>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&divclk4_pin_a>;
                };
+
+               div1_mclk: divclk1 {
+                       compatible = "gpio-gate-clock";
+                       pinctrl-0 = <&audio_mclk>;
+                       pinctrl-names = "default";
+                       clocks = <&rpmcc RPM_SMD_DIV_CLK1>;
+                       #clock-cells = <0>;
+                       enable-gpios = <&pm8994_gpios 15 0>;
+               };
        };
 
        soc {
                                perst-gpio = <&msmgpio 114 GPIO_ACTIVE_LOW>;
                        };
                };
+
+               slim_msm: slim@91c0000 {
+                       ngd@1 {
+                               wcd9335: codec@1{
+                                       clock-names = "mclk", "slimbus";
+                                       clocks = <&div1_mclk>,
+                                                <&rpmcc RPM_SMD_BB_CLK1>;
+                               };
+                       };
+               };
+
+               mdss@900000 {
+                       status = "okay";
+
+                       mdp@901000 {
+                               status = "okay";
+                       };
+
+                       hdmi-phy@9a0600 {
+                               status = "okay";
+
+                               vddio-supply = <&pm8994_l12>;
+                               vcca-supply = <&pm8994_l28>;
+                               #phy-cells = <0>;
+                       };
+
+                       hdmi-tx@9a0000 {
+                               status = "okay";
+
+                               pinctrl-names = "default", "sleep";
+                               pinctrl-0 = <&hdmi_hpd_active &hdmi_ddc_active>;
+                               pinctrl-1 = <&hdmi_hpd_suspend &hdmi_ddc_suspend>;
+
+                               core-vdda-supply = <&pm8994_l12>;
+                               core-vcc-supply = <&pm8994_s4>;
+                       };
+               };
        };
 
 
                };
        };
 };
+
+&sound {
+       compatible = "qcom,apq8096-sndcard";
+       model = "DB820c";
+       audio-routing = "RX_BIAS", "MCLK";
+
+       mm1-dai-link {
+               link-name = "MultiMedia1";
+               cpu {
+                       sound-dai = <&q6asmdai  MSM_FRONTEND_DAI_MULTIMEDIA1>;
+               };
+       };
+
+       mm2-dai-link {
+               link-name = "MultiMedia2";
+               cpu {
+                       sound-dai = <&q6asmdai  MSM_FRONTEND_DAI_MULTIMEDIA2>;
+               };
+       };
+
+       mm3-dai-link {
+               link-name = "MultiMedia3";
+               cpu {
+                       sound-dai = <&q6asmdai  MSM_FRONTEND_DAI_MULTIMEDIA3>;
+               };
+       };
+
+       hdmi-dai-link {
+               link-name = "HDMI";
+               cpu {
+                       sound-dai = <&q6afedai HDMI_RX>;
+               };
+
+               platform {
+                       sound-dai = <&q6routing>;
+               };
+
+               codec {
+                       sound-dai = <&hdmi 0>;
+               };
+       };
+
+       slim-dai-link {
+               link-name = "SLIM Playback";
+               cpu {
+                       sound-dai = <&q6afedai SLIMBUS_6_RX>;
+               };
+
+               platform {
+                       sound-dai = <&q6routing>;
+       };
+
+               codec {
+                       sound-dai = <&wcd9335 6>;
+               };
+       };
+
+       slimcap-dai-link {
+               link-name = "SLIM Capture";
+               cpu {
+                       sound-dai = <&q6afedai SLIMBUS_0_TX>;
+               };
+
+               platform {
+                       sound-dai = <&q6routing>;
+               };
+
+               codec {
+                       sound-dai = <&wcd9335 1>;
+               };
+       };
+};
index 0803ca8..423dda9 100644 (file)
        };
 
        thermal-zones {
-               cpu-thermal0 {
+               cpu0_1-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
                        thermal-sensors = <&tsens 4>;
 
                        trips {
-                               cpu_alert0: trip0 {
+                               cpu0_1_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
-                               cpu_crit0: trip1 {
+                               cpu0_1_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
 
                        cooling-maps {
                                map0 {
-                                       trip = <&cpu_alert0>;
+                                       trip = <&cpu0_1_alert0>;
                                        cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
                                                         <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
                                                         <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
                        };
                };
 
-               cpu-thermal1 {
+               cpu2_3-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
                        thermal-sensors = <&tsens 3>;
 
                        trips {
-                               cpu_alert1: trip0 {
+                               cpu2_3_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
-                               cpu_crit1: trip1 {
+                               cpu2_3_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
 
                        cooling-maps {
                                map0 {
-                                       trip = <&cpu_alert1>;
+                                       trip = <&cpu2_3_alert0>;
                                        cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
                                                         <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
                                                         <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
                        thermal-sensors = <&tsens 2>;
 
                        trips {
-                               gpu_alert: trip0 {
+                               gpu_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
-                               gpu_crit: trip1 {
+                               gpu_crit: gpu_crit {
                                        temperature = <95000>;
                                        hysteresis = <2000>;
                                        type = "critical";
                        thermal-sensors = <&tsens 1>;
 
                        trips {
-                               cam_alert: trip0 {
+                               cam_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
-                                       type = "passive";
+                                       type = "hot";
                                };
-                               cam_crit: trip1 {
-                                       temperature = <95000>;
+                       };
+               };
+
+               modem-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens 0>;
+
+                       trips {
+                               modem_alert0: trip-point@0 {
+                                       temperature = <85000>;
                                        hysteresis = <2000>;
-                                       type = "critical";
+                                       type = "hot";
                                };
                        };
-
                };
 
        };
                                #clock-cells = <1>;
                                #phy-cells = <0>;
 
-                               clocks = <&gcc GCC_MDSS_AHB_CLK>;
-                               clock-names = "iface";
+                               clocks = <&gcc GCC_MDSS_AHB_CLK>,
+                                        <&xo_board>;
+                               clock-names = "iface", "ref";
                        };
                };
 
index 131878d..fba2229 100644 (file)
 
 &msmgpio {
 
+       wcd9xxx_intr {
+               wcd_intr_default: wcd_intr_default{
+                       mux {
+                               pins = "gpio54";
+                               function = "gpio";
+                       };
+
+                       config {
+                               pins = "gpio54";
+                               drive-strength = <2>; /* 2 mA */
+                               bias-pull-down; /* pull down */
+                               input-enable;
+                       };
+               };
+       };
+
+       cdc_reset_ctrl {
+               cdc_reset_sleep: cdc_reset_sleep {
+                       mux {
+                               pins = "gpio64";
+                               function = "gpio";
+                       };
+                       config {
+                               pins = "gpio64";
+                               drive-strength = <16>;
+                               bias-disable;
+                               output-low;
+                       };
+               };
+               cdc_reset_active:cdc_reset_active {
+                       mux {
+                               pins = "gpio64";
+                               function = "gpio";
+                       };
+                       config {
+                               pins = "gpio64";
+                               drive-strength = <16>;
+                               bias-pull-down;
+                               output-high;
+                       };
+               };
+       };
+
        blsp1_spi0_default: blsp1_spi0_default {
                pinmux {
                        function = "blsp_spi1";
index c761269..c4e7fde 100644 (file)
@@ -14,6 +14,7 @@
 #include <dt-bindings/clock/qcom,gcc-msm8996.h>
 #include <dt-bindings/clock/qcom,mmcc-msm8996.h>
 #include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/soc/qcom,apr.h>
 
 / {
        interrupt-parent = <&intc>;
                        qcom,client-id = <1>;
                        qcom,vmid = <15>;
                };
+
+               zap_shader_region: gpu@8f200000 {
+                       compatible = "shared-dma-pool";
+                       reg = <0x0 0x90b00000 0x0 0xa00000>;
+                       no-map;
+               };
        };
 
        cpus {
        };
 
        thermal-zones {
-               cpu-thermal0 {
+               cpu0-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
                        thermal-sensors = <&tsens0 3>;
 
                        trips {
-                               cpu_alert0: trip0 {
+                               cpu0_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
 
-                               cpu_crit0: trip1 {
+                               cpu0_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
                        };
                };
 
-               cpu-thermal1 {
+               cpu1-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
                        thermal-sensors = <&tsens0 5>;
 
                        trips {
-                               cpu_alert1: trip0 {
+                               cpu1_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
 
-                               cpu_crit1: trip1 {
+                               cpu1_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
                        };
                };
 
-               cpu-thermal2 {
+               cpu2-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
                        thermal-sensors = <&tsens0 8>;
 
                        trips {
-                               cpu_alert2: trip0 {
+                               cpu2_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
 
-                               cpu_crit2: trip1 {
+                               cpu2_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
                        };
                };
 
-               cpu-thermal3 {
+               cpu3-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
                        thermal-sensors = <&tsens0 10>;
 
                        trips {
-                               cpu_alert3: trip0 {
+                               cpu3_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
 
-                               cpu_crit3: trip1 {
+                               cpu3_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
                                };
                        };
                };
+
+               gpu-thermal-top {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 6>;
+
+                       trips {
+                               gpu1_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               gpu-thermal-bottom {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 7>;
+
+                       trips {
+                               gpu2_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               m4m-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 1>;
+
+                       trips {
+                               m4m_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               l3-or-venus-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 2>;
+
+                       trips {
+                               l3_or_venus_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               cluster0-l2-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 7>;
+
+                       trips {
+                               cluster0_l2_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               cluster1-l2-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 12>;
+
+                       trips {
+                               cluster1_l2_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               camera-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 1>;
+
+                       trips {
+                               camera_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               q6-dsp-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 2>;
+
+                       trips {
+                               q6_dsp_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               mem-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 3>;
+
+                       trips {
+                               mem_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               modemtx-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 4>;
+
+                       trips {
+                               modemtx_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
        };
 
        timer {
                                reg = <0x24f 0x1>;
                                bits = <1 4>;
                        };
+
+                       gpu_speed_bin: gpu_speed_bin@133 {
+                               reg = <0x133 0x1>;
+                               bits = <5 3>;
+                       };
                };
 
                phy@34000 {
                        };
                };
 
+               adreno_smmu: arm,smmu@b40000 {
+                       compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
+                       reg = <0xb40000 0x10000>;
+
+                       #global-interrupts = <1>;
+                       interrupts = <GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>;
+                       #iommu-cells = <1>;
+
+                       clocks = <&mmcc GPU_AHB_CLK>,
+                                <&gcc GCC_MMSS_BIMC_GFX_CLK>;
+                       clock-names = "iface", "bus";
+
+                       power-domains = <&mmcc GPU_GDSC>;
+
+                       status = "disabled";
+               };
+
+               mdp_smmu: arm,smmu@d00000 {
+                       compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
+                       reg = <0xd00000 0x10000>;
+
+                       #global-interrupts = <1>;
+                       interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH>;
+                       #iommu-cells = <1>;
+                       clocks = <&mmcc SMMU_MDP_AHB_CLK>,
+                                <&mmcc SMMU_MDP_AXI_CLK>;
+                       clock-names = "iface", "bus";
+
+                       power-domains = <&mmcc MDSS_GDSC>;
+
+                       status = "disabled";
+               };
+
+               lpass_q6_smmu: arm,smmu-lpass_q6@1600000 {
+                       compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
+                       reg = <0x1600000 0x20000>;
+                       #iommu-cells = <1>;
+                       power-domains = <&gcc HLOS1_VOTE_LPASS_CORE_GDSC>;
+
+                       #global-interrupts = <1>;
+                       interrupts = <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 394 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 395 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 396 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 397 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 398 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 399 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 401 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 403 IRQ_TYPE_LEVEL_HIGH>;
+
+                       clocks = <&gcc GCC_HLOS1_VOTE_LPASS_CORE_SMMU_CLK>,
+                                <&gcc GCC_HLOS1_VOTE_LPASS_ADSP_SMMU_CLK>;
+                       clock-names = "iface", "bus";
+                       status = "disabled";
+               };
+
                agnoc@0 {
                        power-domains = <&gcc AGGRE0_NOC_GDSC>;
                        compatible = "simple-pm-bus";
                                                "bus_slave";
                        };
                };
+
+               slimbam:dma@9184000
+               {
+                       compatible = "qcom,bam-v1.7.0";
+                       qcom,controlled-remotely;
+                       reg = <0x9184000 0x32000>;
+                       num-channels  = <31>;
+                       interrupts = <0 164 IRQ_TYPE_LEVEL_HIGH>;
+                       #dma-cells = <1>;
+                       qcom,ee = <1>;
+                       qcom,num-ees = <2>;
+               };
+
+               slim_msm: slim@91c0000 {
+                       compatible = "qcom,slim-ngd-v1.5.0";
+                       reg = <0x91c0000 0x2C000>;
+                       reg-names = "ctrl";
+                       interrupts = <0 163 IRQ_TYPE_LEVEL_HIGH>;
+                       dmas =  <&slimbam 3>, <&slimbam 4>,
+                               <&slimbam 5>, <&slimbam 6>;
+                       dma-names = "rx", "tx", "tx2", "rx2";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       ngd@1 {
+                               reg = <1>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+
+                               tasha_ifd: tas-ifd {
+                                       compatible = "slim217,1a0";
+                                       reg  = <0 0>;
+                               };
+
+                               wcd9335: codec@1{
+                                       pinctrl-0 = <&cdc_reset_active &wcd_intr_default>;
+                                       pinctrl-names = "default";
+
+                                       compatible = "slim217,1a0";
+                                       reg  = <1 0>;
+
+                                       interrupt-parent = <&msmgpio>;
+                                       interrupts = <54 IRQ_TYPE_LEVEL_HIGH>,
+                                                    <53 IRQ_TYPE_LEVEL_HIGH>;
+                                       interrupt-names  = "intr1", "intr2";
+                                       interrupt-controller;
+                                       #interrupt-cells = <1>;
+                                       reset-gpios = <&msmgpio 64 0>;
+
+                                       slim-ifc-dev  = <&tasha_ifd>;
+
+                                       vdd-buck-supply = <&pm8994_s4>;
+                                       vdd-buck-sido-supply = <&pm8994_s4>;
+                                       vdd-tx-supply = <&pm8994_s4>;
+                                       vdd-rx-supply = <&pm8994_s4>;
+                                       vdd-io-supply = <&pm8994_s4>;
+
+                                       #sound-dai-cells = <1>;
+                               };
+                       };
+               };
+
+               gpu@b00000 {
+                       compatible = "qcom,adreno-530.2", "qcom,adreno";
+                       #stream-id-cells = <16>;
+
+                       reg = <0xb00000 0x3f000>;
+                       reg-names = "kgsl_3d0_reg_memory";
+
+                       interrupts = <0 300 IRQ_TYPE_LEVEL_HIGH>;
+
+                       clocks = <&mmcc GPU_GX_GFX3D_CLK>,
+                               <&mmcc GPU_AHB_CLK>,
+                               <&mmcc GPU_GX_RBBMTIMER_CLK>,
+                               <&gcc GCC_BIMC_GFX_CLK>,
+                               <&gcc GCC_MMSS_BIMC_GFX_CLK>;
+
+                       clock-names = "core",
+                               "iface",
+                               "rbbmtimer",
+                               "mem",
+                               "mem_iface";
+
+                       power-domains = <&mmcc GPU_GDSC>;
+                       iommus = <&adreno_smmu 0>;
+
+                       nvmem-cells = <&gpu_speed_bin>;
+                       nvmem-cell-names = "speed_bin";
+
+                       qcom,gpu-quirk-two-pass-use-wfi;
+                       qcom,gpu-quirk-fault-detect-mask;
+
+                       operating-points-v2 = <&gpu_opp_table>;
+
+                       gpu_opp_table: opp-table {
+                               compatible  ="operating-points-v2";
+
+                               /*
+                                * 624Mhz and 560Mhz are only available on speed
+                                * bin (1 << 0). All the rest are available on
+                                * all bins of the hardware
+                                */
+                               opp-624000000 {
+                                       opp-hz = /bits/ 64 <624000000>;
+                                       opp-supported-hw = <0x01>;
+                               };
+                               opp-560000000 {
+                                       opp-hz = /bits/ 64 <560000000>;
+                                       opp-supported-hw = <0x01>;
+                               };
+                               opp-510000000 {
+                                       opp-hz = /bits/ 64 <510000000>;
+                                       opp-supported-hw = <0xFF>;
+                               };
+                               opp-401800000 {
+                                       opp-hz = /bits/ 64 <401800000>;
+                                       opp-supported-hw = <0xFF>;
+                               };
+                               opp-315000000 {
+                                       opp-hz = /bits/ 64 <315000000>;
+                                       opp-supported-hw = <0xFF>;
+                               };
+                               opp-214000000 {
+                                       opp-hz = /bits/ 64 <214000000>;
+                                       opp-supported-hw = <0xFF>;
+                               };
+                               opp-133000000 {
+                                       opp-hz = /bits/ 64 <133000000>;
+                                       opp-supported-hw = <0xFF>;
+                               };
+                       };
+
+                       zap-shader {
+                               memory-region = <&zap_shader_region>;
+                       };
+               };
+
+               mdss: mdss@900000 {
+                       compatible = "qcom,mdss";
+
+                       reg = <0x900000 0x1000>,
+                             <0x9b0000 0x1040>,
+                             <0x9b8000 0x1040>;
+                       reg-names = "mdss_phys",
+                                   "vbif_phys",
+                                   "vbif_nrt_phys";
+
+                       power-domains = <&mmcc MDSS_GDSC>;
+                       interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+
+                       clocks = <&mmcc MDSS_AHB_CLK>;
+                       clock-names = "iface_clk";
+
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       mdp: mdp@901000 {
+                               compatible = "qcom,mdp5";
+                               reg = <0x901000 0x90000>;
+                               reg-names = "mdp_phys";
+
+                               interrupt-parent = <&mdss>;
+                               interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+
+                               clocks = <&mmcc MDSS_AHB_CLK>,
+                                        <&mmcc MDSS_AXI_CLK>,
+                                        <&mmcc MDSS_MDP_CLK>,
+                                        <&mmcc SMMU_MDP_AXI_CLK>,
+                                        <&mmcc MDSS_VSYNC_CLK>;
+                               clock-names = "iface_clk",
+                                             "bus_clk",
+                                             "core_clk",
+                                             "iommu_clk",
+                                             "vsync_clk";
+
+                               iommus = <&mdp_smmu 0>;
+
+                               ports {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       port@0 {
+                                               reg = <0>;
+                                               mdp5_intf3_out: endpoint {
+                                                       remote-endpoint = <&hdmi_in>;
+                                               };
+                                       };
+                               };
+                       };
+
+                       hdmi: hdmi-tx@9a0000 {
+                               compatible = "qcom,hdmi-tx-8996";
+                               reg =   <0x009a0000 0x50c>,
+                                       <0x00070000 0x6158>,
+                                       <0x009e0000 0xfff>;
+                               reg-names = "core_physical",
+                                           "qfprom_physical",
+                                           "hdcp_physical";
+
+                               interrupt-parent = <&mdss>;
+                               interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+
+                               clocks = <&mmcc MDSS_MDP_CLK>,
+                                        <&mmcc MDSS_AHB_CLK>,
+                                        <&mmcc MDSS_HDMI_CLK>,
+                                        <&mmcc MDSS_HDMI_AHB_CLK>,
+                                        <&mmcc MDSS_EXTPCLK_CLK>;
+                               clock-names =
+                                       "mdp_core_clk",
+                                       "iface_clk",
+                                       "core_clk",
+                                       "alt_iface_clk",
+                                       "extp_clk";
+
+                               phys = <&hdmi_phy>;
+                               phy-names = "hdmi_phy";
+                               #sound-dai-cells = <1>;
+
+                               ports {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       port@0 {
+                                               reg = <0>;
+                                               hdmi_in: endpoint {
+                                                       remote-endpoint = <&mdp5_intf3_out>;
+                                               };
+                                       };
+                               };
+                       };
+
+                       hdmi_phy: hdmi-phy@9a0600 {
+                               #phy-cells = <0>;
+                               compatible = "qcom,hdmi-phy-8996";
+                               reg = <0x9a0600 0x1c4>,
+                                     <0x9a0a00 0x124>,
+                                     <0x9a0c00 0x124>,
+                                     <0x9a0e00 0x124>,
+                                     <0x9a1000 0x124>,
+                                     <0x9a1200 0x0c8>;
+                               reg-names = "hdmi_pll",
+                                           "hdmi_tx_l0",
+                                           "hdmi_tx_l1",
+                                           "hdmi_tx_l2",
+                                           "hdmi_tx_l3",
+                                           "hdmi_phy";
+
+                               clocks = <&mmcc MDSS_AHB_CLK>,
+                                        <&gcc GCC_HDMI_CLKREF_CLK>;
+                               clock-names = "iface_clk",
+                                             "ref_clk";
+                       };
+               };
+       };
+
+       sound: sound {
        };
 
        adsp-pil {
                        mboxes = <&apcs_glb 8>;
                        qcom,smd-edge = <1>;
                        qcom,remote-pid = <2>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       apr {
+                               power-domains = <&gcc HLOS1_VOTE_LPASS_ADSP_GDSC>;
+                               compatible = "qcom,apr-v2";
+                               qcom,smd-channels = "apr_audio_svc";
+                               reg = <APR_DOMAIN_ADSP>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               q6core {
+                                       reg = <APR_SVC_ADSP_CORE>;
+                                       compatible = "qcom,q6core";
+                               };
+
+                               q6afe: q6afe {
+                                       compatible = "qcom,q6afe";
+                                       reg = <APR_SVC_AFE>;
+                                       q6afedai: dais {
+                                               compatible = "qcom,q6afe-dais";
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                               #sound-dai-cells = <1>;
+                                               hdmi@1 {
+                                                       reg = <1>;
+                                               };
+                                       };
+                               };
+
+                               q6asm: q6asm {
+                                       compatible = "qcom,q6asm";
+                                       reg = <APR_SVC_ASM>;
+                                       q6asmdai: dais {
+                                               compatible = "qcom,q6asm-dais";
+                                               #sound-dai-cells = <1>;
+                                               iommus = <&lpass_q6_smmu 1>;
+                                       };
+                               };
+
+                               q6adm: q6adm {
+                                       compatible = "qcom,q6adm";
+                                       reg = <APR_SVC_ADM>;
+                                       q6routing: routing {
+                                               compatible = "qcom,q6adm-routing";
+                                               #sound-dai-cells = <0>;
+                                       };
+                               };
+                       };
+
                };
        };
 
index f090106..f09f3e0 100644 (file)
                stdout-path = "serial0:115200n8";
        };
 
-       thermal-zones {
-               battery-thermal {
-                       polling-delay-passive = <250>;
-                       polling-delay = <1000>;
-
-                       thermal-sensors = <&tsens0 0>;
-
-                       trips {
-                               battery_crit: trip0 {
-                                       temperature = <60000>;
-                                       hysteresis = <2000>;
-                                       type = "critical";
-                               };
-                       };
-               };
-
-               skin-thermal {
-                       polling-delay-passive = <250>;
-                       polling-delay = <1000>;
-
-                       thermal-sensors = <&tsens1 5>;
-
-                       trips {
-                               skin_alert: trip0 {
-                                       temperature = <44000>;
-                                       hysteresis = <2000>;
-                                       type = "passive";
-                               };
-
-                               skip_crit: trip1 {
-                                       temperature = <70000>;
-                                       hysteresis = <2000>;
-                                       type = "critical";
-                               };
-                       };
-               };
-       };
-
        vph_pwr: vph-pwr-regulator {
                compatible = "regulator-fixed";
                regulator-name = "vph_pwr";
                vreg_s4a_1p8: s4 {
                        regulator-min-microvolt = <1800000>;
                        regulator-max-microvolt = <1800000>;
+                       regulator-allow-set-load;
                };
                vreg_s5a_2p04: s5 {
                        regulator-min-microvolt = <1904000>;
                vreg_l20a_2p95: l20 {
                        regulator-min-microvolt = <2960000>;
                        regulator-max-microvolt = <2960000>;
+                       regulator-allow-set-load;
                };
                vreg_l21a_2p95: l21 {
                        regulator-min-microvolt = <2960000>;
                vreg_l26a_1p2: l26 {
                        regulator-min-microvolt = <1200000>;
                        regulator-max-microvolt = <1200000>;
+                       regulator-allow-set-load;
                };
                vreg_l28_3p0: l28 {
                        regulator-min-microvolt = <3008000>;
        pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
 };
 
+&ufshc {
+       vcc-supply = <&vreg_l20a_2p95>;
+       vccq-supply = <&vreg_l26a_1p2>;
+       vccq2-supply = <&vreg_s4a_1p8>;
+       vcc-max-microamp = <750000>;
+       vccq-max-microamp = <560000>;
+       vccq2-max-microamp = <750000>;
+};
+
+&ufsphy {
+       vdda-phy-supply = <&vreg_l1a_0p875>;
+       vdda-pll-supply = <&vreg_l2a_1p2>;
+       vddp-ref-clk-supply = <&vreg_l26a_1p2>;
+       vdda-phy-max-microamp = <51400>;
+       vdda-pll-max-microamp = <14600>;
+       vddp-ref-clk-max-microamp = <100>;
+       vddp-ref-clk-always-on;
+};
+
 &usb3 {
        status = "okay";
 };
index 3fd0769..574be78 100644 (file)
@@ -78,7 +78,6 @@
                        compatible = "arm,armv8";
                        reg = <0x0 0x0>;
                        enable-method = "psci";
-                       efficiency = <1024>;
                        next-level-cache = <&L2_0>;
                        L2_0: l2-cache {
                                compatible = "arm,arch-cache";
@@ -97,7 +96,6 @@
                        compatible = "arm,armv8";
                        reg = <0x0 0x1>;
                        enable-method = "psci";
-                       efficiency = <1024>;
                        next-level-cache = <&L2_0>;
                        L1_I_1: l1-icache {
                                compatible = "arm,arch-cache";
                        compatible = "arm,armv8";
                        reg = <0x0 0x2>;
                        enable-method = "psci";
-                       efficiency = <1024>;
                        next-level-cache = <&L2_0>;
                        L1_I_2: l1-icache {
                                compatible = "arm,arch-cache";
                        compatible = "arm,armv8";
                        reg = <0x0 0x3>;
                        enable-method = "psci";
-                       efficiency = <1024>;
                        next-level-cache = <&L2_0>;
                        L1_I_3: l1-icache {
                                compatible = "arm,arch-cache";
                        compatible = "arm,armv8";
                        reg = <0x0 0x100>;
                        enable-method = "psci";
-                       efficiency = <1536>;
                        next-level-cache = <&L2_1>;
                        L2_1: l2-cache {
                                compatible = "arm,arch-cache";
                        compatible = "arm,armv8";
                        reg = <0x0 0x101>;
                        enable-method = "psci";
-                       efficiency = <1536>;
                        next-level-cache = <&L2_1>;
                        L1_I_101: l1-icache {
                                compatible = "arm,arch-cache";
                        compatible = "arm,armv8";
                        reg = <0x0 0x102>;
                        enable-method = "psci";
-                       efficiency = <1536>;
                        next-level-cache = <&L2_1>;
                        L1_I_102: l1-icache {
                                compatible = "arm,arch-cache";
                        compatible = "arm,armv8";
                        reg = <0x0 0x103>;
                        enable-method = "psci";
-                       efficiency = <1536>;
                        next-level-cache = <&L2_1>;
                        L1_I_103: l1-icache {
                                compatible = "arm,arch-cache";
        };
 
        thermal-zones {
-               cpu-thermal0 {
+               cpu0-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
-                       thermal-sensors = <&tsens0 6>;
+                       thermal-sensors = <&tsens0 1>;
 
                        trips {
-                               cpu_alert0: trip0 {
+                               cpu0_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
 
-                               cpu_crit0: trip1 {
+                               cpu0_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
                        };
                };
 
-               cpu-thermal1 {
+               cpu1-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
-                       thermal-sensors = <&tsens0 7>;
+                       thermal-sensors = <&tsens0 2>;
 
                        trips {
-                               cpu_alert1: trip0 {
+                               cpu1_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
 
-                               cpu_crit1: trip1 {
+                               cpu1_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
                        };
                };
 
-               cpu-thermal2 {
+               cpu2-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
-                       thermal-sensors = <&tsens0 8>;
+                       thermal-sensors = <&tsens0 3>;
 
                        trips {
-                               cpu_alert2: trip0 {
+                               cpu2_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
 
-                               cpu_crit2: trip1 {
+                               cpu2_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
                        };
                };
 
-               cpu-thermal3 {
+               cpu3-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
-                       thermal-sensors = <&tsens0 9>;
+                       thermal-sensors = <&tsens0 4>;
 
                        trips {
-                               cpu_alert3: trip0 {
+                               cpu3_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
 
-                               cpu_crit3: trip1 {
+                               cpu3_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
                        };
                };
 
-               cpu-thermal4 {
+               cpu4-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
-                       thermal-sensors = <&tsens0 10>;
+                       thermal-sensors = <&tsens0 7>;
 
                        trips {
-                               cpu_alert4: trip0 {
+                               cpu4_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
 
-                               cpu_crit4: trip1 {
+                               cpu4_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
                        };
                };
 
-               cpu-thermal5 {
+               cpu5-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
-                       thermal-sensors = <&tsens0 11>;
+                       thermal-sensors = <&tsens0 8>;
 
                        trips {
-                               cpu_alert5: trip0 {
+                               cpu5_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
 
-                               cpu_crit5: trip1 {
+                               cpu5_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
                        };
                };
 
-               cpu-thermal6 {
+               cpu6-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
-                       thermal-sensors = <&tsens1 0>;
+                       thermal-sensors = <&tsens0 9>;
 
                        trips {
-                               cpu_alert6: trip0 {
+                               cpu6_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
 
-                               cpu_crit6: trip1 {
+                               cpu6_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
                        };
                };
 
-               cpu-thermal7 {
+               cpu7-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
-                       thermal-sensors = <&tsens1 1>;
+                       thermal-sensors = <&tsens0 10>;
 
                        trips {
-                               cpu_alert7: trip0 {
+                               cpu7_alert0: trip-point@0 {
                                        temperature = <75000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
 
-                               cpu_crit7: trip1 {
+                               cpu7_crit: cpu_crit {
                                        temperature = <110000>;
                                        hysteresis = <2000>;
                                        type = "critical";
                        };
                };
 
-               gpu-thermal {
+               gpu-thermal-bottom {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 12>;
+
+                       trips {
+                               gpu1_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               gpu-thermal-top {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 13>;
+
+                       trips {
+                               gpu2_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               clust0-mhm-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 5>;
+
+                       trips {
+                               cluster0_mhm_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               clust1-mhm-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 6>;
+
+                       trips {
+                               cluster1_mhm_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               cluster1-l2-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 11>;
+
+                       trips {
+                               cluster1_l2_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               modem-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 1>;
+
+                       trips {
+                               modem_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               mem-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 2>;
+
+                       trips {
+                               mem_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               wlan-thermal {
                        polling-delay-passive = <250>;
                        polling-delay = <1000>;
 
                        thermal-sensors = <&tsens1 3>;
+
+                       trips {
+                               wlan_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               q6-dsp-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 4>;
+
+                       trips {
+                               q6_dsp_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               camera-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 5>;
+
+                       trips {
+                               camera_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               multimedia-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 6>;
+
+                       trips {
+                               multimedia_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
                };
        };
 
                        cell-index = <0>;
                };
 
-               tsens0: thermal@10aa000 {
+               tsens0: thermal@10ab000 {
                        compatible = "qcom,msm8998-tsens", "qcom,tsens-v2";
-                       reg = <0x10aa000 0x2000>;
+                       reg = <0x10ab000 0x1000>, /* TM */
+                             <0x10aa000 0x1000>; /* SROT */
 
-                       #qcom,sensors = <12>;
+                       #qcom,sensors = <14>;
                        #thermal-sensor-cells = <1>;
                };
 
-               tsens1: thermal@10ad000 {
+               tsens1: thermal@10ae000 {
                        compatible = "qcom,msm8998-tsens", "qcom,tsens-v2";
-                       reg = <0x10ad000 0x2000>;
+                       reg = <0x10ae000 0x1000>, /* TM */
+                             <0x10ad000 0x1000>; /* SROT */
 
                        #qcom,sensors = <8>;
                        #thermal-sensor-cells = <1>;
 
                blsp2_i2c5: i2c@c1ba000 {
                        compatible = "qcom,i2c-qup-v2.2.1";
-                       reg = <0x0c175000 0x600>;
+                       reg = <0x0c1ba000 0x600>;
                        interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
 
                        clocks = <&gcc GCC_BLSP2_QUP6_I2C_APPS_CLK>,
                        redistributor-stride = <0x0 0x20000>;
                        interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
                };
+
+               ufshc: ufshc@1da4000 {
+                       compatible = "qcom,msm8998-ufshc", "qcom,ufshc", "jedec,ufs-2.0";
+                       reg = <0x01da4000 0x2500>;
+                       interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>;
+                       phys = <&ufsphy_lanes>;
+                       phy-names = "ufsphy";
+                       lanes-per-direction = <2>;
+                       power-domains = <&gcc UFS_GDSC>;
+                       #reset-cells = <1>;
+
+                       clock-names =
+                               "core_clk",
+                               "bus_aggr_clk",
+                               "iface_clk",
+                               "core_clk_unipro",
+                               "ref_clk",
+                               "tx_lane0_sync_clk",
+                               "rx_lane0_sync_clk",
+                               "rx_lane1_sync_clk";
+                       clocks =
+                               <&gcc GCC_UFS_AXI_CLK>,
+                               <&gcc GCC_AGGRE1_UFS_AXI_CLK>,
+                               <&gcc GCC_UFS_AHB_CLK>,
+                               <&gcc GCC_UFS_UNIPRO_CORE_CLK>,
+                               <&rpmcc RPM_SMD_LN_BB_CLK1>,
+                               <&gcc GCC_UFS_TX_SYMBOL_0_CLK>,
+                               <&gcc GCC_UFS_RX_SYMBOL_0_CLK>,
+                               <&gcc GCC_UFS_RX_SYMBOL_1_CLK>;
+                       freq-table-hz =
+                               <50000000 200000000>,
+                               <0 0>,
+                               <0 0>,
+                               <37500000 150000000>,
+                               <0 0>,
+                               <0 0>,
+                               <0 0>,
+                               <0 0>;
+
+                       resets = <&gcc GCC_UFS_BCR>;
+                       reset-names = "rst";
+               };
+
+               ufsphy: phy@1da7000 {
+                       compatible = "qcom,msm8998-qmp-ufs-phy";
+                       reg = <0x01da7000 0x18c>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       clock-names =
+                               "ref",
+                               "ref_aux";
+                       clocks =
+                               <&gcc GCC_UFS_CLKREF_CLK>,
+                               <&gcc GCC_UFS_PHY_AUX_CLK>;
+
+                       reset-names = "ufsphy";
+                       resets = <&ufshc 0>;
+
+                       ufsphy_lanes: lanes@1da7400 {
+                               reg = <0x01da7400 0x128>,
+                                     <0x01da7600 0x1fc>,
+                                     <0x01da7c00 0x1dc>,
+                                     <0x01da7800 0x128>,
+                                     <0x01da7a00 0x1fc>;
+                               #phy-cells = <0>;
+                       };
+               };
        };
 };
 
index c0ddf12..3f97607 100644 (file)
@@ -15,6 +15,7 @@
                        compatible = "qcom,pm8005-gpio", "qcom,spmi-gpio";
                        reg = <0xc000>;
                        gpio-controller;
+                       gpio-ranges = <&pm8005_gpio 0 0 4>;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
index 43cb5ea..d3ca35a 100644 (file)
@@ -58,6 +58,8 @@
                        compatible = "qcom,spmi-temp-alarm";
                        reg = <0x2400>;
                        interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_RISING>;
+                       io-channels = <&pm8998_adc ADC5_DIE_TEMP>;
+                       io-channel-names = "thermal";
                        #thermal-sensor-cells = <0>;
                };
 
@@ -93,6 +95,7 @@
                        compatible = "qcom,pm8998-gpio", "qcom,spmi-gpio";
                        reg = <0xc000>;
                        gpio-controller;
+                       gpio-ranges = <&pm8998_gpio 0 0 26>;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
index 3aee10e..21e0521 100644 (file)
@@ -14,6 +14,7 @@
                        compatible = "qcom,pmi8994-gpio", "qcom,spmi-gpio";
                        reg = <0xc000>;
                        gpio-controller;
+                       gpio-ranges = <&pmi8994_gpios 0 0 10>;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
index 051f57e..23f9146 100644 (file)
@@ -13,6 +13,7 @@
                        compatible = "qcom,pmi8998-gpio", "qcom,spmi-gpio";
                        reg = <0xc000>;
                        gpio-controller;
+                       gpio-ranges = <&pmi8998_gpio 0 0 14>;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
index 1bb836d..e8e186b 100644 (file)
                        interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>;
                };
        };
+
+       pms405_1: pms405@1 {
+               compatible = "qcom,spmi-pmic";
+               reg = <0x1 SPMI_USID>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               pms405_spmi_regulators: regulators {
+                       compatible = "qcom,pms405-regulators";
+               };
+       };
 };
index 2c14903..937eb45 100644 (file)
@@ -7,5 +7,6 @@
 
 / {
        model = "Qualcomm Technologies, Inc. QCS404 EVB 1000";
-       compatible = "qcom,qcs404-evb";
+       compatible = "qcom,qcs404-evb-1000", "qcom,qcs404-evb",
+                    "qcom,qcs404";
 };
index 11269ad..479ad3a 100644 (file)
@@ -3,9 +3,92 @@
 
 /dts-v1/;
 
+#include <dt-bindings/gpio/gpio.h>
 #include "qcs404-evb.dtsi"
 
 / {
        model = "Qualcomm Technologies, Inc. QCS404 EVB 4000";
-       compatible = "qcom,qcs404-evb";
+       compatible = "qcom,qcs404-evb-4000", "qcom,qcs404-evb",
+                    "qcom,qcs404";
+};
+
+&ethernet {
+       status = "ok";
+
+       snps,reset-gpio = <&tlmm 60 GPIO_ACTIVE_LOW>;
+       snps,reset-active-low;
+       snps,reset-delays-us = <0 10000 10000>;
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&ethernet_defaults>;
+
+       phy-handle = <&phy1>;
+       phy-mode = "rgmii";
+       mdio {
+               #address-cells = <0x1>;
+               #size-cells = <0x0>;
+               compatible = "snps,dwmac-mdio";
+               phy1: phy@4 {
+                       compatible = "ethernet-phy-ieee802.3-c22";
+                       device_type = "ethernet-phy";
+                       reg = <0x4>;
+               };
+       };
+};
+
+&tlmm {
+       ethernet_defaults: ethernet-defaults {
+               int {
+                       pins = "gpio61";
+                       function = "rgmii_int";
+                       bias-disable;
+                       drive-strength = <2>;
+               };
+               mdc {
+                       pins = "gpio76";
+                       function = "rgmii_mdc";
+                       bias-pull-up;
+               };
+               mdio {
+                       pins = "gpio75";
+                       function = "rgmii_mdio";
+                       bias-pull-up;
+               };
+               tx {
+                       pins = "gpio67", "gpio66", "gpio65", "gpio64";
+                       function = "rgmii_tx";
+                       bias-pull-up;
+                       drive-strength = <16>;
+               };
+               rx {
+                       pins = "gpio73", "gpio72", "gpio71", "gpio70";
+                       function = "rgmii_rx";
+                       bias-disable;
+                       drive-strength = <2>;
+               };
+               tx-ctl {
+                       pins = "gpio68";
+                       function = "rgmii_ctl";
+                       bias-pull-up;
+                       drive-strength = <16>;
+               };
+               rx-ctl {
+                       pins = "gpio74";
+                       function = "rgmii_ctl";
+                       bias-disable;
+                       drive-strength = <2>;
+               };
+               tx-ck {
+                       pins = "gpio63";
+                       function = "rgmii_ck";
+                       bias-pull-up;
+                       drive-strength = <16>;
+               };
+               rx-ck {
+                       pins = "gpio69";
+                       function = "rgmii_ck";
+                       bias-disable;
+                       drive-strength = <2>;
+               };
+       };
 };
index 50b3589..2c31271 100644 (file)
@@ -7,6 +7,7 @@
 / {
        aliases {
                serial0 = &blsp1_uart2;
+               serial1 = &blsp1_uart3;
        };
 
        chosen {
                regulator-always-on;
                regulator-boot-on;
        };
+
+       vdd_ch0_3p3:
+       vdd_esmps3_3p3: vdd-esmps3-3p3-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "eSMPS3_3P3";
+
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+};
+
+&blsp1_uart3 {
+       status = "okay";
+
+       bluetooth {
+               compatible = "qcom,wcn3990-bt";
+               vddio-supply = <&vreg_l6_1p8>;
+               vddxo-supply = <&vreg_l5_1p8>;
+               vddrf-supply = <&vreg_l1_1p3>;
+               vddch0-supply = <&vdd_ch0_3p3>;
+
+               local-bd-address = [ 02 00 00 00 5a ad ];
+
+               max-speed = <3200000>;
+       };
+};
+
+&blsp1_dma {
+       qcom,controlled-remotely;
+};
+
+&blsp2_dma {
+       qcom,controlled-remotely;
+};
+
+&pms405_spmi_regulators {
+       vdd_s3-supply = <&pms405_s3>;
+
+       pms405_s3: s3 {
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-name = "vdd_apc";
+               regulator-min-microvolt = <1048000>;
+               regulator-max-microvolt = <1352000>;
+       };
 };
 
 &remoteproc_adsp {
        pms405-regulators {
                compatible = "qcom,rpm-pms405-regulators";
 
-               vdd-s1-supply = <&vph_pwr>;
-               vdd-s2-supply = <&vph_pwr>;
-               vdd-s3-supply = <&vph_pwr>;
-               vdd-s4-supply = <&vph_pwr>;
-               vdd-s5-supply = <&vph_pwr>;
-               vdd-l1-l2-supply = <&vreg_s5_1p35>;
-               vdd-l3-l8-supply = <&vreg_s5_1p35>;
-               vdd-l4-supply = <&vreg_s5_1p35>;
-               vdd-l5-l6-supply = <&vreg_s4_1p8>;
-               vdd-l7-supply = <&vph_pwr>;
-               vdd-l9-supply = <&vreg_s5_1p35>;
-               vdd-l10-l11-l12-l13-supply = <&vph_pwr>;
+               vdd_s1-supply = <&vph_pwr>;
+               vdd_s2-supply = <&vph_pwr>;
+               vdd_s3-supply = <&vph_pwr>;
+               vdd_s4-supply = <&vph_pwr>;
+               vdd_s5-supply = <&vph_pwr>;
+               vdd_l1_l2-supply = <&vreg_s5_1p35>;
+               vdd_l3_l8-supply = <&vreg_s5_1p35>;
+               vdd_l4-supply = <&vreg_s5_1p35>;
+               vdd_l5_l6-supply = <&vreg_s4_1p8>;
+               vdd_l7-supply = <&vph_pwr>;
+               vdd_l9-supply = <&vreg_s5_1p35>;
+               vdd_l10_l11_l12_l13-supply = <&vph_pwr>;
 
                vreg_s4_1p8: s4 {
                        regulator-min-microvolt = <1728000>;
                };
 
                vreg_s5_1p35: s5 {
-                       regulator-min-microvolt = <>;
-                       regulator-max-microvolt = <>;
+                       regulator-min-microvolt = <1352000>;
+                       regulator-max-microvolt = <1352000>;
                };
 
                vreg_l1_1p3: l1 {
                };
 
                vreg_l3_1p05: l3 {
-                       regulator-min-microvolt = <976000>;
+                       regulator-min-microvolt = <1050000>;
                        regulator-max-microvolt = <1160000>;
                };
 
                bias-disable;
        };
 };
+
+&blsp1_uart3_default {
+       cts {
+               pins = "gpio84";
+               bias-disable;
+       };
+
+       rts-tx {
+               pins = "gpio85", "gpio82";
+               drive-strength = <2>;
+               bias-disable;
+       };
+
+       rx {
+               pins = "gpio83";
+               bias-pull-up;
+       };
+};
index e8fd266..ffedf96 100644 (file)
                        clocks = <&gcc GCC_BLSP1_AHB_CLK>;
                        clock-names = "bam_clk";
                        #dma-cells = <1>;
-                       qcom,controlled-remotely = <1>;
                        qcom,ee = <0>;
                        status = "okay";
                };
                        status = "okay";
                };
 
+               ethernet: ethernet@7a80000 {
+                       compatible = "qcom,qcs404-ethqos";
+                       reg = <0x07a80000 0x10000>,
+                               <0x07a96000 0x100>;
+                       reg-names = "stmmaceth", "rgmii";
+                       clock-names = "stmmaceth", "pclk", "ptp_ref", "rgmii";
+                       clocks = <&gcc GCC_ETH_AXI_CLK>,
+                               <&gcc GCC_ETH_SLAVE_AHB_CLK>,
+                               <&gcc GCC_ETH_PTP_CLK>,
+                               <&gcc GCC_ETH_RGMII_CLK>;
+                       interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "macirq", "eth_lpi";
+
+                       snps,tso;
+                       rx-fifo-depth = <4096>;
+                       tx-fifo-depth = <4096>;
+
+                       status = "disabled";
+               };
+
                wifi: wifi@a000000 {
                        compatible = "qcom,wcn3990-wifi";
                        reg = <0xa000000 0x800000>;
                        clocks = <&gcc GCC_BLSP2_AHB_CLK>;
                        clock-names = "bam_clk";
                        #dma-cells = <1>;
-                       qcom,controlled-remotely = <1>;
                        qcom,ee = <0>;
                        status = "disabled";
                };
index af8c6a2..02b8357 100644 (file)
        };
 };
 
+&adsp_pas {
+       status = "okay";
+};
+
 &apps_rsc {
        pm8998-rpmh-regulators {
                compatible = "qcom,pm8998-rpmh-regulators";
        };
 };
 
+&cdsp_pas {
+       status = "okay";
+};
+
 &gcc {
        protected-clocks = <GCC_QSPI_CORE_CLK>,
                           <GCC_QSPI_CORE_CLK_SRC>,
index 5308f16..fcb9330 100644 (file)
 #include <dt-bindings/clock/qcom,lpass-sdm845.h>
 #include <dt-bindings/clock/qcom,rpmh.h>
 #include <dt-bindings/clock/qcom,videocc-sdm845.h>
+#include <dt-bindings/interconnect/qcom,sdm845.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/phy/phy-qcom-qusb2.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
 #include <dt-bindings/reset/qcom,sdm845-aoss.h>
 #include <dt-bindings/reset/qcom,sdm845-pdc.h>
 #include <dt-bindings/soc/qcom,rpmh-rsc.h>
                #size-cells = <2>;
                ranges;
 
-               memory@85fc0000 {
+               hyp_mem: memory@85700000 {
+                       reg = <0 0x85700000 0 0x600000>;
+                       no-map;
+               };
+
+               xbl_mem: memory@85e00000 {
+                       reg = <0 0x85e00000 0 0x100000>;
+                       no-map;
+               };
+
+               aop_mem: memory@85fc0000 {
                        reg = <0 0x85fc0000 0 0x20000>;
                        no-map;
                };
 
-               memory@85fe0000 {
+               aop_cmd_db_mem: memory@85fe0000 {
                        compatible = "qcom,cmd-db";
-                       reg = <0x0 0x85fe0000 0x0 0x20000>;
+                       reg = <0x0 0x85fe0000 0 0x20000>;
                        no-map;
                };
 
                smem_mem: memory@86000000 {
-                       reg = <0x0 0x86000000 0x0 0x200000>;
+                       reg = <0x0 0x86000000 0 0x200000>;
                        no-map;
                };
 
-               memory@86200000 {
+               tz_mem: memory@86200000 {
                        reg = <0 0x86200000 0 0x2d00000>;
                        no-map;
                };
 
-               wlan_msa_mem: memory@96700000 {
-                       reg = <0 0x96700000 0 0x100000>;
+               rmtfs_mem: memory@88f00000 {
+                       compatible = "qcom,rmtfs-mem";
+                       reg = <0 0x88f00000 0 0x200000>;
+                       no-map;
+
+                       qcom,client-id = <1>;
+                       qcom,vmid = <15>;
+               };
+
+               qseecom_mem: memory@8ab00000 {
+                       reg = <0 0x8ab00000 0 0x1400000>;
+                       no-map;
+               };
+
+               camera_mem: memory@8bf00000 {
+                       reg = <0 0x8bf00000 0 0x500000>;
+                       no-map;
+               };
+
+               ipa_fw_mem: memory@8c400000 {
+                       reg = <0 0x8c400000 0 0x10000>;
+                       no-map;
+               };
+
+               ipa_gsi_mem: memory@8c410000 {
+                       reg = <0 0x8c410000 0 0x5000>;
+                       no-map;
+               };
+
+               gpu_mem: memory@8c415000 {
+                       reg = <0 0x8c415000 0 0x2000>;
+                       no-map;
+               };
+
+               adsp_mem: memory@8c500000 {
+                       reg = <0 0x8c500000 0 0x1a00000>;
+                       no-map;
+               };
+
+               wlan_msa_mem: memory@8df00000 {
+                       reg = <0 0x8df00000 0 0x100000>;
                        no-map;
                };
 
                        no-map;
                };
 
+               venus_mem: memory@95800000 {
+                       reg = <0 0x95800000 0 0x500000>;
+                       no-map;
+               };
+
+               cdsp_mem: memory@95d00000 {
+                       reg = <0 0x95d00000 0 0x800000>;
+                       no-map;
+               };
+
                mba_region: memory@96500000 {
                        reg = <0 0x96500000 0 0x200000>;
                        no-map;
                };
+
+               slpi_mem: memory@96700000 {
+                       reg = <0 0x96700000 0 0x1400000>;
+                       no-map;
+               };
+
+               spss_mem: memory@97b00000 {
+                       reg = <0 0x97b00000 0 0x100000>;
+                       no-map;
+               };
        };
 
        cpus {
                        compatible = "qcom,kryo385";
                        reg = <0x0 0x0>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <607>;
                        qcom,freq-domain = <&cpufreq_hw 0>;
                        #cooling-cells = <2>;
                        next-level-cache = <&L2_0>;
                        compatible = "qcom,kryo385";
                        reg = <0x0 0x100>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <607>;
                        qcom,freq-domain = <&cpufreq_hw 0>;
                        #cooling-cells = <2>;
                        next-level-cache = <&L2_100>;
                        compatible = "qcom,kryo385";
                        reg = <0x0 0x200>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <607>;
                        qcom,freq-domain = <&cpufreq_hw 0>;
                        #cooling-cells = <2>;
                        next-level-cache = <&L2_200>;
                        compatible = "qcom,kryo385";
                        reg = <0x0 0x300>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <607>;
                        qcom,freq-domain = <&cpufreq_hw 0>;
                        #cooling-cells = <2>;
                        next-level-cache = <&L2_300>;
                        compatible = "qcom,kryo385";
                        reg = <0x0 0x400>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <1024>;
                        qcom,freq-domain = <&cpufreq_hw 1>;
                        #cooling-cells = <2>;
                        next-level-cache = <&L2_400>;
                        compatible = "qcom,kryo385";
                        reg = <0x0 0x500>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <1024>;
                        qcom,freq-domain = <&cpufreq_hw 1>;
                        #cooling-cells = <2>;
                        next-level-cache = <&L2_500>;
                        compatible = "qcom,kryo385";
                        reg = <0x0 0x600>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <1024>;
                        qcom,freq-domain = <&cpufreq_hw 1>;
                        #cooling-cells = <2>;
                        next-level-cache = <&L2_600>;
                        compatible = "qcom,kryo385";
                        reg = <0x0 0x700>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <1024>;
                        qcom,freq-domain = <&cpufreq_hw 1>;
                        #cooling-cells = <2>;
                        next-level-cache = <&L2_700>;
                                next-level-cache = <&L3_0>;
                        };
                };
+
+               cpu-map {
+                       cluster0 {
+                               core0 {
+                                       cpu = <&CPU0>;
+                               };
+
+                               core1 {
+                                       cpu = <&CPU1>;
+                               };
+
+                               core2 {
+                                       cpu = <&CPU2>;
+                               };
+
+                               core3 {
+                                       cpu = <&CPU3>;
+                               };
+                       };
+
+                       cluster1 {
+                               core0 {
+                                       cpu = <&CPU4>;
+                               };
+
+                               core1 {
+                                       cpu = <&CPU5>;
+                               };
+
+                               core2 {
+                                       cpu = <&CPU6>;
+                               };
+
+                               core3 {
+                                       cpu = <&CPU7>;
+                               };
+                       };
+               };
        };
 
        pmu {
                };
        };
 
+       adsp_pas: remoteproc-adsp {
+               compatible = "qcom,sdm845-adsp-pas";
+
+               interrupts-extended = <&intc GIC_SPI 162 IRQ_TYPE_EDGE_RISING>,
+                                     <&adsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
+                                     <&adsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
+                                     <&adsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
+                                     <&adsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>;
+               interrupt-names = "wdog", "fatal", "ready",
+                                 "handover", "stop-ack";
+
+               clocks = <&rpmhcc RPMH_CXO_CLK>;
+               clock-names = "xo";
+
+               memory-region = <&adsp_mem>;
+
+               qcom,smem-states = <&adsp_smp2p_out 0>;
+               qcom,smem-state-names = "stop";
+
+               status = "disabled";
+
+               glink-edge {
+                       interrupts = <GIC_SPI 156 IRQ_TYPE_EDGE_RISING>;
+                       label = "lpass";
+                       qcom,remote-pid = <2>;
+                       mboxes = <&apss_shared 8>;
+               };
+       };
+
+       cdsp_pas: remoteproc-cdsp {
+               compatible = "qcom,sdm845-cdsp-pas";
+
+               interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
+                                     <&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
+                                     <&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
+                                     <&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
+                                     <&cdsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>;
+               interrupt-names = "wdog", "fatal", "ready",
+                                 "handover", "stop-ack";
+
+               clocks = <&rpmhcc RPMH_CXO_CLK>;
+               clock-names = "xo";
+
+               memory-region = <&cdsp_mem>;
+
+               qcom,smem-states = <&cdsp_smp2p_out 0>;
+               qcom,smem-state-names = "stop";
+
+               status = "disabled";
+
+               glink-edge {
+                       interrupts = <GIC_SPI 574 IRQ_TYPE_EDGE_RISING>;
+                       label = "turing";
+                       qcom,remote-pid = <5>;
+                       mboxes = <&apss_shared 4>;
+               };
+       };
+
        tcsr_mutex: hwlock {
                compatible = "qcom,tcsr-mutex";
                syscon = <&tcsr_mutex_regs 0 0x1000>;
                        phy-names = "ufsphy";
                        lanes-per-direction = <2>;
                        power-domains = <&gcc UFS_PHY_GDSC>;
+                       #reset-cells = <1>;
 
                        iommus = <&apps_smmu 0x100 0xf>;
 
                        clocks = <&gcc GCC_UFS_MEM_CLKREF_CLK>,
                                 <&gcc GCC_UFS_PHY_PHY_AUX_CLK>;
 
+                       resets = <&ufs_mem_hc 0>;
+                       reset-names = "ufsphy";
                        status = "disabled";
 
                        ufs_mem_phy_lanes: lanes@1d87400 {
                                #clock-cells = <1>;
                                #phy-cells = <0>;
 
-                               clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>;
-                               clock-names = "iface";
+                               clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+                                        <&rpmhcc RPMH_CXO_CLK>;
+                               clock-names = "iface", "ref";
 
                                status = "disabled";
                        };
                                #clock-cells = <1>;
                                #phy-cells = <0>;
 
-                               clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>;
-                               clock-names = "iface";
+                               clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+                                        <&rpmhcc RPMH_CXO_CLK>;
+                               clock-names = "iface", "ref";
 
                                status = "disabled";
                        };
                                        compatible = "operating-points-v2";
 
                                        rpmhpd_opp_ret: opp1 {
-                                               opp-level = <16>;
+                                               opp-level = <RPMH_REGULATOR_LEVEL_RETENTION>;
                                        };
 
                                        rpmhpd_opp_min_svs: opp2 {
-                                               opp-level = <48>;
+                                               opp-level = <RPMH_REGULATOR_LEVEL_MIN_SVS>;
                                        };
 
                                        rpmhpd_opp_low_svs: opp3 {
-                                               opp-level = <64>;
+                                               opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
                                        };
 
                                        rpmhpd_opp_svs: opp4 {
-                                               opp-level = <128>;
+                                               opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
                                        };
 
                                        rpmhpd_opp_svs_l1: opp5 {
-                                               opp-level = <192>;
+                                               opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
                                        };
 
                                        rpmhpd_opp_nom: opp6 {
-                                               opp-level = <256>;
+                                               opp-level = <RPMH_REGULATOR_LEVEL_NOM>;
                                        };
 
                                        rpmhpd_opp_nom_l1: opp7 {
-                                               opp-level = <320>;
+                                               opp-level = <RPMH_REGULATOR_LEVEL_NOM_L1>;
                                        };
 
                                        rpmhpd_opp_nom_l2: opp8 {
-                                               opp-level = <336>;
+                                               opp-level = <RPMH_REGULATOR_LEVEL_NOM_L2>;
                                        };
 
                                        rpmhpd_opp_turbo: opp9 {
-                                               opp-level = <384>;
+                                               opp-level = <RPMH_REGULATOR_LEVEL_TURBO>;
                                        };
 
                                        rpmhpd_opp_turbo_l1: opp10 {
-                                               opp-level = <416>;
+                                               opp-level = <RPMH_REGULATOR_LEVEL_TURBO_L1>;
                                        };
                                };
                        };
                                };
                        };
                };
+
+               aoss0-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 0>;
+
+                       trips {
+                               aoss0_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               cluster0-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 5>;
+
+                       trips {
+                               cluster0_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                               cluster0_crit: cluster0_crit {
+                                       temperature = <110000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
+               };
+
+               cluster1-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 6>;
+
+                       trips {
+                               cluster1_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                               cluster1_crit: cluster1_crit {
+                                       temperature = <110000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
+               };
+
+               gpu-thermal-top {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 11>;
+
+                       trips {
+                               gpu1_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               gpu-thermal-bottom {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens0 12>;
+
+                       trips {
+                               gpu2_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               aoss1-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 0>;
+
+                       trips {
+                               aoss1_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               q6-modem-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 1>;
+
+                       trips {
+                               q6_modem_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               mem-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 2>;
+
+                       trips {
+                               mem_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               wlan-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 3>;
+
+                       trips {
+                               wlan_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               q6-hvx-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 4>;
+
+                       trips {
+                               q6_hvx_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               camera-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 5>;
+
+                       trips {
+                               camera_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               video-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 6>;
+
+                       trips {
+                               video_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
+
+               modem-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+
+                       thermal-sensors = <&tsens1 7>;
+
+                       trips {
+                               modem_alert0: trip-point@0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+                       };
+               };
        };
 };
index 14db667..aaefc3a 100644 (file)
        };
 };
 
+&can0 {
+       pinctrl-0 = <&can0_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+};
+
+&can1 {
+       pinctrl-0 = <&can1_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+};
+
 &pciec0 {
        status = "okay";
 };
                        function = "avb";
                };
        };
+
+       can0_pins: can0 {
+               groups = "can0_data";
+               function = "can0";
+       };
+
+       can1_pins: can1 {
+               groups = "can1_data";
+               function = "can1";
+       };
 };
index ef3cff2..de282c4 100644 (file)
                                     "renesas,rcar-gen3-can";
                        reg = <0 0xe6c30000 0 0x1000>;
                        interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&cpg CPG_MOD 916>, <&can_clk>;
-                       clock-names = "clkp1", "can_clk";
+                       clocks = <&cpg CPG_MOD 916>,
+                                <&cpg CPG_CORE R8A774A1_CLK_CANFD>,
+                                <&can_clk>;
+                       clock-names = "clkp1", "clkp2", "can_clk";
                        power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
                        resets = <&cpg 916>;
                        status = "disabled";
                                     "renesas,rcar-gen3-can";
                        reg = <0 0xe6c38000 0 0x1000>;
                        interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&cpg CPG_MOD 915>, <&can_clk>;
-                       clock-names = "clkp1", "can_clk";
+                       clocks = <&cpg CPG_MOD 915>,
+                                <&cpg CPG_CORE R8A774A1_CLK_CANFD>,
+                                <&can_clk>;
+                       clock-names = "clkp1", "clkp2", "can_clk";
                        power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
                        resets = <&cpg 915>;
                        status = "disabled";
index 96ee0d2..013a48c 100644 (file)
                stdout-path = "serial0:115200n8";
        };
 
+       leds {
+               compatible = "gpio-leds";
+
+               led0 {
+                       gpios = <&gpio5 19 GPIO_ACTIVE_HIGH>;
+                       label = "LED0";
+               };
+
+               led1 {
+                       gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>;
+                       label = "LED1";
+               };
+
+               led2 {
+                       gpios = <&gpio4 10 GPIO_ACTIVE_HIGH>;
+                       label = "LED2";
+               };
+
+               led3 {
+                       gpios = <&gpio6 4 GPIO_ACTIVE_HIGH>;
+                       label = "LED3";
+               };
+       };
+
        memory@48000000 {
                device_type = "memory";
                /* first 128MB is reserved for secure area. */
        };
 };
 
+&ehci0 {
+       dr_mode = "host";
+       status = "okay";
+};
+
 &extal_clk {
        clock-frequency = <48000000>;
 };
 
+&i2c1 {
+       pinctrl-0 = <&i2c1_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
+       clock-frequency = <400000>;
+
+       rtc@32 {
+               compatible = "epson,rx8571";
+               reg = <0x32>;
+       };
+};
+
+&ohci0 {
+       dr_mode = "host";
+       status = "okay";
+};
+
 &pcie_bus_clk {
        clock-frequency = <100000000>;
 };
 };
 
 &pfc {
+       i2c1_pins: i2c1 {
+               groups = "i2c1_b";
+               function = "i2c1";
+       };
+
        scif2_pins: scif2 {
                groups = "scif2_data_a";
                function = "scif2";
        };
 };
 
+&rwdt {
+       timeout-sec = <60>;
+       status = "okay";
+};
+
 &scif2 {
        pinctrl-0 = <&scif2_pins>;
        pinctrl-names = "default";
        sd-uhs-sdr104;
        status = "okay";
 };
+
+&usb2_phy0 {
+       renesas,no-otg-pins;
+       status = "okay";
+};
index 1ea684a..3f86db1 100644 (file)
@@ -76,7 +76,7 @@
                        power-domains = <&sysc R8A774C0_PD_CA53_CPU0>;
                        next-level-cache = <&L2_CA53>;
                        enable-method = "psci";
-                       clocks =<&cpg CPG_CORE R8A774C0_CLK_Z2>;
+                       clocks = <&cpg CPG_CORE R8A774C0_CLK_Z2>;
                        operating-points-v2 = <&cluster1_opp>;
                };
 
@@ -87,7 +87,7 @@
                        power-domains = <&sysc R8A774C0_PD_CA53_CPU1>;
                        next-level-cache = <&L2_CA53>;
                        enable-method = "psci";
-                       clocks =<&cpg CPG_CORE R8A774C0_CLK_Z2>;
+                       clocks = <&cpg CPG_CORE R8A774C0_CLK_Z2>;
                        operating-points-v2 = <&cluster1_opp>;
                };
 
                                     "renesas,rcar-gen3-can";
                        reg = <0 0xe6c30000 0 0x1000>;
                        interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&cpg CPG_MOD 916>, <&can_clk>;
-                       clock-names = "clkp1", "can_clk";
+                       clocks = <&cpg CPG_MOD 916>,
+                                <&cpg CPG_CORE R8A774C0_CLK_CANFD>,
+                                <&can_clk>;
+                       clock-names = "clkp1", "clkp2", "can_clk";
                        power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
                        resets = <&cpg 916>;
                        status = "disabled";
                                     "renesas,rcar-gen3-can";
                        reg = <0 0xe6c38000 0 0x1000>;
                        interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&cpg CPG_MOD 915>, <&can_clk>;
-                       clock-names = "clkp1", "can_clk";
+                       clocks = <&cpg CPG_MOD 915>,
+                                <&cpg CPG_CORE R8A774C0_CLK_CANFD>,
+                                <&can_clk>;
+                       clock-names = "clkp1", "clkp2", "can_clk";
                        power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
                        resets = <&cpg 915>;
                        status = "disabled";
                };
 
+               canfd: can@e66c0000 {
+                       compatible = "renesas,r8a774c0-canfd",
+                                    "renesas,rcar-gen3-canfd";
+                       reg = <0 0xe66c0000 0 0x8000>;
+                       interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 914>,
+                                <&cpg CPG_CORE R8A774C0_CLK_CANFD>,
+                                <&can_clk>;
+                       clock-names = "fck", "canfd", "can_clk";
+                       assigned-clocks = <&cpg CPG_CORE R8A774C0_CLK_CANFD>;
+                       assigned-clock-rates = <40000000>;
+                       power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
+                       resets = <&cpg 914>;
+                       status = "disabled";
+
+                       channel0 {
+                               status = "disabled";
+                       };
+
+                       channel1 {
+                               status = "disabled";
+                       };
+               };
+
                pwm0: pwm@e6e30000 {
                        compatible = "renesas,pwm-r8a774c0", "renesas,pwm-rcar";
                        reg = <0 0xe6e30000 0 0x8>;
                };
 
                csi40: csi2@feaa0000 {
-                       compatible = "renesas,r8a774c0-csi2",
-                                    "renesas,rcar-gen3-csi2";
+                       compatible = "renesas,r8a774c0-csi2";
                        reg = <0 0xfeaa0000 0 0x10000>;
                        interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 716>;
index abeac30..097538c 100644 (file)
                        reg = <0 0xe6060000 0 0x50c>;
                };
 
+               cmt0: timer@e60f0000 {
+                       compatible = "renesas,r8a7795-cmt0",
+                                    "renesas,rcar-gen3-cmt0";
+                       reg = <0 0xe60f0000 0 0x1004>;
+                       interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 303>;
+                       clock-names = "fck";
+                       power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 303>;
+                       status = "disabled";
+               };
+
+               cmt1: timer@e6130000 {
+                       compatible = "renesas,r8a7795-cmt1",
+                                    "renesas,rcar-gen3-cmt1";
+                       reg = <0 0xe6130000 0 0x1004>;
+                       interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 302>;
+                       clock-names = "fck";
+                       power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 302>;
+                       status = "disabled";
+               };
+
+               cmt2: timer@e6140000 {
+                       compatible = "renesas,r8a7795-cmt1",
+                                    "renesas,rcar-gen3-cmt1";
+                       reg = <0 0xe6140000 0 0x1004>;
+                       interrupts = <GIC_SPI 398 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 399 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 401 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 403 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 405 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 301>;
+                       clock-names = "fck";
+                       power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 301>;
+                       status = "disabled";
+               };
+
+               cmt3: timer@e6148000 {
+                       compatible = "renesas,r8a7795-cmt1",
+                                    "renesas,rcar-gen3-cmt1";
+                       reg = <0 0xe6148000 0 0x1004>;
+                       interrupts = <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 471 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 476 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 477 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 300>;
+                       clock-names = "fck";
+                       power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 300>;
+                       status = "disabled";
+               };
+
                cpg: clock-controller@e6150000 {
                        compatible = "renesas,r8a7795-cpg-mssr";
                        reg = <0 0xe6150000 0 0x1000>;
                                <0 0xec5a0000 0 0x100>,  /* ADG */
                                <0 0xec540000 0 0x1000>, /* SSIU */
                                <0 0xec541000 0 0x280>,  /* SSI */
-                               <0 0xec740000 0 0x200>;  /* Audio DMAC peri peri*/
+                               <0 0xec760000 0 0x200>;  /* Audio DMAC peri peri*/
                        reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
 
                        clocks = <&cpg CPG_MOD 1005>,
index b4f9567..2aefa53 100644 (file)
@@ -68,6 +68,7 @@
        ports {
                /* rsnd_port0 is on salvator-common */
                rsnd_port1: port@1 {
+                       reg = <1>;
                        rsnd_endpoint1: endpoint {
                                remote-endpoint = <&dw_hdmi0_snd_in>;
 
index 31f1205..d58ede1 100644 (file)
@@ -68,6 +68,7 @@
        ports {
                /* rsnd_port0 is on salvator-common */
                rsnd_port1: port@1 {
+                       reg = <1>;
                        rsnd_endpoint1: endpoint {
                                remote-endpoint = <&dw_hdmi0_snd_in>;
 
index cdf7848..d5e2f4a 100644 (file)
                                <0 0xec5a0000 0 0x100>,  /* ADG */
                                <0 0xec540000 0 0x1000>, /* SSIU */
                                <0 0xec541000 0 0x280>,  /* SSI */
-                               <0 0xec740000 0 0x200>;  /* Audio DMAC peri peri*/
+                               <0 0xec760000 0 0x200>;  /* Audio DMAC peri peri*/
                        reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
 
                        clocks = <&cpg CPG_MOD 1005>,
                                        dma-names = "rx", "tx";
                                };
                        };
-
-                       ports {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               port@0 {
-                                       reg = <0>;
-                               };
-                               port@1 {
-                                       reg = <1>;
-                               };
-                       };
                };
 
                audma0: dma-controller@ec700000 {
index 9763d10..2554b17 100644 (file)
                        reg = <0 0xe6060000 0 0x50c>;
                };
 
+               cmt0: timer@e60f0000 {
+                       compatible = "renesas,r8a77965-cmt0",
+                                    "renesas,rcar-gen3-cmt0";
+                       reg = <0 0xe60f0000 0 0x1004>;
+                       interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 303>;
+                       clock-names = "fck";
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       resets = <&cpg 303>;
+                       status = "disabled";
+               };
+
+               cmt1: timer@e6130000 {
+                       compatible = "renesas,r8a77965-cmt1",
+                                    "renesas,rcar-gen3-cmt1";
+                       reg = <0 0xe6130000 0 0x1004>;
+                       interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 302>;
+                       clock-names = "fck";
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       resets = <&cpg 302>;
+                       status = "disabled";
+               };
+
+               cmt2: timer@e6140000 {
+                       compatible = "renesas,r8a77965-cmt1",
+                                    "renesas,rcar-gen3-cmt1";
+                       reg = <0 0xe6140000 0 0x1004>;
+                       interrupts = <GIC_SPI 398 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 399 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 401 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 403 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 405 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 301>;
+                       clock-names = "fck";
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       resets = <&cpg 301>;
+                       status = "disabled";
+               };
+
+               cmt3: timer@e6148000 {
+                       compatible = "renesas,r8a77965-cmt1",
+                                    "renesas,rcar-gen3-cmt1";
+                       reg = <0 0xe6148000 0 0x1004>;
+                       interrupts = <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 471 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 476 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 477 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 300>;
+                       clock-names = "fck";
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       resets = <&cpg 300>;
+                       status = "disabled";
+               };
+
                cpg: clock-controller@e6150000 {
                        compatible = "renesas,r8a77965-cpg-mssr";
                        reg = <0 0xe6150000 0 0x1000>;
                                <0 0xec5a0000 0 0x100>,  /* ADG */
                                <0 0xec540000 0 0x1000>, /* SSIU */
                                <0 0xec541000 0 0x280>,  /* SSI */
-                               <0 0xec740000 0 0x200>;  /* Audio DMAC peri peri*/
+                               <0 0xec760000 0 0x200>;  /* Audio DMAC peri peri*/
                        reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
 
                        clocks = <&cpg CPG_MOD 1005>,
                                };
                        };
 
+                       rcar_sound,ssiu {
+                               ssiu00: ssiu-0 {
+                                       dmas = <&audma0 0x15>, <&audma1 0x16>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu01: ssiu-1 {
+                                       dmas = <&audma0 0x35>, <&audma1 0x36>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu02: ssiu-2 {
+                                       dmas = <&audma0 0x37>, <&audma1 0x38>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu03: ssiu-3 {
+                                       dmas = <&audma0 0x47>, <&audma1 0x48>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu04: ssiu-4 {
+                                       dmas = <&audma0 0x3F>, <&audma1 0x40>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu05: ssiu-5 {
+                                       dmas = <&audma0 0x43>, <&audma1 0x44>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu06: ssiu-6 {
+                                       dmas = <&audma0 0x4F>, <&audma1 0x50>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu07: ssiu-7 {
+                                       dmas = <&audma0 0x53>, <&audma1 0x54>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu10: ssiu-8 {
+                                       dmas = <&audma0 0x49>, <&audma1 0x4a>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu11: ssiu-9 {
+                                       dmas = <&audma0 0x4B>, <&audma1 0x4C>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu12: ssiu-10 {
+                                       dmas = <&audma0 0x57>, <&audma1 0x58>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu13: ssiu-11 {
+                                       dmas = <&audma0 0x59>, <&audma1 0x5A>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu14: ssiu-12 {
+                                       dmas = <&audma0 0x5F>, <&audma1 0x60>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu15: ssiu-13 {
+                                       dmas = <&audma0 0xC3>, <&audma1 0xC4>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu16: ssiu-14 {
+                                       dmas = <&audma0 0xC7>, <&audma1 0xC8>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu17: ssiu-15 {
+                                       dmas = <&audma0 0xCB>, <&audma1 0xCC>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu20: ssiu-16 {
+                                       dmas = <&audma0 0x63>, <&audma1 0x64>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu21: ssiu-17 {
+                                       dmas = <&audma0 0x67>, <&audma1 0x68>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu22: ssiu-18 {
+                                       dmas = <&audma0 0x6B>, <&audma1 0x6C>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu23: ssiu-19 {
+                                       dmas = <&audma0 0x6D>, <&audma1 0x6E>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu24: ssiu-20 {
+                                       dmas = <&audma0 0xCF>, <&audma1 0xCE>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu25: ssiu-21 {
+                                       dmas = <&audma0 0xEB>, <&audma1 0xEC>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu26: ssiu-22 {
+                                       dmas = <&audma0 0xED>, <&audma1 0xEE>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu27: ssiu-23 {
+                                       dmas = <&audma0 0xEF>, <&audma1 0xF0>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu30: ssiu-24 {
+                                       dmas = <&audma0 0x6f>, <&audma1 0x70>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu31: ssiu-25 {
+                                       dmas = <&audma0 0x21>, <&audma1 0x22>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu32: ssiu-26 {
+                                       dmas = <&audma0 0x23>, <&audma1 0x24>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu33: ssiu-27 {
+                                       dmas = <&audma0 0x25>, <&audma1 0x26>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu34: ssiu-28 {
+                                       dmas = <&audma0 0x27>, <&audma1 0x28>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu35: ssiu-29 {
+                                       dmas = <&audma0 0x29>, <&audma1 0x2A>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu36: ssiu-30 {
+                                       dmas = <&audma0 0x2B>, <&audma1 0x2C>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu37: ssiu-31 {
+                                       dmas = <&audma0 0x2D>, <&audma1 0x2E>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu40: ssiu-32 {
+                                       dmas =  <&audma0 0x71>, <&audma1 0x72>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu41: ssiu-33 {
+                                       dmas = <&audma0 0x17>, <&audma1 0x18>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu42: ssiu-34 {
+                                       dmas = <&audma0 0x19>, <&audma1 0x1A>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu43: ssiu-35 {
+                                       dmas = <&audma0 0x1B>, <&audma1 0x1C>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu44: ssiu-36 {
+                                       dmas = <&audma0 0x1D>, <&audma1 0x1E>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu45: ssiu-37 {
+                                       dmas = <&audma0 0x1F>, <&audma1 0x20>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu46: ssiu-38 {
+                                       dmas = <&audma0 0x31>, <&audma1 0x32>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu47: ssiu-39 {
+                                       dmas = <&audma0 0x33>, <&audma1 0x34>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu50: ssiu-40 {
+                                       dmas = <&audma0 0x73>, <&audma1 0x74>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu60: ssiu-41 {
+                                       dmas = <&audma0 0x75>, <&audma1 0x76>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu70: ssiu-42 {
+                                       dmas = <&audma0 0x79>, <&audma1 0x7a>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu80: ssiu-43 {
+                                       dmas = <&audma0 0x7b>, <&audma1 0x7c>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu90: ssiu-44 {
+                                       dmas = <&audma0 0x7d>, <&audma1 0x7e>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu91: ssiu-45 {
+                                       dmas = <&audma0 0x7F>, <&audma1 0x80>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu92: ssiu-46 {
+                                       dmas = <&audma0 0x81>, <&audma1 0x82>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu93: ssiu-47 {
+                                       dmas = <&audma0 0x83>, <&audma1 0x84>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu94: ssiu-48 {
+                                       dmas = <&audma0 0xA3>, <&audma1 0xA4>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu95: ssiu-49 {
+                                       dmas = <&audma0 0xA5>, <&audma1 0xA6>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu96: ssiu-50 {
+                                       dmas = <&audma0 0xA7>, <&audma1 0xA8>;
+                                       dma-names = "rx", "tx";
+                               };
+                               ssiu97: ssiu-51 {
+                                       dmas = <&audma0 0xA9>, <&audma1 0xAA>;
+                                       dma-names = "rx", "tx";
+                               };
+                       };
+
                        rcar_sound,ssi {
                                ssi0: ssi-0 {
                                        interrupts = <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>;
-                                       dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>;
-                                       dma-names = "rx", "tx", "rxu", "txu";
+                                       dmas = <&audma0 0x01>, <&audma1 0x02>;
+                                       dma-names = "rx", "tx";
                                };
                                ssi1: ssi-1 {
                                        interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
-                                       dmas = <&audma0 0x03>, <&audma1 0x04>, <&audma0 0x49>, <&audma1 0x4a>;
-                                       dma-names = "rx", "tx", "rxu", "txu";
+                                       dmas = <&audma0 0x03>, <&audma1 0x04>;
+                                       dma-names = "rx", "tx";
                                };
                                ssi2: ssi-2 {
                                        interrupts = <GIC_SPI 372 IRQ_TYPE_LEVEL_HIGH>;
-                                       dmas = <&audma0 0x05>, <&audma1 0x06>, <&audma0 0x63>, <&audma1 0x64>;
-                                       dma-names = "rx", "tx", "rxu", "txu";
+                                       dmas = <&audma0 0x05>, <&audma1 0x06>;
+                                       dma-names = "rx", "tx";
                                };
                                ssi3: ssi-3 {
                                        interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
-                                       dmas = <&audma0 0x07>, <&audma1 0x08>, <&audma0 0x6f>, <&audma1 0x70>;
-                                       dma-names = "rx", "tx", "rxu", "txu";
+                                       dmas = <&audma0 0x07>, <&audma1 0x08>;
+                                       dma-names = "rx", "tx";
                                };
                                ssi4: ssi-4 {
                                        interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>;
-                                       dmas = <&audma0 0x09>, <&audma1 0x0a>, <&audma0 0x71>, <&audma1 0x72>;
-                                       dma-names = "rx", "tx", "rxu", "txu";
+                                       dmas = <&audma0 0x09>, <&audma1 0x0a>;
+                                       dma-names = "rx", "tx";
                                };
                                ssi5: ssi-5 {
                                        interrupts = <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>;
-                                       dmas = <&audma0 0x0b>, <&audma1 0x0c>, <&audma0 0x73>, <&audma1 0x74>;
-                                       dma-names = "rx", "tx", "rxu", "txu";
+                                       dmas = <&audma0 0x0b>, <&audma1 0x0c>;
+                                       dma-names = "rx", "tx";
                                };
                                ssi6: ssi-6 {
                                        interrupts = <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>;
-                                       dmas = <&audma0 0x0d>, <&audma1 0x0e>, <&audma0 0x75>, <&audma1 0x76>;
-                                       dma-names = "rx", "tx", "rxu", "txu";
+                                       dmas = <&audma0 0x0d>, <&audma1 0x0e>;
+                                       dma-names = "rx", "tx";
                                };
                                ssi7: ssi-7 {
                                        interrupts = <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>;
-                                       dmas = <&audma0 0x0f>, <&audma1 0x10>, <&audma0 0x79>, <&audma1 0x7a>;
-                                       dma-names = "rx", "tx", "rxu", "txu";
+                                       dmas = <&audma0 0x0f>, <&audma1 0x10>;
+                                       dma-names = "rx", "tx";
                                };
                                ssi8: ssi-8 {
                                        interrupts = <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>;
-                                       dmas = <&audma0 0x11>, <&audma1 0x12>, <&audma0 0x7b>, <&audma1 0x7c>;
-                                       dma-names = "rx", "tx", "rxu", "txu";
+                                       dmas = <&audma0 0x11>, <&audma1 0x12>;
+                                       dma-names = "rx", "tx";
                                };
                                ssi9: ssi-9 {
                                        interrupts = <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>;
-                                       dmas = <&audma0 0x13>, <&audma1 0x14>, <&audma0 0x7d>, <&audma1 0x7e>;
-                                       dma-names = "rx", "tx", "rxu", "txu";
+                                       dmas = <&audma0 0x13>, <&audma1 0x14>;
+                                       dma-names = "rx", "tx";
                                };
                        };
                };
                du: display@feb00000 {
                        compatible = "renesas,du-r8a77965";
                        reg = <0 0xfeb00000 0 0x80000>;
-                       reg-names = "du";
                        interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
index 4081622..a901a34 100644 (file)
                        clocks = <&cpg CPG_MOD 811>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 811>;
+                       renesas,id = <0>;
                        status = "disabled";
 
                        ports {
                        clocks = <&cpg CPG_MOD 810>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        status = "disabled";
+                       renesas,id = <1>;
                        resets = <&cpg 810>;
 
                        ports {
                        clocks = <&cpg CPG_MOD 809>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 809>;
+                       renesas,id = <2>;
                        status = "disabled";
 
                        ports {
                        clocks = <&cpg CPG_MOD 808>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 808>;
+                       renesas,id = <3>;
                        status = "disabled";
 
                        ports {
                        clocks = <&cpg CPG_MOD 807>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 807>;
+                       renesas,id = <4>;
                        status = "disabled";
 
                        ports {
                        clocks = <&cpg CPG_MOD 806>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 806>;
+                       renesas,id = <5>;
                        status = "disabled";
 
                        ports {
                        clocks = <&cpg CPG_MOD 805>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 805>;
+                       renesas,id = <6>;
                        status = "disabled";
 
                        ports {
                        clocks = <&cpg CPG_MOD 804>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 804>;
+                       renesas,id = <7>;
                        status = "disabled";
 
                        ports {
                        clocks = <&cpg CPG_MOD 628>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 628>;
+                       renesas,id = <8>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 627>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 627>;
+                       renesas,id = <9>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 625>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 625>;
+                       renesas,id = <10>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 618>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 618>;
+                       renesas,id = <11>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 612>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 612>;
+                       renesas,id = <12>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 608>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 608>;
+                       renesas,id = <13>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 605>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 605>;
+                       renesas,id = <14>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 604>;
                        power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
                        resets = <&cpg 604>;
+                       renesas,id = <15>;
                        status = "disabled";
                };
 
index 144c082..c727725 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the ebisu board
  *
@@ -19,7 +19,7 @@
        };
 
        chosen {
-               bootargs = "ignore_loglevel";
+               bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
                stdout-path = "serial0:115200n8";
        };
 
 &i2c0 {
        status = "okay";
 
+       io_expander: gpio@20 {
+               compatible = "onnn,pca9654";
+               reg = <0x20>;
+               gpio-controller;
+               #gpio-cells = <2>;
+               interrupt-parent = <&gpio2>;
+               interrupts = <22 IRQ_TYPE_LEVEL_LOW>;
+       };
+
        hdmi-encoder@39 {
                compatible = "adi,adv7511w";
                reg = <0x39>;
                };
 
                port@a {
-                       reg = <0xa>;
+                       reg = <10>;
 
                        adv7482_txa: endpoint {
                                clock-lanes = <0>;
        };
 };
 
+&i2c_dvfs {
+       status = "okay";
+
+       clock-frequency = <400000>;
+
+       pmic: pmic@30 {
+               pinctrl-0 = <&irq0_pins>;
+               pinctrl-names = "default";
+
+               compatible = "rohm,bd9571mwv";
+               reg = <0x30>;
+               interrupt-parent = <&intc_ex>;
+               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               gpio-controller;
+               #gpio-cells = <2>;
+               rohm,ddr-backup-power = <0x1>;
+               rohm,rstbmode-level;
+       };
+};
+
 &lvds0 {
        status = "okay";
 
 };
 
 &lvds1 {
+       /*
+        * Even though the LVDS1 output is not connected, the encoder must be
+        * enabled to supply a pixel clock to the DU for the DPAD output when
+        * LVDS0 is in use.
+        */
+       status = "okay";
+
        clocks = <&cpg CPG_MOD 727>,
                 <&x13_clk>,
                 <&extal_clk>;
                function = "du";
        };
 
+       irq0_pins: irq0 {
+               groups = "intc_ex_irq0";
+               function = "intc_ex";
+       };
+
        pwm3_pins: pwm3 {
                groups = "pwm3_b";
                function = "pwm3";
        status = "okay";
 };
 
+&vin5 {
+       status = "okay";
+};
+
 &xhci0 {
        pinctrl-0 = <&usb30_pins>;
        pinctrl-names = "default";
index d2ad665..56cb566 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the R-Car E3 (R8A77990) SoC
  *
                        status = "disabled";
                };
 
+               cmt0: timer@e60f0000 {
+                       compatible = "renesas,r8a77990-cmt0",
+                                    "renesas,rcar-gen3-cmt0";
+                       reg = <0 0xe60f0000 0 0x1004>;
+                       interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 303>;
+                       clock-names = "fck";
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       resets = <&cpg 303>;
+                       status = "disabled";
+               };
+
+               cmt1: timer@e6130000 {
+                       compatible = "renesas,r8a77990-cmt1",
+                                    "renesas,rcar-gen3-cmt1";
+                       reg = <0 0xe6130000 0 0x1004>;
+                       interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 302>;
+                       clock-names = "fck";
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       resets = <&cpg 302>;
+                       status = "disabled";
+               };
+
+               cmt2: timer@e6140000 {
+                       compatible = "renesas,r8a77990-cmt1",
+                                    "renesas,rcar-gen3-cmt1";
+                       reg = <0 0xe6140000 0 0x1004>;
+                       interrupts = <GIC_SPI 398 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 399 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 401 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 403 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 405 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 301>;
+                       clock-names = "fck";
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       resets = <&cpg 301>;
+                       status = "disabled";
+               };
+
+               cmt3: timer@e6148000 {
+                       compatible = "renesas,r8a77990-cmt1",
+                                    "renesas,rcar-gen3-cmt1";
+                       reg = <0 0xe6148000 0 0x1004>;
+                       interrupts = <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 471 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 476 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 477 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 300>;
+                       clock-names = "fck";
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       resets = <&cpg 300>;
+                       status = "disabled";
+               };
+
                cpg: clock-controller@e6150000 {
                        compatible = "renesas,r8a77990-cpg-mssr";
                        reg = <0 0xe6150000 0 0x1000>;
                };
 
                csi40: csi2@feaa0000 {
-                       compatible = "renesas,r8a77990-csi2", "renesas,rcar-gen3-csi2";
+                       compatible = "renesas,r8a77990-csi2";
                        reg = <0 0xfeaa0000 0 0x10000>;
                        interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 716>;
index db2bed1..a7dc11e 100644 (file)
@@ -20,7 +20,7 @@
        };
 
        chosen {
-               bootargs = "ignore_loglevel";
+               bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
                stdout-path = "serial0:115200n8";
        };
 
        pinctrl-names = "default";
        renesas,no-ether-link;
        phy-handle = <&phy0>;
-       phy-mode = "rgmii-txid";
        status = "okay";
 
        phy0: ethernet-phy@0 {
        };
 };
 
+&can0 {
+       pinctrl-0 = <&can0_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+};
+
+&can1 {
+       pinctrl-0 = <&can1_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+};
+
 &du {
        pinctrl-0 = <&du_pins>;
        pinctrl-names = "default";
 };
 
 &lvds1 {
+       /*
+        * Even though the LVDS1 output is not connected, the encoder must be
+        * enabled to supply a pixel clock to the DU for the DPAD output when
+        * LVDS0 is in use.
+        */
+       status = "okay";
+
        clocks = <&cpg CPG_MOD 727>,
                 <&x12_clk>,
                 <&extal_clk>;
                };
        };
 
+       can0_pins: can0 {
+               groups = "can0_data_a";
+               function = "can0";
+       };
+
+       can1_pins: can1 {
+               groups = "can1_data_a";
+               function = "can1";
+       };
+
        du_pins: du {
                groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0";
                function = "du";
index a225c24..2dba132 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
 
 / {
        aliases {
                };
        };
 
+       keys {
+               compatible = "gpio-keys";
+
+               pinctrl-0 = <&keys_pins>;
+               pinctrl-names = "default";
+
+               key-1 {
+                       gpios = <&gpio5 17 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_1>;
+                       label = "SW4-1";
+                       wakeup-source;
+                       debounce-interval = <20>;
+               };
+               key-2 {
+                       gpios = <&gpio5 20 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_2>;
+                       label = "SW4-2";
+                       wakeup-source;
+                       debounce-interval = <20>;
+               };
+               key-3 {
+                       gpios = <&gpio5 22 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_3>;
+                       label = "SW4-3";
+                       wakeup-source;
+                       debounce-interval = <20>;
+               };
+               key-4 {
+                       gpios = <&gpio5 23 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_4>;
+                       label = "SW4-4";
+                       wakeup-source;
+                       debounce-interval = <20>;
+               };
+               key-a {
+                       gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_A>;
+                       label = "TSW0";
+                       wakeup-source;
+                       debounce-interval = <20>;
+               };
+               key-b {
+                       gpios = <&gpio6 12 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_B>;
+                       label = "TSW1";
+                       wakeup-source;
+                       debounce-interval = <20>;
+               };
+               key-c {
+                       gpios = <&gpio6 13 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_C>;
+                       label = "TSW2";
+                       wakeup-source;
+                       debounce-interval = <20>;
+               };
+       };
+
        reg_1p8v: regulator0 {
                compatible = "regulator-fixed";
                regulator-name = "fixed-1.8V";
                function = "intc_ex";
        };
 
+       keys_pins: keys {
+               pins = "GP_5_17", "GP_5_20", "GP_5_22";
+               bias-pull-up;
+       };
+
        pwm1_pins: pwm1 {
                groups = "pwm1_a";
                function = "pwm1";
        };
 };
 
+&rwdt {
+       timeout-sec = <60>;
+       status = "okay";
+};
+
 &scif1 {
        pinctrl-0 = <&scif1_pins>;
        pinctrl-names = "default";
        status = "okay";
 };
 
-&rwdt {
-       timeout-sec = <60>;
-       status = "okay";
-};
-
 &xhci0 {
        pinctrl-0 = <&usb30_pins>;
        pinctrl-names = "default";
index 1b28fa7..5f2687a 100644 (file)
@@ -18,6 +18,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-scarlet-inx.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-scarlet-kd.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopc-t4.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-m4.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-neo4.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-orangepi.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-puma-haikou.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-roc-pc.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-pi-4.dtb
index 263d7f3..6eb7407 100644 (file)
 
                soc_slppin_slp: soc_slppin_slp {
                        rockchip,pins =
-                               <0 RK_PA4 RK_FUNC_1 &pcfg_pull_none>;
+                               <0 RK_PA4 1 &pcfg_pull_none>;
                };
 
                soc_slppin_rst: soc_slppin_rst {
                        rockchip,pins =
-                               <0 RK_PA4 RK_FUNC_2 &pcfg_pull_none>;
+                               <0 RK_PA4 2 &pcfg_pull_none>;
                };
        };
 
index 8302d86..49c4b96 100644 (file)
        sdio-pwrseq {
                wifi_enable_h: wifi-enable-h {
                rockchip,pins =
-                       <1 18 RK_FUNC_GPIO &pcfg_pull_none>;
+                       <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 0e34354..5d499c9 100644 (file)
                regulator-always-on;
                regulator-boot-on;
        };
+
+       leds {
+               compatible = "gpio-leds";
+
+               power {
+                       label = "firefly:blue:power";
+                       linux,default-trigger = "heartbeat";
+                       gpios = <&rk805 1 GPIO_ACTIVE_LOW>;
+                       default-state = "on";
+                       mode = <0x23>;
+               };
+
+               user {
+                       label = "firefly:yellow:user";
+                       linux,default-trigger = "mmc1";
+                       gpios = <&rk805 0 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+                       mode = <0x05>;
+               };
+       };
 };
 
 &cpu0 {
        cpu-supply = <&vdd_arm>;
 };
 
+&cpu1 {
+       cpu-supply = <&vdd_arm>;
+};
+
+&cpu2 {
+       cpu-supply = <&vdd_arm>;
+};
+
+&cpu3 {
+       cpu-supply = <&vdd_arm>;
+};
+
 &emmc {
        bus-width = <8>;
        cap-mmc-highspeed;
+       max-frequency = <150000000>;
+       mmc-ddr-1_8v;
+       mmc-hs200-1_8v;
        non-removable;
        pinctrl-names = "default";
        pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
+       vmmc-supply = <&vcc_io>;
+       vqmmc-supply = <&vcc18_emmc>;
        status = "okay";
 };
 
        status = "okay";
 };
 
+&hdmi {
+       status = "okay";
+};
+
+&hdmiphy {
+       status = "okay";
+};
+
 &i2c1 {
        status = "okay";
 
 &usb_host0_ohci {
        status = "okay";
 };
+
+&vop {
+       status = "okay";
+};
+
+&vop_mmu {
+       status = "okay";
+};
index 79b4d1d..7cfd5ca 100644 (file)
                regulator-max-microvolt = <5000000>;
        };
 
+       ir-receiver {
+               compatible = "gpio-ir-receiver";
+               gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>;
+               pinctrl-0 = <&ir_int>;
+               pinctrl-names = "default";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               power {
+                       gpios = <&rk805 1 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "mmc0";
+               };
+
+               standby {
+                       gpios = <&rk805 0 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
        sound {
                compatible = "audio-graph-card";
                label = "rockchip,rk3328";
                interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
                #clock-cells = <1>;
                clock-output-names = "xin32k", "rk805-clkout2";
+               gpio-controller;
+               #gpio-cells = <2>;
                pinctrl-names = "default";
                pinctrl-0 = <&pmic_int_l>;
                rockchip,system-power-controller;
                        };
 
                        vcc_18: LDO_REG1 {
-                               regulator-name = "vdd_18";
+                               regulator-name = "vcc_18";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
                                regulator-always-on;
                        };
 
                        vcc18_emmc: LDO_REG2 {
-                               regulator-name = "vcc_18emmc";
+                               regulator-name = "vcc18_emmc";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
                                regulator-always-on;
 };
 
 &pinctrl {
+       ir {
+               ir_int: ir-int {
+                       rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
        pmic {
                pmic_int_l: pmic-int-l {
                        rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>;
index dabef1a..9944686 100644 (file)
                interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cru PCLK_HDMI>,
-                        <&cru SCLK_HDMI_SFC>;
+                        <&cru SCLK_HDMI_SFC>,
+                        <&cru SCLK_RTC32K>;
                clock-names = "iahb",
-                             "isfr";
+                             "isfr",
+                             "cec";
                phys = <&hdmiphy>;
                phy-names = "hdmi";
                pinctrl-names = "default";
                pinctrl-0 = <&hdmi_cec &hdmii2c_xfer &hdmi_hpd>;
                rockchip,grf = <&grf>;
+               #sound-dai-cells = <0>;
                status = "disabled";
 
                ports {
index e96eb62..1c52f47 100644 (file)
 
        backlight {
                bl_en: bl-en {
-                       rockchip,pins = <0 20 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        emmc {
                emmc_bus8: emmc-bus8 {
-                       rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 19 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 20 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 21 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 22 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 23 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 24 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 25 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC3 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC4 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC5 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC6 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC7 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PD0 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PD1 2 &pcfg_pull_up_drv_8ma>;
                };
 
                emmc-clk {
-                       rockchip,pins = <2 4 RK_FUNC_2 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <2 RK_PA4 2 &pcfg_pull_none_drv_8ma>;
                };
 
                emmc-cmd {
-                       rockchip,pins = <1 26 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <1 RK_PD2 2 &pcfg_pull_up_drv_8ma>;
                };
 
                emmc_reset: emmc-reset {
-                       rockchip,pins = <2 3 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        keys {
                pwr_key: pwr-key {
-                       rockchip,pins = <0 2 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        pmic {
                pmic_int: pmic-int {
-                       rockchip,pins = <0 1 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        sdio {
                wifi_reg_on: wifi-reg-on {
-                       rockchip,pins = <3 4 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                bt_rst: bt-rst {
-                       rockchip,pins = <3 5 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        usb {
                host_vbus_drv: host-vbus-drv {
-                       rockchip,pins = <0 4 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 8fa550c..1d0778f 100644 (file)
 &pinctrl {
        ir {
                ir_int: ir-int {
-                       rockchip,pins = <3 30 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <3 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        keys {
                pwr_key: pwr-key {
-                       rockchip,pins = <0 2 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pmic {
                pmic_sleep: pmic-sleep {
-                       rockchip,pins = <0 0 RK_FUNC_2 &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA0 2 &pcfg_pull_none>;
                };
 
                pmic_int: pmic-int {
-                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 };
index fca8e87..8251f3c 100644 (file)
                haikou_pin_hog: haikou-pin-hog {
                        rockchip,pins =
                                /* LID_BTN */
-                               <RK_GPIO3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
+                               <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
                                /* BATLOW# */
-                               <RK_GPIO0 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>,
+                               <0 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>,
                                /* SLP_BTN# */
-                               <RK_GPIO3 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>,
+                               <3 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>,
                                /* BIOS_DISABLE# */
-                               <RK_GPIO3 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
+                               <3 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        leds {
                led_sd_haikou: led-sd-gpio {
                        rockchip,pins =
-                               <RK_GPIO0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        sdmmc {
                sdmmc_cd_gpio: sdmmc-cd-gpio {
                        rockchip,pins =
-                               <RK_GPIO2 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <2 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        usb_otg {
                otg_vbus_drv: otg-vbus-drv {
                        rockchip,pins =
-                               <RK_GPIO0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 1b35d61..e17311e 100644 (file)
@@ -56,8 +56,6 @@
                        fan: fan@18 {
                                compatible = "ti,amc6821";
                                reg = <0x18>;
-                               cooling-min-state = <0>;
-                               cooling-max-state = <9>;
                                #cooling-cells = <2>;
                        };
 
        leds {
                led_pins_module: led-module-gpio {
                        rockchip,pins =
-                               <RK_GPIO2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>,
-                               <RK_GPIO3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>,
+                               <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
        pmic {
                pmic_int_l: pmic-int-l {
-                       rockchip,pins = <RK_GPIO0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                pmic_sleep: pmic-sleep {
-                       rockchip,pins = <RK_GPIO0 RK_PA0 RK_FUNC_2 &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA0 2 &pcfg_pull_none>;
                };
        };
 };
index f5aa3ca..6cc3102 100644 (file)
 
        emmc {
                emmc_bus8: emmc-bus8 {
-                       rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 19 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 20 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 21 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 22 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 23 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 24 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 25 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC3 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC4 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC5 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC6 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC7 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PD0 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PD1 2 &pcfg_pull_up_drv_8ma>;
                };
 
                emmc-clk {
-                       rockchip,pins = <2 4 RK_FUNC_2 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <2 RK_PA4 2 &pcfg_pull_none_drv_8ma>;
                };
 
                emmc-cmd {
-                       rockchip,pins = <1 26 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <1 RK_PD2 2 &pcfg_pull_up_drv_8ma>;
                };
 
                emmc_reset: emmc-reset {
-                       rockchip,pins = <2 3 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        keys {
                pwr_key: pwr-key {
-                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_down>;
                };
        };
 
        leds {
                stby_pwren: stby-pwren {
-                       rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                led_ctl: led-ctl {
-                       rockchip,pins = <3 29 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        sdmmc {
                sdmmc_clk: sdmmc-clk {
-                       rockchip,pins = <2 9 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <2 RK_PB1 1 &pcfg_pull_none_drv_8ma>;
                };
 
                sdmmc_cmd: sdmmc-cmd {
-                       rockchip,pins = <2 10 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <2 RK_PB2 1 &pcfg_pull_up_drv_8ma>;
                };
 
                sdmmc_cd: sdmmc-cd {
-                       rockchip,pins = <2 11 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <2 RK_PB3 1 &pcfg_pull_up_drv_8ma>;
                };
 
                sdmmc_bus1: sdmmc-bus1 {
-                       rockchip,pins = <2 5 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <2 RK_PA5 1 &pcfg_pull_up_drv_8ma>;
                };
 
                sdmmc_bus4: sdmmc-bus4 {
-                       rockchip,pins = <2 5 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
-                                       <2 6 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
-                                       <2 7 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
-                                       <2 8 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <2 RK_PA5 1 &pcfg_pull_up_drv_8ma>,
+                                       <2 RK_PA6 1 &pcfg_pull_up_drv_8ma>,
+                                       <2 RK_PA7 1 &pcfg_pull_up_drv_8ma>,
+                                       <2 RK_PB0 1 &pcfg_pull_up_drv_8ma>;
                };
        };
 
        usb {
                host_vbus_drv: host-vbus-drv {
-                       rockchip,pins = <0 4 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 41edcfd..231db03 100644 (file)
 &pinctrl {
        keys {
                pwr_key: pwr-key {
-                       rockchip,pins = <0 2 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pmic {
                pmic_sleep: pmic-sleep {
-                       rockchip,pins = <0 0 RK_FUNC_2 &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA0 2 &pcfg_pull_none>;
                };
 
                pmic_int: pmic-int {
-                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 };
index d34064c..006a1fb 100644 (file)
 
        emmc {
                emmc_bus8: emmc-bus8 {
-                       rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 19 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 20 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 21 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 22 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 23 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 24 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
-                                       <1 25 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC3 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC4 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC5 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC6 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PC7 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PD0 2 &pcfg_pull_up_drv_8ma>,
+                                       <1 RK_PD1 2 &pcfg_pull_up_drv_8ma>;
                };
 
                emmc-clk {
-                       rockchip,pins = <2 4 RK_FUNC_2 &pcfg_pull_none_drv_8ma>;
+                       rockchip,pins = <2 RK_PA4 2 &pcfg_pull_none_drv_8ma>;
                };
 
                emmc-cmd {
-                       rockchip,pins = <1 26 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+                       rockchip,pins = <1 RK_PD2 2 &pcfg_pull_up_drv_8ma>;
                };
 
                emmc_reset: emmc-reset {
-                       rockchip,pins = <2 3 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        ir {
                ir_int: ir-int {
-                       rockchip,pins = <3 30 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <3 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        keys {
                pwr_key: pwr-key {
-                       rockchip,pins = <0 2 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        leds {
                stby_pwren: stby-pwren {
-                       rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                led_ctl: led-ctl {
-                       rockchip,pins = <3 29 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        sdio {
                wifi_reg_on: wifi-reg-on {
-                       rockchip,pins = <3 4 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                bt_rst: bt-rst {
-                       rockchip,pins = <3 5 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        usb {
                host_vbus_drv: host-vbus-drv {
-                       rockchip,pins = <0 4 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 06e7c31..fd86188 100644 (file)
 
                emmc {
                        emmc_clk: emmc-clk {
-                               rockchip,pins = <2 4 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PA4 2 &pcfg_pull_none>;
                        };
 
                        emmc_cmd: emmc-cmd {
-                               rockchip,pins = <1 26 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PD2 2 &pcfg_pull_up>;
                        };
 
                        emmc_pwr: emmc-pwr {
-                               rockchip,pins = <1 27 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PD3 2 &pcfg_pull_up>;
                        };
 
                        emmc_bus1: emmc-bus1 {
-                               rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>;
                        };
 
                        emmc_bus4: emmc-bus4 {
-                               rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up>,
-                                               <1 19 RK_FUNC_2 &pcfg_pull_up>,
-                                               <1 20 RK_FUNC_2 &pcfg_pull_up>,
-                                               <1 21 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>,
+                                               <1 RK_PC3 2 &pcfg_pull_up>,
+                                               <1 RK_PC4 2 &pcfg_pull_up>,
+                                               <1 RK_PC5 2 &pcfg_pull_up>;
                        };
 
                        emmc_bus8: emmc-bus8 {
-                               rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up>,
-                                               <1 19 RK_FUNC_2 &pcfg_pull_up>,
-                                               <1 20 RK_FUNC_2 &pcfg_pull_up>,
-                                               <1 21 RK_FUNC_2 &pcfg_pull_up>,
-                                               <1 22 RK_FUNC_2 &pcfg_pull_up>,
-                                               <1 23 RK_FUNC_2 &pcfg_pull_up>,
-                                               <1 24 RK_FUNC_2 &pcfg_pull_up>,
-                                               <1 25 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>,
+                                               <1 RK_PC3 2 &pcfg_pull_up>,
+                                               <1 RK_PC4 2 &pcfg_pull_up>,
+                                               <1 RK_PC5 2 &pcfg_pull_up>,
+                                               <1 RK_PC6 2 &pcfg_pull_up>,
+                                               <1 RK_PC7 2 &pcfg_pull_up>,
+                                               <1 RK_PD0 2 &pcfg_pull_up>,
+                                               <1 RK_PD1 2 &pcfg_pull_up>;
                        };
                };
 
                gmac {
                        rgmii_pins: rgmii-pins {
-                               rockchip,pins = <3 22 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 24 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 19 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 8 RK_FUNC_1 &pcfg_pull_none_12ma>,
-                                               <3 9 RK_FUNC_1 &pcfg_pull_none_12ma>,
-                                               <3 10 RK_FUNC_1 &pcfg_pull_none_12ma>,
-                                               <3 14 RK_FUNC_1 &pcfg_pull_none_12ma>,
-                                               <3 28 RK_FUNC_1 &pcfg_pull_none_12ma>,
-                                               <3 13 RK_FUNC_1 &pcfg_pull_none_12ma>,
-                                               <3 15 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 16 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 17 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 18 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 25 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 20 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PC6 1 &pcfg_pull_none>,
+                                               <3 RK_PD0 1 &pcfg_pull_none>,
+                                               <3 RK_PC3 1 &pcfg_pull_none>,
+                                               <3 RK_PB0 1 &pcfg_pull_none_12ma>,
+                                               <3 RK_PB1 1 &pcfg_pull_none_12ma>,
+                                               <3 RK_PB2 1 &pcfg_pull_none_12ma>,
+                                               <3 RK_PB6 1 &pcfg_pull_none_12ma>,
+                                               <3 RK_PD4 1 &pcfg_pull_none_12ma>,
+                                               <3 RK_PB5 1 &pcfg_pull_none_12ma>,
+                                               <3 RK_PB7 1 &pcfg_pull_none>,
+                                               <3 RK_PC0 1 &pcfg_pull_none>,
+                                               <3 RK_PC1 1 &pcfg_pull_none>,
+                                               <3 RK_PC2 1 &pcfg_pull_none>,
+                                               <3 RK_PD1 1 &pcfg_pull_none>,
+                                               <3 RK_PC4 1 &pcfg_pull_none>;
                        };
 
                        rmii_pins: rmii-pins {
-                               rockchip,pins = <3 22 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 24 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 19 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 8 RK_FUNC_1 &pcfg_pull_none_12ma>,
-                                               <3 9 RK_FUNC_1 &pcfg_pull_none_12ma>,
-                                               <3 13 RK_FUNC_1 &pcfg_pull_none_12ma>,
-                                               <3 15 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 16 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 20 RK_FUNC_1 &pcfg_pull_none>,
-                                               <3 21 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PC6 1 &pcfg_pull_none>,
+                                               <3 RK_PD0 1 &pcfg_pull_none>,
+                                               <3 RK_PC3 1 &pcfg_pull_none>,
+                                               <3 RK_PB0 1 &pcfg_pull_none_12ma>,
+                                               <3 RK_PB1 1 &pcfg_pull_none_12ma>,
+                                               <3 RK_PB5 1 &pcfg_pull_none_12ma>,
+                                               <3 RK_PB7 1 &pcfg_pull_none>,
+                                               <3 RK_PC0 1 &pcfg_pull_none>,
+                                               <3 RK_PC4 1 &pcfg_pull_none>,
+                                               <3 RK_PC5 1 &pcfg_pull_none>;
                        };
                };
 
                i2c0 {
                        i2c0_xfer: i2c0-xfer {
-                               rockchip,pins = <0 6 RK_FUNC_1 &pcfg_pull_none>,
-                                               <0 7 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA6 1 &pcfg_pull_none>,
+                                               <0 RK_PA7 1 &pcfg_pull_none>;
                        };
                };
 
                i2c1 {
                        i2c1_xfer: i2c1-xfer {
-                               rockchip,pins = <2 21 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 22 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PC5 1 &pcfg_pull_none>,
+                                               <2 RK_PC6 1 &pcfg_pull_none>;
                        };
                };
 
                i2c2 {
                        i2c2_xfer: i2c2-xfer {
-                               rockchip,pins = <0 9 RK_FUNC_2 &pcfg_pull_none>,
-                                               <3 31 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PB1 2 &pcfg_pull_none>,
+                                               <3 RK_PD7 2 &pcfg_pull_none>;
                        };
                };
 
                i2c3 {
                        i2c3_xfer: i2c3-xfer {
-                               rockchip,pins = <1 16 RK_FUNC_1 &pcfg_pull_none>,
-                                               <1 17 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PC0 1 &pcfg_pull_none>,
+                                               <1 RK_PC1 1 &pcfg_pull_none>;
                        };
                };
 
                i2c4 {
                        i2c4_xfer: i2c4-xfer {
-                               rockchip,pins = <3 24 RK_FUNC_2 &pcfg_pull_none>,
-                                               <3 25 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PD0 2 &pcfg_pull_none>,
+                                               <3 RK_PD1 2 &pcfg_pull_none>;
                        };
                };
 
                i2c5 {
                        i2c5_xfer: i2c5-xfer {
-                               rockchip,pins = <3 26 RK_FUNC_2 &pcfg_pull_none>,
-                                               <3 27 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PD2 2 &pcfg_pull_none>,
+                                               <3 RK_PD3 2 &pcfg_pull_none>;
                        };
                };
 
                i2s {
                        i2s_8ch_bus: i2s-8ch-bus {
-                               rockchip,pins = <2 12 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 13 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 14 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 15 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 16 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 17 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 18 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 19 RK_FUNC_1 &pcfg_pull_none>,
-                                               <2 20 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PB4 1 &pcfg_pull_none>,
+                                               <2 RK_PB5 1 &pcfg_pull_none>,
+                                               <2 RK_PB6 1 &pcfg_pull_none>,
+                                               <2 RK_PB7 1 &pcfg_pull_none>,
+                                               <2 RK_PC0 1 &pcfg_pull_none>,
+                                               <2 RK_PC1 1 &pcfg_pull_none>,
+                                               <2 RK_PC2 1 &pcfg_pull_none>,
+                                               <2 RK_PC3 1 &pcfg_pull_none>,
+                                               <2 RK_PC4 1 &pcfg_pull_none>;
                        };
                };
 
                pwm0 {
                        pwm0_pin: pwm0-pin {
-                               rockchip,pins = <3 8 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PB0 2 &pcfg_pull_none>;
                        };
                };
 
                pwm1 {
                        pwm1_pin: pwm1-pin {
-                               rockchip,pins = <0 8 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PB0 2 &pcfg_pull_none>;
                        };
                };
 
                pwm3 {
                        pwm3_pin: pwm3-pin {
-                               rockchip,pins = <3 29 RK_FUNC_3 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PD5 3 &pcfg_pull_none>;
                        };
                };
 
                sdio0 {
                        sdio0_bus1: sdio0-bus1 {
-                               rockchip,pins = <2 28 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <2 RK_PD4 1 &pcfg_pull_up>;
                        };
 
                        sdio0_bus4: sdio0-bus4 {
-                               rockchip,pins = <2 28 RK_FUNC_1 &pcfg_pull_up>,
-                                               <2 29 RK_FUNC_1 &pcfg_pull_up>,
-                                               <2 30 RK_FUNC_1 &pcfg_pull_up>,
-                                               <2 31 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <2 RK_PD4 1 &pcfg_pull_up>,
+                                               <2 RK_PD5 1 &pcfg_pull_up>,
+                                               <2 RK_PD6 1 &pcfg_pull_up>,
+                                               <2 RK_PD7 1 &pcfg_pull_up>;
                        };
 
                        sdio0_cmd: sdio0-cmd {
-                               rockchip,pins = <3 0 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PA0 1 &pcfg_pull_up>;
                        };
 
                        sdio0_clk: sdio0-clk {
-                               rockchip,pins = <3 1 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PA1 1 &pcfg_pull_none>;
                        };
 
                        sdio0_cd: sdio0-cd {
-                               rockchip,pins = <3 2 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PA2 1 &pcfg_pull_up>;
                        };
 
                        sdio0_wp: sdio0-wp {
-                               rockchip,pins = <3 3 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PA3 1 &pcfg_pull_up>;
                        };
 
                        sdio0_pwr: sdio0-pwr {
-                               rockchip,pins = <3 4 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PA4 1 &pcfg_pull_up>;
                        };
 
                        sdio0_bkpwr: sdio0-bkpwr {
-                               rockchip,pins = <3 5 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PA5 1 &pcfg_pull_up>;
                        };
 
                        sdio0_int: sdio0-int {
-                               rockchip,pins = <3 6 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PA6 1 &pcfg_pull_up>;
                        };
                };
 
                sdmmc {
                        sdmmc_clk: sdmmc-clk {
-                               rockchip,pins = <2 9 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PB1 1 &pcfg_pull_none>;
                        };
 
                        sdmmc_cmd: sdmmc-cmd {
-                               rockchip,pins = <2 10 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <2 RK_PB2 1 &pcfg_pull_up>;
                        };
 
                        sdmmc_cd: sdmmc-cd {
-                               rockchip,pins = <2 11 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <2 RK_PB3 1 &pcfg_pull_up>;
                        };
 
                        sdmmc_bus1: sdmmc-bus1 {
-                               rockchip,pins = <2 5 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <2 RK_PA5 1 &pcfg_pull_up>;
                        };
 
                        sdmmc_bus4: sdmmc-bus4 {
-                               rockchip,pins = <2 5 RK_FUNC_1 &pcfg_pull_up>,
-                                               <2 6 RK_FUNC_1 &pcfg_pull_up>,
-                                               <2 7 RK_FUNC_1 &pcfg_pull_up>,
-                                               <2 8 RK_FUNC_1 &pcfg_pull_up>;
+                               rockchip,pins = <2 RK_PA5 1 &pcfg_pull_up>,
+                                               <2 RK_PA6 1 &pcfg_pull_up>,
+                                               <2 RK_PA7 1 &pcfg_pull_up>,
+                                               <2 RK_PB0 1 &pcfg_pull_up>;
                        };
                };
 
                spdif {
                        spdif_tx: spdif-tx {
-                               rockchip,pins = <2 RK_PC7 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PC7 1 &pcfg_pull_none>;
                        };
                };
 
                spi0 {
                        spi0_clk: spi0-clk {
-                               rockchip,pins = <1 29 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PD5 2 &pcfg_pull_up>;
                        };
                        spi0_cs0: spi0-cs0 {
-                               rockchip,pins = <1 24 RK_FUNC_3 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PD0 3 &pcfg_pull_up>;
                        };
                        spi0_cs1: spi0-cs1 {
-                               rockchip,pins = <1 25 RK_FUNC_3 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PD1 3 &pcfg_pull_up>;
                        };
                        spi0_tx: spi0-tx {
-                               rockchip,pins = <1 23 RK_FUNC_3 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PC7 3 &pcfg_pull_up>;
                        };
                        spi0_rx: spi0-rx {
-                               rockchip,pins = <1 22 RK_FUNC_3 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PC6 3 &pcfg_pull_up>;
                        };
                };
 
                spi1 {
                        spi1_clk: spi1-clk {
-                               rockchip,pins = <1 14 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PB6 2 &pcfg_pull_up>;
                        };
                        spi1_cs0: spi1-cs0 {
-                               rockchip,pins = <1 15 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PB7 2 &pcfg_pull_up>;
                        };
                        spi1_cs1: spi1-cs1 {
-                               rockchip,pins = <3 28 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <3 RK_PD4 2 &pcfg_pull_up>;
                        };
                        spi1_rx: spi1-rx {
-                               rockchip,pins = <1 16 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PC0 2 &pcfg_pull_up>;
                        };
                        spi1_tx: spi1-tx {
-                               rockchip,pins = <1 17 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <1 RK_PC1 2 &pcfg_pull_up>;
                        };
                };
 
                spi2 {
                        spi2_clk: spi2-clk {
-                               rockchip,pins = <0 12 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PB4 2 &pcfg_pull_up>;
                        };
                        spi2_cs0: spi2-cs0 {
-                               rockchip,pins = <0 13 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PB5 2 &pcfg_pull_up>;
                        };
                        spi2_rx: spi2-rx {
-                               rockchip,pins = <0 10 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PB2 2 &pcfg_pull_up>;
                        };
                        spi2_tx: spi2-tx {
-                               rockchip,pins = <0 11 RK_FUNC_2 &pcfg_pull_up>;
+                               rockchip,pins = <0 RK_PB3 2 &pcfg_pull_up>;
                        };
                };
 
                tsadc {
                        otp_gpio: otp-gpio {
-                               rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
                        };
 
                        otp_out: otp-out {
-                               rockchip,pins = <0 3 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA3 1 &pcfg_pull_none>;
                        };
                };
 
                uart0 {
                        uart0_xfer: uart0-xfer {
-                               rockchip,pins = <2 24 RK_FUNC_1 &pcfg_pull_up>,
-                                               <2 25 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PD0 1 &pcfg_pull_up>,
+                                               <2 RK_PD1 1 &pcfg_pull_none>;
                        };
 
                        uart0_cts: uart0-cts {
-                               rockchip,pins = <2 26 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PD2 1 &pcfg_pull_none>;
                        };
 
                        uart0_rts: uart0-rts {
-                               rockchip,pins = <2 27 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PD3 1 &pcfg_pull_none>;
                        };
                };
 
                uart1 {
                        uart1_xfer: uart1-xfer {
-                               rockchip,pins = <0 20 RK_FUNC_3 &pcfg_pull_up>,
-                                               <0 21 RK_FUNC_3 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PC4 3 &pcfg_pull_up>,
+                                               <0 RK_PC5 3 &pcfg_pull_none>;
                        };
 
                        uart1_cts: uart1-cts {
-                               rockchip,pins = <0 22 RK_FUNC_3 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PC6 3 &pcfg_pull_none>;
                        };
 
                        uart1_rts: uart1-rts {
-                               rockchip,pins = <0 23 RK_FUNC_3 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PC7 3 &pcfg_pull_none>;
                        };
                };
 
                uart2 {
                        uart2_xfer: uart2-xfer {
-                               rockchip,pins = <2 6 RK_FUNC_2 &pcfg_pull_up>,
-                                               <2 5 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <2 RK_PA6 2 &pcfg_pull_up>,
+                                               <2 RK_PA5 2 &pcfg_pull_none>;
                        };
                        /* no rts / cts for uart2 */
                };
 
                uart3 {
                        uart3_xfer: uart3-xfer {
-                               rockchip,pins = <3 29 RK_FUNC_2 &pcfg_pull_up>,
-                                               <3 30 RK_FUNC_3 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PD5 2 &pcfg_pull_up>,
+                                               <3 RK_PD6 3 &pcfg_pull_none>;
                        };
 
                        uart3_cts: uart3-cts {
-                               rockchip,pins = <3 16 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PC0 2 &pcfg_pull_none>;
                        };
 
                        uart3_rts: uart3-rts {
-                               rockchip,pins = <3 17 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <3 RK_PC1 2 &pcfg_pull_none>;
                        };
                };
 
                uart4 {
                        uart4_xfer: uart4-xfer {
-                               rockchip,pins = <0 27 RK_FUNC_3 &pcfg_pull_up>,
-                                               <0 26 RK_FUNC_3 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PD3 3 &pcfg_pull_up>,
+                                               <0 RK_PD2 3 &pcfg_pull_none>;
                        };
 
                        uart4_cts: uart4-cts {
-                               rockchip,pins = <0 24 RK_FUNC_3 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PD0 3 &pcfg_pull_none>;
                        };
 
                        uart4_rts: uart4-rts {
-                               rockchip,pins = <0 25 RK_FUNC_3 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PD1 3 &pcfg_pull_none>;
                        };
                };
        };
index 959ddc3..77008dc 100644 (file)
        pmic {
                pmic_int_l: pmic-int-l {
                        rockchip,pins =
-                               <1 21 RK_FUNC_GPIO &pcfg_pull_up>;
+                               <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                pmic_dvs2: pmic-dvs2 {
                        rockchip,pins =
-                               <1 18 RK_FUNC_GPIO &pcfg_pull_down>;
+                               <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>;
                };
        };
 
        usb2 {
                vcc5v0_host_en: vcc5v0-host-en {
                        rockchip,pins =
-                               <4 25 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <4 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 027d428..6b059bd 100644 (file)
        gmac {
                rgmii_sleep_pins: rgmii-sleep-pins {
                        rockchip,pins =
-                               <3 15 RK_FUNC_GPIO &pcfg_output_low>;
+                               <3 RK_PB7 RK_FUNC_GPIO &pcfg_output_low>;
                };
        };
 
        pcie {
                pcie_drv: pcie-drv {
                        rockchip,pins =
-                               <1 24 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
                        };
        };
 
        usb2 {
                host_vbus_drv: host-vbus-drv {
                        rockchip,pins =
-                               <4 27 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <4 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        leds {
                user_led1: user_led1 {
                        rockchip,pins =
-                               <4 25 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <4 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                user_led2: user_led2 {
                        rockchip,pins =
-                               <4 26 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                user_led3: user_led3 {
                        rockchip,pins =
-                               <4 30 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                user_led4: user_led4 {
                        rockchip,pins =
-                               <1 0 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                wlan_led: wlan_led {
                        rockchip,pins =
-                               <1 1 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                bt_led: bt_led {
                        rockchip,pins =
-                               <1 4 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index d1cf404..a9f4d6d 100644 (file)
@@ -73,7 +73,7 @@
 &pinctrl {
        tpm {
                h1_int_od_l: h1-int-od-l {
-                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 };
index 931640e..7cd6d47 100644 (file)
@@ -365,27 +365,27 @@ ap_i2c_tp: &i2c5 {
 &pinctrl {
        discrete-regulators {
                pp1500_en: pp1500-en {
-                       rockchip,pins = <RK_GPIO0 10 RK_FUNC_GPIO
+                       rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO
                                         &pcfg_pull_none>;
                };
 
                pp1800_audio_en: pp1800-audio-en {
-                       rockchip,pins = <RK_GPIO0 2 RK_FUNC_GPIO
+                       rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO
                                         &pcfg_pull_down>;
                };
 
                pp3000_en: pp3000-en {
-                       rockchip,pins = <RK_GPIO0 12 RK_FUNC_GPIO
+                       rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO
                                         &pcfg_pull_none>;
                };
 
                pp3300_disp_en: pp3300-disp-en {
-                       rockchip,pins = <RK_GPIO4 27 RK_FUNC_GPIO
+                       rockchip,pins = <4 RK_PD3 RK_FUNC_GPIO
                                         &pcfg_pull_none>;
                };
 
                wlan_module_pd_l: wlan-module-pd-l {
-                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO
                                         &pcfg_pull_down>;
                };
        };
@@ -393,10 +393,10 @@ ap_i2c_tp: &i2c5 {
 
 &wifi {
        wifi_perst_l: wifi-perst-l {
-               rockchip,pins = <2 27 RK_FUNC_GPIO &pcfg_pull_none>;
+               rockchip,pins = <2 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>;
        };
 
        wlan_host_wake_l: wlan-host-wake-l {
-               rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_none>;
+               rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
        };
 };
index 15e254a..3e2272b 100644 (file)
@@ -290,24 +290,24 @@ ap_i2c_dig: &i2c2 {
        digitizer {
                /* Has external pullup */
                cpu1_dig_irq_l: cpu1-dig-irq-l {
-                       rockchip,pins = <2 4 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                /* Has external pullup */
                cpu1_dig_pdct_l: cpu1-dig-pdct-l {
-                       rockchip,pins = <2 5 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        discrete-regulators {
                cpu3_pen_pwr_en: cpu3-pen-pwr-en {
-                       rockchip,pins = <4 30 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pen {
                cpu1_pen_eject: cpu1-pen-eject {
-                       rockchip,pins = <0 13 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 };
index 62ea7d6..50dfab5 100644 (file)
@@ -455,58 +455,58 @@ camera: &i2c7 {
 
 /* PINCTRL OVERRIDES */
 &ec_ap_int_l {
-       rockchip,pins = <1 18 RK_FUNC_GPIO &pcfg_pull_up>;
+       rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;
 };
 
 &ap_fw_wp {
-       rockchip,pins = <0 13 RK_FUNC_GPIO &pcfg_pull_none>;
+       rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
 };
 
 &bl_en {
-       rockchip,pins = <4 21 RK_FUNC_GPIO &pcfg_pull_none>;
+       rockchip,pins = <4 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>;
 };
 
 &bt_host_wake_l {
-       rockchip,pins = <1 2 RK_FUNC_GPIO &pcfg_pull_none>;
+       rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
 };
 
 &ec_ap_int_l {
-       rockchip,pins = <1 18 RK_FUNC_GPIO &pcfg_pull_up>;
+       rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;
 };
 
 &headset_int_l {
-       rockchip,pins = <1 23 RK_FUNC_GPIO &pcfg_pull_up>;
+       rockchip,pins = <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>;
 };
 
 &i2s0_8ch_bus {
        rockchip,pins =
-               <3 24 RK_FUNC_1 &pcfg_pull_none_6ma>,
-               <3 25 RK_FUNC_1 &pcfg_pull_none_6ma>,
-               <3 26 RK_FUNC_1 &pcfg_pull_none_6ma>,
-               <3 27 RK_FUNC_1 &pcfg_pull_none_6ma>,
-               <3 31 RK_FUNC_1 &pcfg_pull_none_6ma>,
-               <4 0 RK_FUNC_1 &pcfg_pull_none_6ma>;
+               <3 RK_PD0 1 &pcfg_pull_none_6ma>,
+               <3 RK_PD1 1 &pcfg_pull_none_6ma>,
+               <3 RK_PD2 1 &pcfg_pull_none_6ma>,
+               <3 RK_PD3 1 &pcfg_pull_none_6ma>,
+               <3 RK_PD7 1 &pcfg_pull_none_6ma>,
+               <4 RK_PA0 1 &pcfg_pull_none_6ma>;
 };
 
 /* there is no external pull up, so need to set this pin pull up */
 &sdmmc_cd_gpio {
-       rockchip,pins = <1 11 RK_FUNC_GPIO &pcfg_pull_up>;
+       rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>;
 };
 
 &sd_pwr_1800_sel {
-       rockchip,pins = <2 28 RK_FUNC_GPIO &pcfg_pull_up>;
+       rockchip,pins = <2 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>;
 };
 
 &sdmode_en {
-       rockchip,pins = <0 2 RK_FUNC_GPIO &pcfg_pull_down>;
+       rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_down>;
 };
 
 &touch_reset_l {
-       rockchip,pins = <0 10 RK_FUNC_GPIO &pcfg_pull_down>;
+       rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_down>;
 };
 
 &touch_int_l {
-       rockchip,pins = <1 4 RK_FUNC_GPIO &pcfg_pull_down>;
+       rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>;
 };
 
 &pinctrl {
@@ -523,84 +523,84 @@ camera: &i2c7 {
 
        camera {
                pp1250_cam_en: pp1250-dvdd {
-                       rockchip,pins = <2 4 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                pp2800_cam_en: pp2800-avdd {
-                       rockchip,pins = <2 24 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                ucam_rst: ucam_rst {
-                       rockchip,pins = <2 3 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                wcam_rst: wcam_rst {
-                       rockchip,pins = <2 5 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        digitizer {
                pen_int_odl: pen-int-odl {
-                       rockchip,pins = <1 0 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                pen_reset_l: pen-reset-l {
-                       rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        discrete-regulators {
                display_rst_l: display-rst-l {
-                       rockchip,pins = <4 25 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <4 RK_PD1 RK_FUNC_GPIO &pcfg_pull_down>;
                };
 
                ppvarp_lcd_en: ppvarp-lcd-en {
-                       rockchip,pins = <4 27 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <4 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                ppvarn_lcd_en: ppvarn-lcd-en {
-                       rockchip,pins = <4 28 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <4 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        dmic {
                dmic_en: dmic-en {
-                       rockchip,pins = <4 3 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pen {
                pen_eject_odl: pen-eject-odl {
-                       rockchip,pins = <1 1 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        tpm {
                h1_int_od_l: h1-int-od-l {
-                       rockchip,pins = <1 17 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 };
 
 &wifi {
        bt_en_1v8_l: bt-en-1v8-l {
-               rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_none>;
+               rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
        };
 
        wlan_pd_1v8_l: wlan-pd-1v8-l {
-               rockchip,pins = <0 4 RK_FUNC_GPIO &pcfg_pull_none>;
+               rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
        };
 
        /* Default pull-up, but just to be clear */
        wlan_rf_kill_1v8_l: wlan-rf-kill-1v8-l {
-               rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+               rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
        };
 
        wifi_perst_l: wifi-perst-l {
-               rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_none>;
+               rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
        };
 
        wlan_host_wake_l: wlan-host-wake-l {
-               rockchip,pins = <1 3 RK_FUNC_GPIO &pcfg_pull_up>;
+               rockchip,pins = <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
        };
 };
index da03fa9..dd56249 100644 (file)
@@ -676,29 +676,29 @@ ap_i2c_audio: &i2c8 {
 
        backlight-enable {
                bl_en: bl-en {
-                       rockchip,pins = <1 17 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        cros-ec {
                ec_ap_int_l: ec-ap-int-l {
-                       rockchip,pins = <RK_GPIO0 1 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        discrete-regulators {
                sd_io_pwr_en: sd-io-pwr-en {
-                       rockchip,pins = <RK_GPIO2 2 RK_FUNC_GPIO
+                       rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO
                                         &pcfg_pull_none>;
                };
 
                sd_pwr_1800_sel: sd-pwr-1800-sel {
-                       rockchip,pins = <RK_GPIO2 28 RK_FUNC_GPIO
+                       rockchip,pins = <2 RK_PD4 RK_FUNC_GPIO
                                         &pcfg_pull_none>;
                };
 
                sd_slot_pwr_en: sd-slot-pwr-en {
-                       rockchip,pins = <RK_GPIO4 29 RK_FUNC_GPIO
+                       rockchip,pins = <4 RK_PD5 RK_FUNC_GPIO
                                         &pcfg_pull_none>;
                };
        };
@@ -706,17 +706,17 @@ ap_i2c_audio: &i2c8 {
        codec {
                /* Has external pullup */
                headset_int_l: headset-int-l {
-                       rockchip,pins = <1 23 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                mic_int: mic-int {
-                       rockchip,pins = <1 13 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>;
                };
        };
 
        max98357a {
                sdmode_en: sdmode-en {
-                       rockchip,pins = <1 2 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_down>;
                };
        };
 
@@ -727,7 +727,7 @@ ap_i2c_audio: &i2c8 {
                         * to hack this as gpio, so the EP could be able to
                         * de-assert it along and make ClockPM(CPM) work.
                         */
-                       rockchip,pins = <2 26 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
@@ -738,20 +738,20 @@ ap_i2c_audio: &i2c8 {
                 */
                sdmmc_bus4: sdmmc-bus4 {
                        rockchip,pins =
-                               <4 8 RK_FUNC_1 &pcfg_pull_none_8ma>,
-                               <4 9 RK_FUNC_1 &pcfg_pull_none_8ma>,
-                               <4 10 RK_FUNC_1 &pcfg_pull_none_8ma>,
-                               <4 11 RK_FUNC_1 &pcfg_pull_none_8ma>;
+                               <4 RK_PB0 1 &pcfg_pull_none_8ma>,
+                               <4 RK_PB1 1 &pcfg_pull_none_8ma>,
+                               <4 RK_PB2 1 &pcfg_pull_none_8ma>,
+                               <4 RK_PB3 1 &pcfg_pull_none_8ma>;
                };
 
                sdmmc_clk: sdmmc-clk {
                        rockchip,pins =
-                               <4 12 RK_FUNC_1 &pcfg_pull_none_8ma>;
+                               <4 RK_PB4 1 &pcfg_pull_none_8ma>;
                };
 
                sdmmc_cmd: sdmmc-cmd {
                        rockchip,pins =
-                               <4 13 RK_FUNC_1 &pcfg_pull_none_8ma>;
+                               <4 RK_PB5 1 &pcfg_pull_none_8ma>;
                };
 
                /*
@@ -765,12 +765,12 @@ ap_i2c_audio: &i2c8 {
                 */
                sdmmc_cd: sdmmc-cd {
                        rockchip,pins =
-                               <0 7 RK_FUNC_1 &pcfg_pull_none>;
+                               <0 RK_PA7 1 &pcfg_pull_none>;
                };
 
                /* This is where we actually hook up CD; has external pull */
                sdmmc_cd_gpio: sdmmc-cd-gpio {
-                       rockchip,pins = <4 24 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
@@ -780,47 +780,47 @@ ap_i2c_audio: &i2c8 {
                         * Pull down SPI1 CLK/CS/RX/TX during suspend, to
                         * prevent leakage.
                         */
-                       rockchip,pins = <1 9 RK_FUNC_GPIO &pcfg_pull_down>,
-                                       <1 10 RK_FUNC_GPIO &pcfg_pull_down>,
-                                       <1 7 RK_FUNC_GPIO &pcfg_pull_down>,
-                                       <1 8 RK_FUNC_GPIO &pcfg_pull_down>;
+                       rockchip,pins = <1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_down>,
+                                       <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_down>,
+                                       <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_down>,
+                                       <1 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>;
                };
        };
 
        touchscreen {
                touch_int_l: touch-int-l {
-                       rockchip,pins = <3 13 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <3 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                touch_reset_l: touch-reset-l {
-                       rockchip,pins = <4 26 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        trackpad {
                ap_i2c_tp_pu_en: ap-i2c-tp-pu-en {
-                       rockchip,pins = <3 12 RK_FUNC_GPIO &pcfg_output_high>;
+                       rockchip,pins = <3 RK_PB4 RK_FUNC_GPIO &pcfg_output_high>;
                };
 
                trackpad_int_l: trackpad-int-l {
-                       rockchip,pins = <1 4 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        wifi: wifi {
                wlan_module_reset_l: wlan-module-reset-l {
-                       rockchip,pins = <1 11 RK_FUNC_GPIO &pcfg_pull_none>;
+                       rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
 
                bt_host_wake_l: bt-host-wake-l {
                        /* Kevin has an external pull up, but Gru does not */
-                       rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        write-protect {
                ap_fw_wp: ap-fw-wp {
-                       rockchip,pins = <1 18 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 };
index 84433cf..2a12798 100644 (file)
                pinctrl-names = "default";
                pinctrl-0 = <&ir_rx>;
        };
+
+       fan: pwm-fan {
+               compatible = "pwm-fan";
+               /*
+                * With 20KHz PWM and an EVERCOOL EC4007H12SA fan, these levels
+                * work out to 0, ~1200, ~3000, and 5000RPM respectively.
+                */
+               cooling-levels = <0 12 18 255>;
+               #cooling-cells = <2>;
+               fan-supply = <&vcc12v0_sys>;
+               pwms = <&pwm1 0 50000 0>;
+       };
+};
+
+&cpu_thermal {
+       trips {
+               cpu_warm: cpu_warm {
+                       temperature = <55000>;
+                       hysteresis = <2000>;
+                       type = "active";
+               };
+
+               cpu_hot: cpu_hot {
+                       temperature = <65000>;
+                       hysteresis = <2000>;
+                       type = "active";
+               };
+       };
+
+       cooling-maps {
+               map2 {
+                       trip = <&cpu_warm>;
+                       cooling-device = <&fan THERMAL_NO_LIMIT 1>;
+               };
+
+               map3 {
+                       trip = <&cpu_hot>;
+                       cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
+               };
+       };
+};
+
+&gpu_thermal {
+       trips {
+               gpu_warm: gpu_warm {
+                       temperature = <55000>;
+                       hysteresis = <2000>;
+                       type = "active";
+               };
+
+               gpu_hot: gpu_hot {
+                       temperature = <65000>;
+                       hysteresis = <2000>;
+                       type = "active";
+               };
+       };
+       cooling-maps {
+               map1 {
+                       trip = <&gpu_warm>;
+                       cooling-device = <&fan THERMAL_NO_LIMIT 1>;
+               };
+
+               map2 {
+                       trip = <&gpu_hot>;
+                       cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
+               };
+       };
 };
 
 &pinctrl {
        ir {
                ir_rx: ir-rx {
                        /* external pullup to VCC3V3_SYS, despite being 1.8V :/ */
-                       rockchip,pins = <0 RK_PA6 RK_FUNC_1 &pcfg_pull_none>;
+                       rockchip,pins = <0 RK_PA6 1 &pcfg_pull_none>;
                };
        };
 };
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-neo4.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-neo4.dts
new file mode 100644 (file)
index 0000000..195410b
--- /dev/null
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Amarula Solutions B.V.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+/dts-v1/;
+
+#include "rk3399-nanopi4.dtsi"
+
+/ {
+       model = "FriendlyARM NanoPi NEO4";
+       compatible = "friendlyarm,nanopi-neo4", "rockchip,rk3399";
+
+       vdd_5v: vdd-5v {
+               compatible = "regulator-fixed";
+               regulator-name = "vdd_5v";
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
+       vcc5v0_core: vcc5v0-core {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc5v0_core";
+               regulator-always-on;
+               regulator-boot-on;
+               vin-supply = <&vdd_5v>;
+       };
+
+       vcc5v0_usb1: vcc5v0-usb1 {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc5v0_usb1";
+               regulator-always-on;
+               regulator-boot-on;
+               vin-supply = <&vcc5v0_sys>;
+       };
+};
+
+&vcc3v3_sys {
+       vin-supply = <&vcc5v0_core>;
+};
+
+&u2phy0_host {
+       phy-supply = <&vcc5v0_usb1>;
+};
+
+&vbus_typec {
+       regulator-always-on;
+       vin-supply = <&vdd_5v>;
+};
index d325e11..dd16c80 100644 (file)
        assigned-clocks = <&cru SCLK_RMII_SRC>;
        clock_in_out = "input";
        pinctrl-names = "default";
-       pinctrl-0 = <&rgmii_pins>;
+       pinctrl-0 = <&rgmii_pins>, <&phy_intb>, <&phy_rstb>;
+       phy-handle = <&rtl8211e>;
        phy-mode = "rgmii";
        phy-supply = <&vcc3v3_s3>;
        snps,reset-active-low;
-       snps,reset-delays-us = <0 10000 50000>;
+       snps,reset-delays-us = <0 10000 30000>;
        snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
        tx_delay = <0x28>;
        rx_delay = <0x11>;
        status = "okay";
+
+       mdio {
+               compatible = "snps,dwmac-mdio";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               rtl8211e: phy@1 {
+                       reg = <1>;
+                       interrupt-parent = <&gpio3>;
+                       interrupts = <RK_PB2 IRQ_TYPE_LEVEL_LOW>;
+               };
+       };
 };
 
 &gpu {
                };
        };
 
+       phy {
+               phy_intb: phy-intb {
+                       rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+
+               phy_rstb: phy-rstb {
+                       rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
        pmic {
                cpu_b_sleep: cpu-b-sleep {
                        rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts b/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts
new file mode 100644 (file)
index 0000000..0541dfc
--- /dev/null
@@ -0,0 +1,790 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd.
+ */
+
+/dts-v1/;
+
+#include "dt-bindings/pwm/pwm.h"
+#include "dt-bindings/input/input.h"
+#include "rk3399.dtsi"
+#include "rk3399-opp.dtsi"
+
+/ {
+       model = "Orange Pi RK3399 Board";
+       compatible = "rockchip,rk3399-orangepi", "rockchip,rk3399";
+
+       chosen {
+               stdout-path = "serial2:1500000n8";
+       };
+
+       clkin_gmac: external-gmac-clock {
+               compatible = "fixed-clock";
+               clock-frequency = <125000000>;
+               clock-output-names = "clkin_gmac";
+               #clock-cells = <0>;
+       };
+
+       adc-keys {
+               compatible = "adc-keys";
+               io-channels = <&saradc 1>;
+               io-channel-names = "buttons";
+               keyup-threshold-microvolt = <1800000>;
+               poll-interval = <100>;
+
+               button-up {
+                       label = "Volume Up";
+                       linux,code = <KEY_VOLUMEUP>;
+                       press-threshold-microvolt = <100000>;
+               };
+
+               button-down {
+                       label = "Volume Down";
+                       linux,code = <KEY_VOLUMEDOWN>;
+                       press-threshold-microvolt = <300000>;
+               };
+
+               back {
+                       label = "Back";
+                       linux,code = <KEY_BACK>;
+                       press-threshold-microvolt = <985000>;
+               };
+
+               menu {
+                       label = "Menu";
+                       linux,code = <KEY_MENU>;
+                       press-threshold-microvolt = <1314000>;
+               };
+       };
+
+       dc_12v: dc-12v {
+               compatible = "regulator-fixed";
+               regulator-name = "dc_12v";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <12000000>;
+               regulator-max-microvolt = <12000000>;
+       };
+
+       keys: gpio-keys {
+               compatible = "gpio-keys";
+               autorepeat;
+
+               power {
+                       debounce-interval = <100>;
+                       gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>;
+                       label = "GPIO Power";
+                       linux,code = <KEY_POWER>;
+                       linux,input-type = <1>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pwr_btn>;
+                       wakeup-source;
+               };
+       };
+
+       sdio_pwrseq: sdio-pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               clocks = <&rk808 1>;
+               clock-names = "ext_clock";
+               pinctrl-names = "default";
+               pinctrl-0 = <&wifi_reg_on_h>;
+               reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
+       };
+
+       /* switched by pmic_sleep */
+       vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc1v8_s3";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vcc_1v8>;
+       };
+
+       vcc3v0_sd: vcc3v0-sd {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&sdmmc0_pwr_h>;
+               regulator-boot-on;
+               regulator-max-microvolt = <3000000>;
+               regulator-min-microvolt = <3000000>;
+               regulator-name = "vcc3v0_sd";
+               vin-supply = <&vcc3v3_sys>;
+       };
+
+       vcc3v3_sys: vcc3v3-sys {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc3v3_sys";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&vcc_sys>;
+       };
+
+       vcc5v0_host: vcc5v0-host-regulator {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&vcc5v0_host_en>;
+               regulator-name = "vcc5v0_host";
+               regulator-always-on;
+               vin-supply = <&vcc_sys>;
+       };
+
+       vbus_typec: vbus-typec-regulator {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&vcc5v0_typec_en>;
+               regulator-name = "vbus_typec";
+               vin-supply = <&vcc_sys>;
+       };
+
+       vcc_sys: vcc-sys {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_sys";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               vin-supply = <&dc_12v>;
+       };
+
+       vdd_log: vdd-log {
+               compatible = "pwm-regulator";
+               pwms = <&pwm2 0 25000 1>;
+               regulator-name = "vdd_log";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <1400000>;
+               vin-supply = <&vcc_sys>;
+       };
+};
+
+&cpu_l0 {
+       cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l1 {
+       cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l2 {
+       cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l3 {
+       cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_b0 {
+       cpu-supply = <&vdd_cpu_b>;
+};
+
+&cpu_b1 {
+       cpu-supply = <&vdd_cpu_b>;
+};
+
+&emmc_phy {
+       status = "okay";
+};
+
+&gmac {
+       assigned-clocks = <&cru SCLK_RMII_SRC>;
+       assigned-clock-parents = <&clkin_gmac>;
+       clock_in_out = "input";
+       phy-supply = <&vcc3v3_s3>;
+       phy-mode = "rgmii";
+       pinctrl-names = "default";
+       pinctrl-0 = <&rgmii_pins>;
+       snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
+       snps,reset-active-low;
+       snps,reset-delays-us = <0 10000 50000>;
+       tx_delay = <0x28>;
+       rx_delay = <0x11>;
+       status = "okay";
+};
+
+&gpu {
+       mali-supply = <&vdd_gpu>;
+       status = "okay";
+};
+
+&hdmi {
+       ddc-i2c-bus = <&i2c3>;
+       status = "okay";
+};
+
+&hdmi_sound {
+       status = "okay";
+};
+
+&i2c0 {
+       clock-frequency = <400000>;
+       i2c-scl-rising-time-ns = <168>;
+       i2c-scl-falling-time-ns = <4>;
+       status = "okay";
+
+       rk808: pmic@1b {
+               compatible = "rockchip,rk808";
+               reg = <0x1b>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+               #clock-cells = <1>;
+               clock-output-names = "rtc_clko_soc", "rtc_clko_wifi";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pmic_int_l>;
+               rockchip,system-power-controller;
+               wakeup-source;
+
+               vcc1-supply = <&vcc3v3_sys>;
+               vcc2-supply = <&vcc3v3_sys>;
+               vcc3-supply = <&vcc3v3_sys>;
+               vcc4-supply = <&vcc3v3_sys>;
+               vcc6-supply = <&vcc3v3_sys>;
+               vcc7-supply = <&vcc3v3_sys>;
+               vcc8-supply = <&vcc3v3_sys>;
+               vcc9-supply = <&vcc3v3_sys>;
+               vcc10-supply = <&vcc3v3_sys>;
+               vcc11-supply = <&vcc3v3_sys>;
+               vcc12-supply = <&vcc3v3_sys>;
+               vddio-supply = <&vcc_3v0>;
+
+               regulators {
+                       vdd_center: DCDC_REG1 {
+                               regulator-name = "vdd_center";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <700000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-ramp-delay = <6001>;
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vdd_cpu_l: DCDC_REG2 {
+                               regulator-name = "vdd_cpu_l";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <700000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-ramp-delay = <6001>;
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vcc_ddr: DCDC_REG3 {
+                               regulator-name = "vcc_ddr";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+
+                       vcc_1v8: DCDC_REG4 {
+                               regulator-name = "vcc_1v8";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vcc1v8_dvp: LDO_REG1 {
+                               regulator-name = "vcc1v8_dvp";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3400000>;
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vcc3v0_tp: LDO_REG2 {
+                               regulator-name = "vcc3v0_tp";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3400000>;
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vcc1v8_pmupll: LDO_REG3 {
+                               regulator-name = "vcc1v8_pmupll";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <2500000>;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vcc_sdio: LDO_REG4 {
+                               regulator-name = "vcc_sdio";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3400000>;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <3000000>;
+                               };
+                       };
+
+                       vcca3v0_codec: LDO_REG5 {
+                               regulator-name = "vcca3v0_codec";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3400000>;
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vcc_1v5: LDO_REG6 {
+                               regulator-name = "vcc_1v5";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <2500000>;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1500000>;
+                               };
+                       };
+
+                       vcca1v8_codec: LDO_REG7 {
+                               regulator-name = "vcca1v8_codec";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <2500000>;
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vcc_3v0: LDO_REG8 {
+                               regulator-name = "vcc_3v0";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3400000>;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <3000000>;
+                               };
+                       };
+
+                       vcc3v3_s3: SWITCH_REG1 {
+                               regulator-name = "vcc3v3_s3";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vcc3v3_s0: SWITCH_REG2 {
+                               regulator-name = "vcc3v3_s0";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+               };
+       };
+
+       vdd_cpu_b: regulator@40 {
+               compatible = "silergy,syr827";
+               reg = <0x40>;
+               fcs,suspend-voltage-selector = <1>;
+               regulator-name = "vdd_cpu_b";
+               regulator-min-microvolt = <712500>;
+               regulator-max-microvolt = <1500000>;
+               regulator-ramp-delay = <1000>;
+               regulator-always-on;
+               regulator-boot-on;
+               vin-supply = <&vcc3v3_sys>;
+
+               regulator-state-mem {
+                       regulator-off-in-suspend;
+               };
+       };
+
+       vdd_gpu: regulator@41 {
+               compatible = "silergy,syr828";
+               reg = <0x41>;
+               fcs,suspend-voltage-selector = <1>;
+               regulator-name = "vdd_gpu";
+               regulator-min-microvolt = <712500>;
+               regulator-max-microvolt = <1500000>;
+               regulator-ramp-delay = <1000>;
+               regulator-always-on;
+               regulator-boot-on;
+               vin-supply = <&vcc3v3_sys>;
+
+               regulator-state-mem {
+                       regulator-off-in-suspend;
+               };
+       };
+};
+
+&i2c1 {
+       i2c-scl-rising-time-ns = <450>;
+       i2c-scl-falling-time-ns = <15>;
+       status = "okay";
+};
+
+&i2c3 {
+       i2c-scl-rising-time-ns = <450>;
+       i2c-scl-falling-time-ns = <15>;
+       status = "okay";
+};
+
+&i2c4 {
+       clock-frequency = <400000>;
+       i2c-scl-rising-time-ns = <450>;
+       i2c-scl-falling-time-ns = <15>;
+       status = "okay";
+
+       ak09911@c {
+               compatible = "asahi-kasei,ak09911";
+               reg = <0x0c>;
+               vdd-supply = <&vcc3v3_s3>;
+               vid-supply = <&vcc3v3_s3>;
+       };
+
+       mpu6500@68 {
+               compatible = "invensense,mpu6500";
+               reg = <0x68>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <RK_PC6 IRQ_TYPE_EDGE_RISING>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&gsensor_int_l>;
+               vddio-supply = <&vcc3v3_s3>;
+       };
+
+       lsm6ds3@6a {
+               compatible = "st,lsm6ds3";
+               reg = <0x6a>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <RK_PD0 IRQ_TYPE_EDGE_RISING>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&gyr_int_l>;
+               vdd-supply = <&vcc3v3_s3>;
+               vddio-supply = <&vcc3v3_s3>;
+       };
+
+       cm32181@10 {
+               compatible = "capella,cm32181";
+               reg = <0x10>;
+               interrupt-parent = <&gpio4>;
+               interrupts = <RK_PD0 IRQ_TYPE_EDGE_RISING>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&light_int_l>;
+               vdd-supply = <&vcc3v3_s3>;
+       };
+
+       fusb302@22 {
+               compatible = "fcs,fusb302";
+               reg = <0x22>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <RK_PA2 IRQ_TYPE_LEVEL_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&chg_cc_int_l>;
+               vbus-supply = <&vbus_typec>;
+       };
+};
+
+&io_domains {
+       status = "okay";
+       bt656-supply = <&vcc_3v0>;
+       audio-supply = <&vcca1v8_codec>;
+       sdmmc-supply = <&vcc_sdio>;
+       gpio1830-supply = <&vcc_3v0>;
+};
+
+&pmu_io_domains {
+       status = "okay";
+       pmu1830-supply = <&vcc_3v0>;
+};
+
+&pinctrl {
+       buttons {
+               pwr_btn: pwr-btn {
+                       rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       pmic {
+               pmic_int_l: pmic-int-l {
+                       rockchip,pins =
+                               <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       sd {
+               sdmmc0_pwr_h: sdmmc0-pwr-h {
+                       rockchip,pins =
+                               <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       usb2 {
+               vcc5v0_host_en: vcc5v0-host-en {
+                       rockchip,pins =
+                               <4 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               vcc5v0_typec_en: vcc5v0-typec-en {
+                       rockchip,pins =
+                               <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       sdio-pwrseq {
+               wifi_reg_on_h: wifi-reg-on-h {
+                       rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       wifi {
+               wifi_host_wake_l: wifi-host-wake-l {
+                       rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       bluetooth {
+               bt_reg_on_h: bt-enable-h {
+                       rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               bt_host_wake_l: bt-host-wake-l {
+                       rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               bt_wake_l: bt-wake-l {
+                       rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       mpu6500 {
+               gsensor_int_l: gsensor-int-l {
+                       rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       lsm6ds3 {
+               gyr_int_l: gyr-int-l {
+                       rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       cm32181 {
+               light_int_l: light-int-l {
+                       rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       fusb302 {
+               chg_cc_int_l: chg-cc-int-l {
+                       rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+};
+
+&pwm0 {
+       status = "okay";
+};
+
+&pwm2 {
+       status = "okay";
+};
+
+&saradc {
+       vref-supply = <&vcca1v8_s3>;
+       status = "okay";
+};
+
+&sdhci {
+       bus-width = <8>;
+       mmc-hs400-1_8v;
+       mmc-hs400-enhanced-strobe;
+       non-removable;
+       status = "okay";
+};
+
+&sdio0 {
+       bus-width = <4>;
+       cap-sd-highspeed;
+       cap-sdio-irq;
+       clock-frequency = <50000000>;
+       disable-wp;
+       keep-power-in-suspend;
+       max-frequency = <50000000>;
+       mmc-pwrseq = <&sdio_pwrseq>;
+       non-removable;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>;
+       sd-uhs-sdr104;
+       status = "okay";
+
+       brcmf: wifi@1 {
+               compatible = "brcm,bcm4329-fmac";
+               interrupt-parent = <&gpio0>;
+               interrupts = <RK_PA3 GPIO_ACTIVE_HIGH>;
+               interrupt-names = "host-wake";
+               pinctrl-names = "default";
+               pinctrl-0 = <&wifi_host_wake_l>;
+       };
+};
+
+&sdmmc {
+       bus-width = <4>;
+       cap-mmc-highspeed;
+       cap-sd-highspeed;
+       cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
+       clock-frequency = <150000000>;
+       disable-wp;
+       max-frequency = <150000000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
+       vmmc-supply = <&vcc3v0_sd>;
+       vqmmc-supply = <&vcc_sdio>;
+       status = "okay";
+};
+
+&tcphy0 {
+       status = "okay";
+};
+
+&tcphy1 {
+       status = "okay";
+};
+
+&tsadc {
+       rockchip,hw-tshut-mode = <1>;
+       rockchip,hw-tshut-polarity = <1>;
+       status = "okay";
+};
+
+&u2phy0 {
+       status = "okay";
+
+       u2phy0_otg: otg-port {
+               phy-supply = <&vbus_typec>;
+               status = "okay";
+       };
+
+       u2phy0_host: host-port {
+               phy-supply = <&vcc5v0_host>;
+               status = "okay";
+       };
+};
+
+&u2phy1 {
+       status = "okay";
+
+       u2phy1_otg: otg-port {
+               status = "okay";
+       };
+
+       u2phy1_host: host-port {
+               phy-supply = <&vcc5v0_host>;
+               status = "okay";
+       };
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+       status = "okay";
+
+       bluetooth {
+               compatible = "brcm,bcm43438-bt";
+               clocks = <&rk808 1>;
+               clock-names = "lpo";
+               device-wakeup-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_HIGH>;
+               host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>;
+               shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&bt_host_wake_l &bt_wake_l &bt_reg_on_h>;
+               vbat-supply = <&vcc3v3_sys>;
+               vddio-supply = <&vcc_1v8>;
+       };
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&usb_host0_ehci {
+       status = "okay";
+};
+
+&usb_host0_ohci {
+       status = "okay";
+};
+
+&usb_host1_ehci {
+       status = "okay";
+};
+
+&usb_host1_ohci {
+       status = "okay";
+};
+
+&usbdrd3_0 {
+       status = "okay";
+};
+
+&usbdrd_dwc3_0 {
+       status = "okay";
+       dr_mode = "otg";
+};
+
+&usbdrd3_1 {
+       status = "okay";
+};
+
+&usbdrd_dwc3_1 {
+       status = "okay";
+       dr_mode = "host";
+};
+
+&vopb {
+       status = "okay";
+};
+
+&vopb_mmu {
+       status = "okay";
+};
+
+&vopl {
+       status = "okay";
+};
+
+&vopl_mmu {
+       status = "okay";
+};
index 1e6a710..d80d6b7 100644 (file)
                haikou_pin_hog: haikou-pin-hog {
                        rockchip,pins =
                          /* LID_BTN */
-                         <RK_GPIO0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>,
+                         <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>,
                          /* BATLOW# */
-                         <RK_GPIO0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>,
+                         <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>,
                          /* SLP_BTN# */
-                         <RK_GPIO0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>,
+                         <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>,
                          /* BIOS_DISABLE# */
-                         <RK_GPIO0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;
+                         <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        leds {
                led_sd_haikou: led-sd-gpio {
                        rockchip,pins =
-                         <RK_GPIO1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+                         <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        usb2 {
                otg_vbus_drv: otg-vbus-drv {
                        rockchip,pins =
-                         <RK_GPIO0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+                         <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 0130b9f..62ea288 100644 (file)
 
 &emmc_phy {
        status = "okay";
+       drive-impedance-ohm = <33>;
 };
 
 &gmac {
        fan: fan@18 {
                compatible = "ti,amc6821";
                reg = <0x18>;
-               cooling-min-state = <0>;
-               cooling-max-state = <9>;
                #cooling-cells = <2>;
        };
 
  */
 &i2s0_2ch_bus {
        rockchip,pins =
-               <RK_GPIO3 RK_PD0 RK_FUNC_1 &pcfg_pull_none>,
-               <RK_GPIO3 RK_PD2 RK_FUNC_1 &pcfg_pull_none>,
-               <RK_GPIO3 RK_PD3 RK_FUNC_1 &pcfg_pull_none>,
-               <RK_GPIO3 RK_PD7 RK_FUNC_1 &pcfg_pull_none>;
+               <3 RK_PD0 1 &pcfg_pull_none>,
+               <3 RK_PD2 1 &pcfg_pull_none>,
+               <3 RK_PD3 1 &pcfg_pull_none>,
+               <3 RK_PD7 1 &pcfg_pull_none>;
 };
 
 &io_domains {
        i2c8 {
                i2c8_xfer_a: i2c8-xfer {
                        rockchip,pins =
-                         <RK_GPIO1 RK_PC4 RK_FUNC_1 &pcfg_pull_up>,
-                         <RK_GPIO1 RK_PC5 RK_FUNC_1 &pcfg_pull_up>;
+                         <1 RK_PC4 1 &pcfg_pull_up>,
+                         <1 RK_PC5 1 &pcfg_pull_up>;
                };
        };
 
        leds {
                led_pin_module: led-module-gpio {
                        rockchip,pins =
-                         <RK_GPIO2 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
+                         <2 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        pmic {
                pmic_int_l: pmic-int-l {
                        rockchip,pins =
-                         <RK_GPIO1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>;
+                         <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 
        usb2 {
                vcc5v0_host_en: vcc5v0-host-en {
                        rockchip,pins =
-                         <RK_GPIO4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+                         <4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 };
index 844eac9..e030627 100644 (file)
        status = "okay";
 };
 
+&gpu {
+       mali-supply = <&vdd_gpu>;
+       status = "okay";
+};
+
 &hdmi {
        ddc-i2c-bus = <&i2c3>;
        pinctrl-names = "default";
index 2927db4..c7d48d4 100644 (file)
                reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
        };
 
+       vcc12v_dcin: vcc12v-dcin {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc12v_dcin";
+               regulator-min-microvolt = <12000000>;
+               regulator-max-microvolt = <12000000>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
        vcc1v8_s0: vcc1v8-s0 {
                compatible = "regulator-fixed";
                regulator-name = "vcc1v8_s0";
                regulator-always-on;
        };
 
-       vcc_sys: vcc-sys {
+       vcc5v0_sys: vcc5v0-sys {
                compatible = "regulator-fixed";
-               regulator-name = "vcc_sys";
+               regulator-name = "vcc5v0_sys";
                regulator-min-microvolt = <5000000>;
                regulator-max-microvolt = <5000000>;
                regulator-always-on;
+               vin-supply = <&vcc12v_dcin>;
        };
 
        vcc3v3_sys: vcc3v3-sys {
@@ -40,7 +50,7 @@
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
                regulator-always-on;
-               vin-supply = <&vcc_sys>;
+               vin-supply = <&vcc5v0_sys>;
        };
 
        vcc3v3_pcie: vcc3v3-pcie-regulator {
@@ -64,7 +74,7 @@
                regulator-min-microvolt = <5000000>;
                regulator-max-microvolt = <5000000>;
                regulator-always-on;
-               vin-supply = <&vcc_sys>;
+               vin-supply = <&vcc5v0_sys>;
        };
 };
 
        status = "okay";
 };
 
+&gpu {
+       mali-supply = <&vdd_gpu>;
+       status = "okay";
+};
+
 &hdmi {
        ddc-i2c-bus = <&i2c3>;
        pinctrl-names = "default";
                regulator-ramp-delay = <1000>;
                regulator-always-on;
                regulator-boot-on;
-               vin-supply = <&vcc_sys>;
+               vin-supply = <&vcc5v0_sys>;
                status = "okay";
 
                regulator-state-mem {
                regulator-ramp-delay = <1000>;
                regulator-always-on;
                regulator-boot-on;
-               vin-supply = <&vcc_sys>;
+               vin-supply = <&vcc5v0_sys>;
                regulator-state-mem {
                        regulator-off-in-suspend;
                };
                #clock-cells = <1>;
                clock-output-names = "xin32k", "rk808-clkout2";
 
-               vcc1-supply = <&vcc_sys>;
-               vcc2-supply = <&vcc_sys>;
-               vcc3-supply = <&vcc_sys>;
-               vcc4-supply = <&vcc_sys>;
-               vcc6-supply = <&vcc_sys>;
-               vcc7-supply = <&vcc_sys>;
+               vcc1-supply = <&vcc5v0_sys>;
+               vcc2-supply = <&vcc5v0_sys>;
+               vcc3-supply = <&vcc5v0_sys>;
+               vcc4-supply = <&vcc5v0_sys>;
+               vcc6-supply = <&vcc5v0_sys>;
+               vcc7-supply = <&vcc5v0_sys>;
                vcc8-supply = <&vcc3v3_sys>;
-               vcc9-supply = <&vcc_sys>;
-               vcc10-supply = <&vcc_sys>;
-               vcc11-supply = <&vcc_sys>;
+               vcc9-supply = <&vcc5v0_sys>;
+               vcc10-supply = <&vcc5v0_sys>;
+               vcc11-supply = <&vcc5v0_sys>;
                vcc12-supply = <&vcc3v3_sys>;
                vddio-supply = <&vcc_1v8>;
 
        sdmmc {
                sdmmc_bus1: sdmmc-bus1 {
                        rockchip,pins =
-                               <4 8 RK_FUNC_1 &pcfg_pull_up_8ma>;
+                               <4 RK_PB0 1 &pcfg_pull_up_8ma>;
                };
 
                sdmmc_bus4: sdmmc-bus4 {
                        rockchip,pins =
-                               <4 8 RK_FUNC_1 &pcfg_pull_up_8ma>,
-                               <4 9 RK_FUNC_1 &pcfg_pull_up_8ma>,
-                               <4 10 RK_FUNC_1 &pcfg_pull_up_8ma>,
-                               <4 11 RK_FUNC_1 &pcfg_pull_up_8ma>;
+                               <4 RK_PB0 1 &pcfg_pull_up_8ma>,
+                               <4 RK_PB1 1 &pcfg_pull_up_8ma>,
+                               <4 RK_PB2 1 &pcfg_pull_up_8ma>,
+                               <4 RK_PB3 1 &pcfg_pull_up_8ma>;
                };
 
                sdmmc_clk: sdmmc-clk {
                        rockchip,pins =
-                               <4 12 RK_FUNC_1 &pcfg_pull_none_18ma>;
+                               <4 RK_PB4 1 &pcfg_pull_none_18ma>;
                };
 
                sdmmc_cmd: sdmmc-cmd {
                        rockchip,pins =
-                               <4 13 RK_FUNC_1 &pcfg_pull_up_8ma>;
+                               <4 RK_PB5 1 &pcfg_pull_up_8ma>;
                };
        };
 
        sdio0 {
                sdio0_bus4: sdio0-bus4 {
                        rockchip,pins =
-                               <2 20 RK_FUNC_1 &pcfg_pull_up_20ma>,
-                               <2 21 RK_FUNC_1 &pcfg_pull_up_20ma>,
-                               <2 22 RK_FUNC_1 &pcfg_pull_up_20ma>,
-                               <2 23 RK_FUNC_1 &pcfg_pull_up_20ma>;
+                               <2 RK_PC4 1 &pcfg_pull_up_20ma>,
+                               <2 RK_PC5 1 &pcfg_pull_up_20ma>,
+                               <2 RK_PC6 1 &pcfg_pull_up_20ma>,
+                               <2 RK_PC7 1 &pcfg_pull_up_20ma>;
                };
 
                sdio0_cmd: sdio0-cmd {
                        rockchip,pins =
-                               <2 24 RK_FUNC_1 &pcfg_pull_up_20ma>;
+                               <2 RK_PD0 1 &pcfg_pull_up_20ma>;
                };
 
                sdio0_clk: sdio0-clk {
                        rockchip,pins =
-                               <2 25 RK_FUNC_1 &pcfg_pull_none_20ma>;
+                               <2 RK_PD1 1 &pcfg_pull_none_20ma>;
                };
        };
 
        pmic {
                pmic_int_l: pmic-int-l {
                        rockchip,pins =
-                               <1 21 RK_FUNC_GPIO &pcfg_pull_up>;
+                               <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                vsel1_gpio: vsel1-gpio {
                        rockchip,pins =
-                               <1 17 RK_FUNC_GPIO &pcfg_pull_down>;
+                               <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>;
                };
 
                vsel2_gpio: vsel2-gpio {
                        rockchip,pins =
-                               <1 14 RK_FUNC_GPIO &pcfg_pull_down>;
+                               <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>;
                };
        };
 
index 1f2394e..20ec7d1 100644 (file)
        status = "okay";
 };
 
+&hdmi_sound {
+       status = "okay";
+};
+
 &gpu {
        mali-supply = <&vdd_gpu>;
        status = "okay";
        status = "okay";
 
        bt656-supply = <&vcc1v8_dvp>;
-       audio-supply = <&vcca1v8_codec>;
+       audio-supply = <&vcc_3v0>;
        sdmmc-supply = <&vcc_sdio>;
        gpio1830-supply = <&vcc_3v0>;
 };
index 946d358..04623e5 100644 (file)
        fan {
                motor_pwr: motor-pwr {
                        rockchip,pins =
-                               <RK_GPIO1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
        sd {
                sdmmc0_pwr_h: sdmmc0-pwr-h {
                        rockchip,pins =
-                               <RK_GPIO0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
+                               <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
index db9d948..196ac9b 100644 (file)
@@ -71,6 +71,7 @@
                        compatible = "arm,cortex-a53";
                        reg = <0x0 0x0>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <485>;
                        clocks = <&cru ARMCLKL>;
                        #cooling-cells = <2>; /* min followed by max */
                        dynamic-power-coefficient = <100>;
@@ -82,6 +83,7 @@
                        compatible = "arm,cortex-a53";
                        reg = <0x0 0x1>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <485>;
                        clocks = <&cru ARMCLKL>;
                        #cooling-cells = <2>; /* min followed by max */
                        dynamic-power-coefficient = <100>;
@@ -93,6 +95,7 @@
                        compatible = "arm,cortex-a53";
                        reg = <0x0 0x2>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <485>;
                        clocks = <&cru ARMCLKL>;
                        #cooling-cells = <2>; /* min followed by max */
                        dynamic-power-coefficient = <100>;
                        compatible = "arm,cortex-a53";
                        reg = <0x0 0x3>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <485>;
                        clocks = <&cru ARMCLKL>;
                        #cooling-cells = <2>; /* min followed by max */
                        dynamic-power-coefficient = <100>;
                        compatible = "arm,cortex-a72";
                        reg = <0x0 0x100>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <1024>;
                        clocks = <&cru ARMCLKB>;
                        #cooling-cells = <2>; /* min followed by max */
                        dynamic-power-coefficient = <436>;
                        compatible = "arm,cortex-a72";
                        reg = <0x0 0x101>;
                        enable-method = "psci";
+                       capacity-dmips-mhz = <1024>;
                        clocks = <&cru ARMCLKB>;
                        #cooling-cells = <2>; /* min followed by max */
                        dynamic-power-coefficient = <436>;
                phys = <&emmc_phy>;
                phy-names = "phy_arasan";
                power-domains = <&power RK3399_PD_EMMC>;
+               disable-cqe-dcmd;
                status = "disabled";
        };
 
                        clock-names = "refclk";
                        #phy-cells = <1>;
                        resets = <&cru SRST_PCIEPHY>;
+                       drive-impedance-ohm = <50>;
                        reset-names = "phy";
                        status = "disabled";
                };
 
                clock {
                        clk_32k: clk-32k {
-                               rockchip,pins = <0 0 RK_FUNC_2 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA0 2 &pcfg_pull_none>;
                        };
                };
 
                edp {
                        edp_hpd: edp-hpd {
                                rockchip,pins =
-                                       <4 23 RK_FUNC_2 &pcfg_pull_none>;
+                                       <4 RK_PC7 2 &pcfg_pull_none>;
                        };
                };
 
                        rgmii_pins: rgmii-pins {
                                rockchip,pins =
                                        /* mac_txclk */
-                                       <3 17 RK_FUNC_1 &pcfg_pull_none_13ma>,
+                                       <3 RK_PC1 1 &pcfg_pull_none_13ma>,
                                        /* mac_rxclk */
-                                       <3 14 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PB6 1 &pcfg_pull_none>,
                                        /* mac_mdio */
-                                       <3 13 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PB5 1 &pcfg_pull_none>,
                                        /* mac_txen */
-                                       <3 12 RK_FUNC_1 &pcfg_pull_none_13ma>,
+                                       <3 RK_PB4 1 &pcfg_pull_none_13ma>,
                                        /* mac_clk */
-                                       <3 11 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PB3 1 &pcfg_pull_none>,
                                        /* mac_rxdv */
-                                       <3 9 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PB1 1 &pcfg_pull_none>,
                                        /* mac_mdc */
-                                       <3 8 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PB0 1 &pcfg_pull_none>,
                                        /* mac_rxd1 */
-                                       <3 7 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PA7 1 &pcfg_pull_none>,
                                        /* mac_rxd0 */
-                                       <3 6 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PA6 1 &pcfg_pull_none>,
                                        /* mac_txd1 */
-                                       <3 5 RK_FUNC_1 &pcfg_pull_none_13ma>,
+                                       <3 RK_PA5 1 &pcfg_pull_none_13ma>,
                                        /* mac_txd0 */
-                                       <3 4 RK_FUNC_1 &pcfg_pull_none_13ma>,
+                                       <3 RK_PA4 1 &pcfg_pull_none_13ma>,
                                        /* mac_rxd3 */
-                                       <3 3 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PA3 1 &pcfg_pull_none>,
                                        /* mac_rxd2 */
-                                       <3 2 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PA2 1 &pcfg_pull_none>,
                                        /* mac_txd3 */
-                                       <3 1 RK_FUNC_1 &pcfg_pull_none_13ma>,
+                                       <3 RK_PA1 1 &pcfg_pull_none_13ma>,
                                        /* mac_txd2 */
-                                       <3 0 RK_FUNC_1 &pcfg_pull_none_13ma>;
+                                       <3 RK_PA0 1 &pcfg_pull_none_13ma>;
                        };
 
                        rmii_pins: rmii-pins {
                                rockchip,pins =
                                        /* mac_mdio */
-                                       <3 13 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PB5 1 &pcfg_pull_none>,
                                        /* mac_txen */
-                                       <3 12 RK_FUNC_1 &pcfg_pull_none_13ma>,
+                                       <3 RK_PB4 1 &pcfg_pull_none_13ma>,
                                        /* mac_clk */
-                                       <3 11 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PB3 1 &pcfg_pull_none>,
                                        /* mac_rxer */
-                                       <3 10 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PB2 1 &pcfg_pull_none>,
                                        /* mac_rxdv */
-                                       <3 9 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PB1 1 &pcfg_pull_none>,
                                        /* mac_mdc */
-                                       <3 8 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PB0 1 &pcfg_pull_none>,
                                        /* mac_rxd1 */
-                                       <3 7 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PA7 1 &pcfg_pull_none>,
                                        /* mac_rxd0 */
-                                       <3 6 RK_FUNC_1 &pcfg_pull_none>,
+                                       <3 RK_PA6 1 &pcfg_pull_none>,
                                        /* mac_txd1 */
-                                       <3 5 RK_FUNC_1 &pcfg_pull_none_13ma>,
+                                       <3 RK_PA5 1 &pcfg_pull_none_13ma>,
                                        /* mac_txd0 */
-                                       <3 4 RK_FUNC_1 &pcfg_pull_none_13ma>;
+                                       <3 RK_PA4 1 &pcfg_pull_none_13ma>;
                        };
                };
 
                i2c0 {
                        i2c0_xfer: i2c0-xfer {
                                rockchip,pins =
-                                       <1 15 RK_FUNC_2 &pcfg_pull_none>,
-                                       <1 16 RK_FUNC_2 &pcfg_pull_none>;
+                                       <1 RK_PB7 2 &pcfg_pull_none>,
+                                       <1 RK_PC0 2 &pcfg_pull_none>;
                        };
                };
 
                i2c1 {
                        i2c1_xfer: i2c1-xfer {
                                rockchip,pins =
-                                       <4 2 RK_FUNC_1 &pcfg_pull_none>,
-                                       <4 1 RK_FUNC_1 &pcfg_pull_none>;
+                                       <4 RK_PA2 1 &pcfg_pull_none>,
+                                       <4 RK_PA1 1 &pcfg_pull_none>;
                        };
                };
 
                i2c2 {
                        i2c2_xfer: i2c2-xfer {
                                rockchip,pins =
-                                       <2 1 RK_FUNC_2 &pcfg_pull_none_12ma>,
-                                       <2 0 RK_FUNC_2 &pcfg_pull_none_12ma>;
+                                       <2 RK_PA1 2 &pcfg_pull_none_12ma>,
+                                       <2 RK_PA0 2 &pcfg_pull_none_12ma>;
                        };
                };
 
                i2c3 {
                        i2c3_xfer: i2c3-xfer {
                                rockchip,pins =
-                                       <4 17 RK_FUNC_1 &pcfg_pull_none>,
-                                       <4 16 RK_FUNC_1 &pcfg_pull_none>;
+                                       <4 RK_PC1 1 &pcfg_pull_none>,
+                                       <4 RK_PC0 1 &pcfg_pull_none>;
                        };
                };
 
                i2c4 {
                        i2c4_xfer: i2c4-xfer {
                                rockchip,pins =
-                                       <1 12 RK_FUNC_1 &pcfg_pull_none>,
-                                       <1 11 RK_FUNC_1 &pcfg_pull_none>;
+                                       <1 RK_PB4 1 &pcfg_pull_none>,
+                                       <1 RK_PB3 1 &pcfg_pull_none>;
                        };
                };
 
                i2c5 {
                        i2c5_xfer: i2c5-xfer {
                                rockchip,pins =
-                                       <3 11 RK_FUNC_2 &pcfg_pull_none>,
-                                       <3 10 RK_FUNC_2 &pcfg_pull_none>;
+                                       <3 RK_PB3 2 &pcfg_pull_none>,
+                                       <3 RK_PB2 2 &pcfg_pull_none>;
                        };
                };
 
                i2c6 {
                        i2c6_xfer: i2c6-xfer {
                                rockchip,pins =
-                                       <2 10 RK_FUNC_2 &pcfg_pull_none>,
-                                       <2 9 RK_FUNC_2 &pcfg_pull_none>;
+                                       <2 RK_PB2 2 &pcfg_pull_none>,
+                                       <2 RK_PB1 2 &pcfg_pull_none>;
                        };
                };
 
                i2c7 {
                        i2c7_xfer: i2c7-xfer {
                                rockchip,pins =
-                                       <2 8 RK_FUNC_2 &pcfg_pull_none>,
-                                       <2 7 RK_FUNC_2 &pcfg_pull_none>;
+                                       <2 RK_PB0 2 &pcfg_pull_none>,
+                                       <2 RK_PA7 2 &pcfg_pull_none>;
                        };
                };
 
                i2c8 {
                        i2c8_xfer: i2c8-xfer {
                                rockchip,pins =
-                                       <1 21 RK_FUNC_1 &pcfg_pull_none>,
-                                       <1 20 RK_FUNC_1 &pcfg_pull_none>;
+                                       <1 RK_PC5 1 &pcfg_pull_none>,
+                                       <1 RK_PC4 1 &pcfg_pull_none>;
                        };
                };
 
                i2s0 {
                        i2s0_2ch_bus: i2s0-2ch-bus {
                                rockchip,pins =
-                                       <3 24 RK_FUNC_1 &pcfg_pull_none>,
-                                       <3 25 RK_FUNC_1 &pcfg_pull_none>,
-                                       <3 26 RK_FUNC_1 &pcfg_pull_none>,
-                                       <3 27 RK_FUNC_1 &pcfg_pull_none>,
-                                       <3 31 RK_FUNC_1 &pcfg_pull_none>,
-                                       <4 0 RK_FUNC_1 &pcfg_pull_none>;
+                                       <3 RK_PD0 1 &pcfg_pull_none>,
+                                       <3 RK_PD1 1 &pcfg_pull_none>,
+                                       <3 RK_PD2 1 &pcfg_pull_none>,
+                                       <3 RK_PD3 1 &pcfg_pull_none>,
+                                       <3 RK_PD7 1 &pcfg_pull_none>,
+                                       <4 RK_PA0 1 &pcfg_pull_none>;
                        };
 
                        i2s0_8ch_bus: i2s0-8ch-bus {
                                rockchip,pins =
-                                       <3 24 RK_FUNC_1 &pcfg_pull_none>,
-                                       <3 25 RK_FUNC_1 &pcfg_pull_none>,
-                                       <3 26 RK_FUNC_1 &pcfg_pull_none>,
-                                       <3 27 RK_FUNC_1 &pcfg_pull_none>,
-                                       <3 28 RK_FUNC_1 &pcfg_pull_none>,
-                                       <3 29 RK_FUNC_1 &pcfg_pull_none>,
-                                       <3 30 RK_FUNC_1 &pcfg_pull_none>,
-                                       <3 31 RK_FUNC_1 &pcfg_pull_none>,
-                                       <4 0 RK_FUNC_1 &pcfg_pull_none>;
+                                       <3 RK_PD0 1 &pcfg_pull_none>,
+                                       <3 RK_PD1 1 &pcfg_pull_none>,
+                                       <3 RK_PD2 1 &pcfg_pull_none>,
+                                       <3 RK_PD3 1 &pcfg_pull_none>,
+                                       <3 RK_PD4 1 &pcfg_pull_none>,
+                                       <3 RK_PD5 1 &pcfg_pull_none>,
+                                       <3 RK_PD6 1 &pcfg_pull_none>,
+                                       <3 RK_PD7 1 &pcfg_pull_none>,
+                                       <4 RK_PA0 1 &pcfg_pull_none>;
                        };
                };
 
                i2s1 {
                        i2s1_2ch_bus: i2s1-2ch-bus {
                                rockchip,pins =
-                                       <4 3 RK_FUNC_1 &pcfg_pull_none>,
-                                       <4 4 RK_FUNC_1 &pcfg_pull_none>,
-                                       <4 5 RK_FUNC_1 &pcfg_pull_none>,
-                                       <4 6 RK_FUNC_1 &pcfg_pull_none>,
-                                       <4 7 RK_FUNC_1 &pcfg_pull_none>;
+                                       <4 RK_PA3 1 &pcfg_pull_none>,
+                                       <4 RK_PA4 1 &pcfg_pull_none>,
+                                       <4 RK_PA5 1 &pcfg_pull_none>,
+                                       <4 RK_PA6 1 &pcfg_pull_none>,
+                                       <4 RK_PA7 1 &pcfg_pull_none>;
                        };
                };
 
                sdio0 {
                        sdio0_bus1: sdio0-bus1 {
                                rockchip,pins =
-                                       <2 RK_PC4 RK_FUNC_1 &pcfg_pull_up>;
+                                       <2 RK_PC4 1 &pcfg_pull_up>;
                        };
 
                        sdio0_bus4: sdio0-bus4 {
                                rockchip,pins =
-                                       <2 RK_PC4 RK_FUNC_1 &pcfg_pull_up>,
-                                       <2 RK_PC5 RK_FUNC_1 &pcfg_pull_up>,
-                                       <2 RK_PC6 RK_FUNC_1 &pcfg_pull_up>,
-                                       <2 RK_PC7 RK_FUNC_1 &pcfg_pull_up>;
+                                       <2 RK_PC4 1 &pcfg_pull_up>,
+                                       <2 RK_PC5 1 &pcfg_pull_up>,
+                                       <2 RK_PC6 1 &pcfg_pull_up>,
+                                       <2 RK_PC7 1 &pcfg_pull_up>;
                        };
 
                        sdio0_cmd: sdio0-cmd {
                                rockchip,pins =
-                                       <2 RK_PD0 RK_FUNC_1 &pcfg_pull_up>;
+                                       <2 RK_PD0 1 &pcfg_pull_up>;
                        };
 
                        sdio0_clk: sdio0-clk {
                                rockchip,pins =
-                                       <2 RK_PD1 RK_FUNC_1 &pcfg_pull_none>;
+                                       <2 RK_PD1 1 &pcfg_pull_none>;
                        };
 
                        sdio0_cd: sdio0-cd {
                                rockchip,pins =
-                                       <2 RK_PD2 RK_FUNC_1 &pcfg_pull_up>;
+                                       <2 RK_PD2 1 &pcfg_pull_up>;
                        };
 
                        sdio0_pwr: sdio0-pwr {
                                rockchip,pins =
-                                       <2 RK_PD3 RK_FUNC_1 &pcfg_pull_up>;
+                                       <2 RK_PD3 1 &pcfg_pull_up>;
                        };
 
                        sdio0_bkpwr: sdio0-bkpwr {
                                rockchip,pins =
-                                       <2 RK_PD4 RK_FUNC_1 &pcfg_pull_up>;
+                                       <2 RK_PD4 1 &pcfg_pull_up>;
                        };
 
                        sdio0_wp: sdio0-wp {
                                rockchip,pins =
-                                       <0 RK_PA3 RK_FUNC_1 &pcfg_pull_up>;
+                                       <0 RK_PA3 1 &pcfg_pull_up>;
                        };
 
                        sdio0_int: sdio0-int {
                                rockchip,pins =
-                                       <0 RK_PA4 RK_FUNC_1 &pcfg_pull_up>;
+                                       <0 RK_PA4 1 &pcfg_pull_up>;
                        };
                };
 
                sdmmc {
                        sdmmc_bus1: sdmmc-bus1 {
                                rockchip,pins =
-                                       <4 RK_PB0 RK_FUNC_1 &pcfg_pull_up>;
+                                       <4 RK_PB0 1 &pcfg_pull_up>;
                        };
 
                        sdmmc_bus4: sdmmc-bus4 {
                                rockchip,pins =
-                                       <4 RK_PB0 RK_FUNC_1 &pcfg_pull_up>,
-                                       <4 RK_PB1 RK_FUNC_1 &pcfg_pull_up>,
-                                       <4 RK_PB2 RK_FUNC_1 &pcfg_pull_up>,
-                                       <4 RK_PB3 RK_FUNC_1 &pcfg_pull_up>;
+                                       <4 RK_PB0 1 &pcfg_pull_up>,
+                                       <4 RK_PB1 1 &pcfg_pull_up>,
+                                       <4 RK_PB2 1 &pcfg_pull_up>,
+                                       <4 RK_PB3 1 &pcfg_pull_up>;
                        };
 
                        sdmmc_clk: sdmmc-clk {
                                rockchip,pins =
-                                       <4 RK_PB4 RK_FUNC_1 &pcfg_pull_none>;
+                                       <4 RK_PB4 1 &pcfg_pull_none>;
                        };
 
                        sdmmc_cmd: sdmmc-cmd {
                                rockchip,pins =
-                                       <4 RK_PB5 RK_FUNC_1 &pcfg_pull_up>;
+                                       <4 RK_PB5 1 &pcfg_pull_up>;
                        };
 
                        sdmmc_cd: sdmmc-cd {
                                rockchip,pins =
-                                       <0 RK_PA7 RK_FUNC_1 &pcfg_pull_up>;
+                                       <0 RK_PA7 1 &pcfg_pull_up>;
                        };
 
                        sdmmc_wp: sdmmc-wp {
                                rockchip,pins =
-                                       <0 RK_PB0 RK_FUNC_1 &pcfg_pull_up>;
+                                       <0 RK_PB0 1 &pcfg_pull_up>;
                        };
                };
 
                sleep {
                        ap_pwroff: ap-pwroff {
-                               rockchip,pins = <1 5 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PA5 1 &pcfg_pull_none>;
                        };
 
                        ddrio_pwroff: ddrio-pwroff {
-                               rockchip,pins = <0 1 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <0 RK_PA1 1 &pcfg_pull_none>;
                        };
                };
 
                spdif {
                        spdif_bus: spdif-bus {
                                rockchip,pins =
-                                       <4 21 RK_FUNC_1 &pcfg_pull_none>;
+                                       <4 RK_PC5 1 &pcfg_pull_none>;
                        };
 
                        spdif_bus_1: spdif-bus-1 {
                                rockchip,pins =
-                                       <3 RK_PC0 RK_FUNC_3 &pcfg_pull_none>;
+                                       <3 RK_PC0 3 &pcfg_pull_none>;
                        };
                };
 
                spi0 {
                        spi0_clk: spi0-clk {
                                rockchip,pins =
-                                       <3 6 RK_FUNC_2 &pcfg_pull_up>;
+                                       <3 RK_PA6 2 &pcfg_pull_up>;
                        };
                        spi0_cs0: spi0-cs0 {
                                rockchip,pins =
-                                       <3 7 RK_FUNC_2 &pcfg_pull_up>;
+                                       <3 RK_PA7 2 &pcfg_pull_up>;
                        };
                        spi0_cs1: spi0-cs1 {
                                rockchip,pins =
-                                       <3 8 RK_FUNC_2 &pcfg_pull_up>;
+                                       <3 RK_PB0 2 &pcfg_pull_up>;
                        };
                        spi0_tx: spi0-tx {
                                rockchip,pins =
-                                       <3 5 RK_FUNC_2 &pcfg_pull_up>;
+                                       <3 RK_PA5 2 &pcfg_pull_up>;
                        };
                        spi0_rx: spi0-rx {
                                rockchip,pins =
-                                       <3 4 RK_FUNC_2 &pcfg_pull_up>;
+                                       <3 RK_PA4 2 &pcfg_pull_up>;
                        };
                };
 
                spi1 {
                        spi1_clk: spi1-clk {
                                rockchip,pins =
-                                       <1 9 RK_FUNC_2 &pcfg_pull_up>;
+                                       <1 RK_PB1 2 &pcfg_pull_up>;
                        };
                        spi1_cs0: spi1-cs0 {
                                rockchip,pins =
-                                       <1 10 RK_FUNC_2 &pcfg_pull_up>;
+                                       <1 RK_PB2 2 &pcfg_pull_up>;
                        };
                        spi1_rx: spi1-rx {
                                rockchip,pins =
-                                       <1 7 RK_FUNC_2 &pcfg_pull_up>;
+                                       <1 RK_PA7 2 &pcfg_pull_up>;
                        };
                        spi1_tx: spi1-tx {
                                rockchip,pins =
-                                       <1 8 RK_FUNC_2 &pcfg_pull_up>;
+                                       <1 RK_PB0 2 &pcfg_pull_up>;
                        };
                };
 
                spi2 {
                        spi2_clk: spi2-clk {
                                rockchip,pins =
-                                       <2 11 RK_FUNC_1 &pcfg_pull_up>;
+                                       <2 RK_PB3 1 &pcfg_pull_up>;
                        };
                        spi2_cs0: spi2-cs0 {
                                rockchip,pins =
-                                       <2 12 RK_FUNC_1 &pcfg_pull_up>;
+                                       <2 RK_PB4 1 &pcfg_pull_up>;
                        };
                        spi2_rx: spi2-rx {
                                rockchip,pins =
-                                       <2 9 RK_FUNC_1 &pcfg_pull_up>;
+                                       <2 RK_PB1 1 &pcfg_pull_up>;
                        };
                        spi2_tx: spi2-tx {
                                rockchip,pins =
-                                       <2 10 RK_FUNC_1 &pcfg_pull_up>;
+                                       <2 RK_PB2 1 &pcfg_pull_up>;
                        };
                };
 
                spi3 {
                        spi3_clk: spi3-clk {
                                rockchip,pins =
-                                       <1 17 RK_FUNC_1 &pcfg_pull_up>;
+                                       <1 RK_PC1 1 &pcfg_pull_up>;
                        };
                        spi3_cs0: spi3-cs0 {
                                rockchip,pins =
-                                       <1 18 RK_FUNC_1 &pcfg_pull_up>;
+                                       <1 RK_PC2 1 &pcfg_pull_up>;
                        };
                        spi3_rx: spi3-rx {
                                rockchip,pins =
-                                       <1 15 RK_FUNC_1 &pcfg_pull_up>;
+                                       <1 RK_PB7 1 &pcfg_pull_up>;
                        };
                        spi3_tx: spi3-tx {
                                rockchip,pins =
-                                       <1 16 RK_FUNC_1 &pcfg_pull_up>;
+                                       <1 RK_PC0 1 &pcfg_pull_up>;
                        };
                };
 
                spi4 {
                        spi4_clk: spi4-clk {
                                rockchip,pins =
-                                       <3 2 RK_FUNC_2 &pcfg_pull_up>;
+                                       <3 RK_PA2 2 &pcfg_pull_up>;
                        };
                        spi4_cs0: spi4-cs0 {
                                rockchip,pins =
-                                       <3 3 RK_FUNC_2 &pcfg_pull_up>;
+                                       <3 RK_PA3 2 &pcfg_pull_up>;
                        };
                        spi4_rx: spi4-rx {
                                rockchip,pins =
-                                       <3 0 RK_FUNC_2 &pcfg_pull_up>;
+                                       <3 RK_PA0 2 &pcfg_pull_up>;
                        };
                        spi4_tx: spi4-tx {
                                rockchip,pins =
-                                       <3 1 RK_FUNC_2 &pcfg_pull_up>;
+                                       <3 RK_PA1 2 &pcfg_pull_up>;
                        };
                };
 
                spi5 {
                        spi5_clk: spi5-clk {
                                rockchip,pins =
-                                       <2 22 RK_FUNC_2 &pcfg_pull_up>;
+                                       <2 RK_PC6 2 &pcfg_pull_up>;
                        };
                        spi5_cs0: spi5-cs0 {
                                rockchip,pins =
-                                       <2 23 RK_FUNC_2 &pcfg_pull_up>;
+                                       <2 RK_PC7 2 &pcfg_pull_up>;
                        };
                        spi5_rx: spi5-rx {
                                rockchip,pins =
-                                       <2 20 RK_FUNC_2 &pcfg_pull_up>;
+                                       <2 RK_PC4 2 &pcfg_pull_up>;
                        };
                        spi5_tx: spi5-tx {
                                rockchip,pins =
-                                       <2 21 RK_FUNC_2 &pcfg_pull_up>;
+                                       <2 RK_PC5 2 &pcfg_pull_up>;
                        };
                };
 
                testclk {
                        test_clkout0: test-clkout0 {
                                rockchip,pins =
-                                       <0 0 RK_FUNC_1 &pcfg_pull_none>;
+                                       <0 RK_PA0 1 &pcfg_pull_none>;
                        };
 
                        test_clkout1: test-clkout1 {
                                rockchip,pins =
-                                       <2 25 RK_FUNC_2 &pcfg_pull_none>;
+                                       <2 RK_PD1 2 &pcfg_pull_none>;
                        };
 
                        test_clkout2: test-clkout2 {
                                rockchip,pins =
-                                       <0 8 RK_FUNC_3 &pcfg_pull_none>;
+                                       <0 RK_PB0 3 &pcfg_pull_none>;
                        };
                };
 
                tsadc {
                        otp_gpio: otp-gpio {
-                               rockchip,pins = <1 6 RK_FUNC_GPIO &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
                        };
 
                        otp_out: otp-out {
-                               rockchip,pins = <1 6 RK_FUNC_1 &pcfg_pull_none>;
+                               rockchip,pins = <1 RK_PA6 1 &pcfg_pull_none>;
                        };
                };
 
                uart0 {
                        uart0_xfer: uart0-xfer {
                                rockchip,pins =
-                                       <2 16 RK_FUNC_1 &pcfg_pull_up>,
-                                       <2 17 RK_FUNC_1 &pcfg_pull_none>;
+                                       <2 RK_PC0 1 &pcfg_pull_up>,
+                                       <2 RK_PC1 1 &pcfg_pull_none>;
                        };
 
                        uart0_cts: uart0-cts {
                                rockchip,pins =
-                                       <2 18 RK_FUNC_1 &pcfg_pull_none>;
+                                       <2 RK_PC2 1 &pcfg_pull_none>;
                        };
 
                        uart0_rts: uart0-rts {
                                rockchip,pins =
-                                       <2 19 RK_FUNC_1 &pcfg_pull_none>;
+                                       <2 RK_PC3 1 &pcfg_pull_none>;
                        };
                };
 
                uart1 {
                        uart1_xfer: uart1-xfer {
                                rockchip,pins =
-                                       <3 12 RK_FUNC_2 &pcfg_pull_up>,
-                                       <3 13 RK_FUNC_2 &pcfg_pull_none>;
+                                       <3 RK_PB4 2 &pcfg_pull_up>,
+                                       <3 RK_PB5 2 &pcfg_pull_none>;
                        };
                };
 
                uart2a {
                        uart2a_xfer: uart2a-xfer {
                                rockchip,pins =
-                                       <4 8 RK_FUNC_2 &pcfg_pull_up>,
-                                       <4 9 RK_FUNC_2 &pcfg_pull_none>;
+                                       <4 RK_PB0 2 &pcfg_pull_up>,
+                                       <4 RK_PB1 2 &pcfg_pull_none>;
                        };
                };
 
                uart2b {
                        uart2b_xfer: uart2b-xfer {
                                rockchip,pins =
-                                       <4 16 RK_FUNC_2 &pcfg_pull_up>,
-                                       <4 17 RK_FUNC_2 &pcfg_pull_none>;
+                                       <4 RK_PC0 2 &pcfg_pull_up>,
+                                       <4 RK_PC1 2 &pcfg_pull_none>;
                        };
                };
 
                uart2c {
                        uart2c_xfer: uart2c-xfer {
                                rockchip,pins =
-                                       <4 19 RK_FUNC_1 &pcfg_pull_up>,
-                                       <4 20 RK_FUNC_1 &pcfg_pull_none>;
+                                       <4 RK_PC3 1 &pcfg_pull_up>,
+                                       <4 RK_PC4 1 &pcfg_pull_none>;
                        };
                };
 
                uart3 {
                        uart3_xfer: uart3-xfer {
                                rockchip,pins =
-                                       <3 14 RK_FUNC_2 &pcfg_pull_up>,
-                                       <3 15 RK_FUNC_2 &pcfg_pull_none>;
+                                       <3 RK_PB6 2 &pcfg_pull_up>,
+                                       <3 RK_PB7 2 &pcfg_pull_none>;
                        };
 
                        uart3_cts: uart3-cts {
                                rockchip,pins =
-                                       <3 18 RK_FUNC_2 &pcfg_pull_none>;
+                                       <3 RK_PC0 2 &pcfg_pull_none>;
                        };
 
                        uart3_rts: uart3-rts {
                                rockchip,pins =
-                                       <3 19 RK_FUNC_2 &pcfg_pull_none>;
+                                       <3 RK_PC1 2 &pcfg_pull_none>;
                        };
                };
 
                uart4 {
                        uart4_xfer: uart4-xfer {
                                rockchip,pins =
-                                       <1 7 RK_FUNC_1 &pcfg_pull_up>,
-                                       <1 8 RK_FUNC_1 &pcfg_pull_none>;
+                                       <1 RK_PA7 1 &pcfg_pull_up>,
+                                       <1 RK_PB0 1 &pcfg_pull_none>;
                        };
                };
 
                uarthdcp {
                        uarthdcp_xfer: uarthdcp-xfer {
                                rockchip,pins =
-                                       <4 21 RK_FUNC_2 &pcfg_pull_up>,
-                                       <4 22 RK_FUNC_2 &pcfg_pull_none>;
+                                       <4 RK_PC5 2 &pcfg_pull_up>,
+                                       <4 RK_PC6 2 &pcfg_pull_none>;
                        };
                };
 
                pwm0 {
                        pwm0_pin: pwm0-pin {
                                rockchip,pins =
-                                       <4 RK_PC2 RK_FUNC_1 &pcfg_pull_none>;
+                                       <4 RK_PC2 1 &pcfg_pull_none>;
                        };
 
                        pwm0_pin_pull_down: pwm0-pin-pull-down {
                                rockchip,pins =
-                                       <4 RK_PC2 RK_FUNC_1 &pcfg_pull_down>;
+                                       <4 RK_PC2 1 &pcfg_pull_down>;
                        };
 
                        vop0_pwm_pin: vop0-pwm-pin {
                                rockchip,pins =
-                                       <4 RK_PC2 RK_FUNC_2 &pcfg_pull_none>;
+                                       <4 RK_PC2 2 &pcfg_pull_none>;
                        };
 
                        vop1_pwm_pin: vop1-pwm-pin {
                                rockchip,pins =
-                                       <4 RK_PC2 RK_FUNC_3 &pcfg_pull_none>;
+                                       <4 RK_PC2 3 &pcfg_pull_none>;
                        };
                };
 
                pwm1 {
                        pwm1_pin: pwm1-pin {
                                rockchip,pins =
-                                       <4 RK_PC6 RK_FUNC_1 &pcfg_pull_none>;
+                                       <4 RK_PC6 1 &pcfg_pull_none>;
                        };
 
                        pwm1_pin_pull_down: pwm1-pin-pull-down {
                                rockchip,pins =
-                                       <4 RK_PC6 RK_FUNC_1 &pcfg_pull_down>;
+                                       <4 RK_PC6 1 &pcfg_pull_down>;
                        };
                };
 
                pwm2 {
                        pwm2_pin: pwm2-pin {
                                rockchip,pins =
-                                       <1 RK_PC3 RK_FUNC_1 &pcfg_pull_none>;
+                                       <1 RK_PC3 1 &pcfg_pull_none>;
                        };
 
                        pwm2_pin_pull_down: pwm2-pin-pull-down {
                                rockchip,pins =
-                                       <1 RK_PC3 RK_FUNC_1 &pcfg_pull_down>;
+                                       <1 RK_PC3 1 &pcfg_pull_down>;
                        };
                };
 
                pwm3a {
                        pwm3a_pin: pwm3a-pin {
                                rockchip,pins =
-                                       <0 RK_PA6 RK_FUNC_1 &pcfg_pull_none>;
+                                       <0 RK_PA6 1 &pcfg_pull_none>;
                        };
                };
 
                pwm3b {
                        pwm3b_pin: pwm3b-pin {
                                rockchip,pins =
-                                       <1 RK_PB6 RK_FUNC_1 &pcfg_pull_none>;
+                                       <1 RK_PB6 1 &pcfg_pull_none>;
                        };
                };
 
                hdmi {
                        hdmi_i2c_xfer: hdmi-i2c-xfer {
                                rockchip,pins =
-                                       <4 RK_PC1 RK_FUNC_3 &pcfg_pull_none>,
-                                       <4 RK_PC0 RK_FUNC_3 &pcfg_pull_none>;
+                                       <4 RK_PC1 3 &pcfg_pull_none>,
+                                       <4 RK_PC0 3 &pcfg_pull_none>;
                        };
 
                        hdmi_cec: hdmi-cec {
                                rockchip,pins =
-                                       <4 RK_PC7 RK_FUNC_1 &pcfg_pull_none>;
+                                       <4 RK_PC7 1 &pcfg_pull_none>;
                        };
                };
 
index 11cc671..2421ec7 100644 (file)
@@ -89,6 +89,7 @@
                ti,rx-internal-delay = <0x8>;
                ti,tx-internal-delay = <0xa>;
                ti,fifo-depth = <0x1>;
+               ti,dp83867-rxctrl-strap-quirk;
        };
 };
 
index cef8167..2a3b665 100644 (file)
                ti,rx-internal-delay = <0x8>;
                ti,tx-internal-delay = <0xa>;
                ti,fifo-depth = <0x1>;
+               ti,dp83867-rxctrl-strap-quirk;
        };
 };
 
index af4d868..1780ed2 100644 (file)
@@ -21,6 +21,7 @@
                ti,rx-internal-delay = <0x8>;
                ti,tx-internal-delay = <0xa>;
                ti,fifo-depth = <0x1>;
+               ti,dp83867-rxctrl-strap-quirk;
        };
        /* Cleanup from RevA */
        /delete-node/ phy@21;
index d4ad19a..8f45614 100644 (file)
@@ -55,6 +55,7 @@
                ti,rx-internal-delay = <0x8>;
                ti,tx-internal-delay = <0xa>;
                ti,fifo-depth = <0x1>;
+               ti,dp83867-rxctrl-strap-quirk;
        };
 };
 
index 94cf509..93ce7eb 100644 (file)
                ti,rx-internal-delay = <0x8>;
                ti,tx-internal-delay = <0xa>;
                ti,fifo-depth = <0x1>;
+               ti,dp83867-rxctrl-strap-quirk;
        };
 };
 
index 460adc3..8bb0001 100644 (file)
                ti,rx-internal-delay = <0x8>;
                ti,tx-internal-delay = <0xa>;
                ti,fifo-depth = <0x1>;
+               ti,dp83867-rxctrl-strap-quirk;
        };
 };
 
index 9a8718b..4d58351 100644 (file)
@@ -29,6 +29,7 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
+CONFIG_ARCH_AGILEX=y
 CONFIG_ARCH_SUNXI=y
 CONFIG_ARCH_ALPINE=y
 CONFIG_ARCH_BCM2835=y
@@ -46,15 +47,6 @@ CONFIG_ARCH_MVEBU=y
 CONFIG_ARCH_MXC=y
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_RENESAS=y
-CONFIG_ARCH_R8A774A1=y
-CONFIG_ARCH_R8A774C0=y
-CONFIG_ARCH_R8A7795=y
-CONFIG_ARCH_R8A7796=y
-CONFIG_ARCH_R8A77965=y
-CONFIG_ARCH_R8A77970=y
-CONFIG_ARCH_R8A77980=y
-CONFIG_ARCH_R8A77990=y
-CONFIG_ARCH_R8A77995=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_ARCH_SEATTLE=y
 CONFIG_ARCH_STRATIX10=y
@@ -68,25 +60,6 @@ CONFIG_ARCH_VEXPRESS=y
 CONFIG_ARCH_XGENE=y
 CONFIG_ARCH_ZX=y
 CONFIG_ARCH_ZYNQMP=y
-CONFIG_PCI=y
-CONFIG_PCIEPORTBUS=y
-CONFIG_PCI_IOV=y
-CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_ACPI=y
-CONFIG_PCI_AARDVARK=y
-CONFIG_PCI_TEGRA=y
-CONFIG_PCIE_RCAR=y
-CONFIG_PCI_HOST_GENERIC=y
-CONFIG_PCI_XGENE=y
-CONFIG_PCI_HOST_THUNDER_PEM=y
-CONFIG_PCI_HOST_THUNDER_ECAM=y
-CONFIG_PCIE_ROCKCHIP_HOST=m
-CONFIG_PCI_LAYERSCAPE=y
-CONFIG_PCI_HISI=y
-CONFIG_PCIE_QCOM=y
-CONFIG_PCIE_ARMADA_8K=y
-CONFIG_PCIE_KIRIN=y
-CONFIG_PCIE_HISI_STB=y
 CONFIG_ARM64_VA_BITS_48=y
 CONFIG_SCHED_MC=y
 CONFIG_NUMA=y
@@ -112,6 +85,7 @@ CONFIG_ARM_SCPI_CPUFREQ=y
 CONFIG_ARM_TEGRA186_CPUFREQ=y
 CONFIG_ARM_SCPI_PROTOCOL=y
 CONFIG_RASPBERRYPI_FIRMWARE=y
+CONFIG_INTEL_STRATIX10_SERVICE=y
 CONFIG_TI_SCI_PROTOCOL=y
 CONFIG_EFI_CAPSULE_LOADER=y
 CONFIG_IMX_SCU=y
@@ -196,11 +170,30 @@ CONFIG_MAC80211_LEDS=y
 CONFIG_RFKILL=m
 CONFIG_NET_9P=y
 CONFIG_NET_9P_VIRTIO=y
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCI_IOV=y
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_ACPI=y
+CONFIG_PCI_AARDVARK=y
+CONFIG_PCI_TEGRA=y
+CONFIG_PCIE_RCAR=y
+CONFIG_PCI_HOST_GENERIC=y
+CONFIG_PCI_XGENE=y
+CONFIG_PCIE_ALTERA=y
+CONFIG_PCIE_ALTERA_MSI=y
+CONFIG_PCI_HOST_THUNDER_PEM=y
+CONFIG_PCI_HOST_THUNDER_ECAM=y
+CONFIG_PCIE_ROCKCHIP_HOST=m
+CONFIG_PCI_LAYERSCAPE=y
+CONFIG_PCI_HISI=y
+CONFIG_PCIE_QCOM=y
+CONFIG_PCIE_ARMADA_8K=y
+CONFIG_PCIE_KIRIN=y
+CONFIG_PCIE_HISI_STB=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_DMA_CMA=y
-CONFIG_CMA_SIZE_MBYTES=32
 CONFIG_HISILICON_LPC=y
 CONFIG_SIMPLE_PM_BUS=y
 CONFIG_MTD=y
@@ -222,10 +215,10 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_SAS_ATA=y
 CONFIG_SCSI_HISI_SAS=y
 CONFIG_SCSI_HISI_SAS_PCI=y
-CONFIG_SCSI_UFSHCD=m
-CONFIG_SCSI_UFSHCD_PLATFORM=m
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
 CONFIG_SCSI_UFS_QCOM=m
-CONFIG_SCSI_UFS_HISI=m
+CONFIG_SCSI_UFS_HISI=y
 CONFIG_ATA=y
 CONFIG_SATA_AHCI=y
 CONFIG_SATA_AHCI_PLATFORM=y
@@ -364,6 +357,7 @@ CONFIG_SPI=y
 CONFIG_SPI_ARMADA_3700=y
 CONFIG_SPI_BCM2835=m
 CONFIG_SPI_BCM2835AUX=m
+CONFIG_SPI_NXP_FLEXSPI=y
 CONFIG_SPI_MESON_SPICC=m
 CONFIG_SPI_MESON_SPIFC=m
 CONFIG_SPI_ORION=y
@@ -372,7 +366,7 @@ CONFIG_SPI_ROCKCHIP=y
 CONFIG_SPI_QUP=y
 CONFIG_SPI_S3C64XX=y
 CONFIG_SPI_SPIDEV=m
-CONFIG_SPI_NXP_FLEXSPI=y
+CONFIG_SPI_SUN6I=y
 CONFIG_SPMI=y
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_PINCTRL_MAX77620=y
@@ -387,7 +381,6 @@ CONFIG_PINCTRL_QCS404=y
 CONFIG_PINCTRL_QDF2XXX=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
 CONFIG_PINCTRL_SDM845=y
-CONFIG_PINCTRL_MTK_MOORE=y
 CONFIG_GPIO_DWAPB=y
 CONFIG_GPIO_MB86S7X=y
 CONFIG_GPIO_PL061=y
@@ -408,6 +401,7 @@ CONFIG_BATTERY_SBS=m
 CONFIG_BATTERY_BQ27XXX=y
 CONFIG_SENSORS_ARM_SCPI=y
 CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_PWM_FAN=m
 CONFIG_SENSORS_RASPBERRYPI_HWMON=m
 CONFIG_SENSORS_INA2XX=m
 CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
@@ -432,6 +426,7 @@ CONFIG_MESON_WATCHDOG=m
 CONFIG_RENESAS_WDT=y
 CONFIG_UNIPHIER_WATCHDOG=y
 CONFIG_BCM2835_WDT=y
+CONFIG_MFD_ALTERA_SYSMGR=y
 CONFIG_MFD_BD9571MWV=y
 CONFIG_MFD_AXP20X_I2C=y
 CONFIG_MFD_AXP20X_RSB=y
@@ -472,14 +467,14 @@ CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 # CONFIG_DVB_NET is not set
-CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_MEDIA_USB_SUPPORT=y
 CONFIG_USB_VIDEO_CLASS=m
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_SUN6I_CSI=m
 CONFIG_V4L_MEM2MEM_DRIVERS=y
 CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m
 CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
 CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m
-CONFIG_VIDEO_SUN6I_CSI=m
 CONFIG_VIDEO_RENESAS_FCP=m
 CONFIG_VIDEO_RENESAS_VSP1=m
 CONFIG_DRM=m
@@ -498,7 +493,6 @@ CONFIG_ROCKCHIP_DW_HDMI=y
 CONFIG_ROCKCHIP_DW_MIPI_DSI=y
 CONFIG_ROCKCHIP_INNO_HDMI=y
 CONFIG_DRM_RCAR_DU=m
-CONFIG_DRM_RCAR_LVDS=m
 CONFIG_DRM_SUN4I=m
 CONFIG_DRM_SUN8I_DW_HDMI=m
 CONFIG_DRM_SUN8I_MIXER=m
@@ -513,7 +507,6 @@ CONFIG_DRM_MESON=m
 CONFIG_DRM_PL111=m
 CONFIG_FB=y
 CONFIG_FB_MODE_HELPERS=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_GENERIC=m
 CONFIG_BACKLIGHT_PWM=m
 CONFIG_BACKLIGHT_LP855X=m
@@ -522,22 +515,24 @@ CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_VGA16 is not set
 CONFIG_SOUND=y
 CONFIG_SND=y
+CONFIG_SND_HDA_TEGRA=m
+CONFIG_SND_HDA_CODEC_HDMI=m
 CONFIG_SND_SOC=y
 CONFIG_SND_BCM2835_SOC_I2S=m
+CONFIG_SND_MESON_AXG_SOUND_CARD=m
 CONFIG_SND_SOC_ROCKCHIP=m
 CONFIG_SND_SOC_ROCKCHIP_SPDIF=m
 CONFIG_SND_SOC_ROCKCHIP_RT5645=m
 CONFIG_SND_SOC_RK3399_GRU_SOUND=m
-CONFIG_SND_MESON_AXG_SOUND_CARD=m
 CONFIG_SND_SOC_SAMSUNG=y
 CONFIG_SND_SOC_RCAR=m
 CONFIG_SND_SOC_AK4613=m
-CONFIG_SND_SOC_PCM3168A_I2C=m
-CONFIG_SND_SIMPLE_CARD=m
-CONFIG_SND_AUDIO_GRAPH_CARD=m
 CONFIG_SND_SOC_ES7134=m
 CONFIG_SND_SOC_ES7241=m
+CONFIG_SND_SOC_PCM3168A_I2C=m
 CONFIG_SND_SOC_TAS571X=m
+CONFIG_SND_SIMPLE_CARD=m
+CONFIG_SND_AUDIO_GRAPH_CARD=m
 CONFIG_I2C_HID=m
 CONFIG_USB=y
 CONFIG_USB_OTG=y
@@ -605,6 +600,7 @@ CONFIG_EDAC_GHES=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_MAX77686=y
 CONFIG_RTC_DRV_RK808=m
+CONFIG_RTC_DRV_RX8581=m
 CONFIG_RTC_DRV_S5M=y
 CONFIG_RTC_DRV_DS3232=y
 CONFIG_RTC_DRV_EFI=y
@@ -619,6 +615,7 @@ CONFIG_RTC_DRV_XGENE=y
 CONFIG_DMADEVICES=y
 CONFIG_DMA_BCM2835=m
 CONFIG_K3_DMA=y
+CONFIG_MV_XOR=y
 CONFIG_MV_XOR_V2=y
 CONFIG_PL330_DMA=y
 CONFIG_TEGRA20_APB_DMA=y
@@ -676,7 +673,6 @@ CONFIG_RPMSG_QCOM_GLINK_RPM=y
 CONFIG_RPMSG_QCOM_GLINK_SMEM=m
 CONFIG_RPMSG_QCOM_SMD=y
 CONFIG_RASPBERRYPI_POWER=y
-CONFIG_IMX_GPCV2_PM_DOMAINS=y
 CONFIG_QCOM_COMMAND_DB=y
 CONFIG_QCOM_GENI_SE=y
 CONFIG_QCOM_GLINK_SSR=m
@@ -685,6 +681,15 @@ CONFIG_QCOM_SMEM=y
 CONFIG_QCOM_SMD_RPM=y
 CONFIG_QCOM_SMP2P=y
 CONFIG_QCOM_SMSM=y
+CONFIG_ARCH_R8A774A1=y
+CONFIG_ARCH_R8A774C0=y
+CONFIG_ARCH_R8A7795=y
+CONFIG_ARCH_R8A7796=y
+CONFIG_ARCH_R8A77965=y
+CONFIG_ARCH_R8A77970=y
+CONFIG_ARCH_R8A77980=y
+CONFIG_ARCH_R8A77990=y
+CONFIG_ARCH_R8A77995=y
 CONFIG_ROCKCHIP_PM_DOMAINS=y
 CONFIG_ARCH_TEGRA_132_SOC=y
 CONFIG_ARCH_TEGRA_210_SOC=y
@@ -740,6 +745,12 @@ CONFIG_QCOM_QFPROM=y
 CONFIG_ROCKCHIP_EFUSE=y
 CONFIG_UNIPHIER_EFUSE=y
 CONFIG_MESON_EFUSE=m
+CONFIG_FPGA=y
+CONFIG_FPGA_MGR_STRATIX10_SOC=m
+CONFIG_FPGA_BRIDGE=m
+CONFIG_ALTERA_FREEZE_BRIDGE=m
+CONFIG_FPGA_REGION=m
+CONFIG_OF_FPGA_REGION=m
 CONFIG_TEE=y
 CONFIG_OPTEE=y
 CONFIG_EXT2_FS=y
@@ -770,6 +781,8 @@ CONFIG_NLS_ISO8859_1=y
 CONFIG_SECURITY=y
 CONFIG_CRYPTO_ECHAINIV=y
 CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_FS=y
index eb0df23..1de6e05 100644 (file)
@@ -17,10 +17,8 @@ generic-y += mmiowb.h
 generic-y += msi.h
 generic-y += qrwlock.h
 generic-y += qspinlock.h
-generic-y += segment.h
 generic-y += serial.h
 generic-y += set_memory.h
-generic-y += sizes.h
 generic-y += switch_to.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
index 355e552..c7f67da 100644 (file)
@@ -3,7 +3,7 @@
 #ifndef __ASM_BOOT_H
 #define __ASM_BOOT_H
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 /*
  * arm64 requires the DTB to be 8 byte aligned and
index f210bcf..bc895c8 100644 (file)
@@ -401,7 +401,7 @@ unsigned long cpu_get_elf_hwcap2(void);
 #define cpu_have_named_feature(name) cpu_have_feature(cpu_feature(name))
 
 /* System capability check for constant caps */
-static inline bool __cpus_have_const_cap(int num)
+static __always_inline bool __cpus_have_const_cap(int num)
 {
        if (num >= ARM64_NCAPS)
                return false;
@@ -415,7 +415,7 @@ static inline bool cpus_have_cap(unsigned int num)
        return test_bit(num, cpu_hwcaps);
 }
 
-static inline bool cpus_have_const_cap(int num)
+static __always_inline bool cpus_have_const_cap(int num)
 {
        if (static_branch_likely(&arm64_const_caps_ready))
                return __cpus_have_const_cap(num);
index c6a07a3..4aad638 100644 (file)
@@ -70,8 +70,4 @@ extern void set_huge_swap_pte_at(struct mm_struct *mm, unsigned long addr,
 
 #include <asm-generic/hugetlb.h>
 
-#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE
-static inline bool gigantic_page_supported(void) { return true; }
-#endif
-
 #endif /* __ASM_HUGETLB_H */
index 2cb8248..8ffcf5a 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/types.h>
 #include <asm/bug.h>
 #include <asm/page-def.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 /*
  * Size of the PCI I/O space. This must remain a power of two so that
index 40e2d7e..d2adffb 100644 (file)
@@ -48,7 +48,7 @@
 #include <asm/numa.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/tlb.h>
 #include <asm/alternative.h>
 
@@ -578,24 +578,11 @@ void free_initmem(void)
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
-
-static int keep_initrd __initdata;
-
 void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
-       if (!keep_initrd) {
-               free_reserved_area((void *)start, (void *)end, 0, "initrd");
-               memblock_free(__virt_to_phys(start), end - start);
-       }
-}
-
-static int __init keepinitrd_setup(char *__unused)
-{
-       keep_initrd = 1;
-       return 1;
+       free_reserved_area((void *)start, (void *)end, 0, "initrd");
+       memblock_free(__virt_to_phys(start), end - start);
 }
-
-__setup("keepinitrd", keepinitrd_setup);
 #endif
 
 /*
index ef82312..a170c63 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/kernel-pgtable.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/tlb.h>
 #include <asm/mmu_context.h>
 #include <asm/ptdump.h>
@@ -1065,8 +1065,8 @@ int p4d_free_pud_page(p4d_t *p4d, unsigned long addr)
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
-                   bool want_memblock)
+int arch_add_memory(int nid, u64 start, u64 size,
+                       struct mhp_restrictions *restrictions)
 {
        int flags = 0;
 
@@ -1077,6 +1077,6 @@ int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
                             size, PAGE_KERNEL, __pgd_pgtable_alloc, flags);
 
        return __add_pages(nid, start >> PAGE_SHIFT, size >> PAGE_SHIFT,
-                          altmap, want_memblock);
+                          restrictions);
 }
 #endif
index 6b168d3..2162eb3 100644 (file)
@@ -30,7 +30,6 @@ generic-y += pci.h
 generic-y += percpu.h
 generic-y += pgalloc.h
 generic-y += preempt.h
-generic-y += segment.h
 generic-y += serial.h
 generic-y += shmparam.h
 generic-y += tlbflush.h
index fe582c3..573242b 100644 (file)
@@ -68,15 +68,3 @@ void __init mem_init(void)
 
        mem_init_print_info(NULL);
 }
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void __init free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
-
-void __init free_initmem(void)
-{
-       free_initmem_default(-1);
-}
index 61c01db..ecfc4b4 100644 (file)
@@ -23,6 +23,7 @@ config H8300
        select HAVE_ARCH_KGDB
        select HAVE_ARCH_HASH
        select CPU_NO_EFFICIENT_FFS
+       select UACCESS_MEMCPY
 
 config CPU_BIG_ENDIAN
        def_bool y
index 123d8f5..79cd1e6 100644 (file)
@@ -42,12 +42,12 @@ generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += serial.h
 generic-y += shmparam.h
-generic-y += sizes.h
 generic-y += spinlock.h
 generic-y += timex.h
 generic-y += tlbflush.h
 generic-y += topology.h
 generic-y += trace_clock.h
+generic-y += uaccess.h
 generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
diff --git a/arch/h8300/include/asm/uaccess.h b/arch/h8300/include/asm/uaccess.h
deleted file mode 100644 (file)
index bc80319..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_UACCESS_H
-#define _ASM_UACCESS_H
-
-#include <linux/string.h>
-
-static inline __must_check unsigned long
-raw_copy_from_user(void *to, const void __user * from, unsigned long n)
-{
-       if (__builtin_constant_p(n)) {
-               switch(n) {
-               case 1:
-                       *(u8 *)to = *(u8 __force *)from;
-                       return 0;
-               case 2:
-                       *(u16 *)to = *(u16 __force *)from;
-                       return 0;
-               case 4:
-                       *(u32 *)to = *(u32 __force *)from;
-                       return 0;
-               }
-       }
-
-       memcpy(to, (const void __force *)from, n);
-       return 0;
-}
-
-static inline __must_check unsigned long
-raw_copy_to_user(void __user *to, const void *from, unsigned long n)
-{
-       if (__builtin_constant_p(n)) {
-               switch(n) {
-               case 1:
-                       *(u8 __force *)to = *(u8 *)from;
-                       return 0;
-               case 2:
-                       *(u16 __force *)to = *(u16 *)from;
-                       return 0;
-               case 4:
-                       *(u32 __force *)to = *(u32 *)from;
-                       return 0;
-               default:
-                       break;
-               }
-       }
-
-       memcpy((void __force *)to, from, n);
-       return 0;
-}
-#define INLINE_COPY_FROM_USER
-#define INLINE_COPY_TO_USER
-
-#include <asm-generic/uaccess.h>
-
-#endif
index b32bfa1..23a979a 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/console.h>
index 0f04a5e..1eab16b 100644 (file)
@@ -102,17 +102,3 @@ void __init mem_init(void)
 
        mem_init_print_info(NULL);
 }
-
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
-
-void
-free_initmem(void)
-{
-       free_initmem_default(-1);
-}
index 3e54a53..b7d404b 100644 (file)
@@ -22,7 +22,6 @@ config HEXAGON
        select GENERIC_IRQ_SHOW
        select HAVE_ARCH_KGDB
        select HAVE_ARCH_TRACEHOOK
-       select ARCH_DISCARD_MEMBLOCK
        select NEED_SG_DMA_LENGTH
        select NO_IOPORT_MAP
        select GENERIC_IOMAP
index 6234a30..84bb1ed 100644 (file)
@@ -29,10 +29,8 @@ generic-y += pci.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += sections.h
-generic-y += segment.h
 generic-y += serial.h
 generic-y += shmparam.h
-generic-y += sizes.h
 generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
index a30e58d..7a34092 100644 (file)
@@ -24,7 +24,6 @@
  * User space memory access functions
  */
 #include <linux/mm.h>
-#include <asm/segment.h>
 #include <asm/sections.h>
 
 /*
index 1719ede..41cf342 100644 (file)
@@ -84,16 +84,6 @@ void __init mem_init(void)
        init_mm.context.ptbase = __pa(init_mm.pgd);
 }
 
-/*
- * free_initmem - frees memory used by stuff declared with __init
- *
- * Todo:  free pages between __init_begin and __init_end; possibly
- * some devtree related stuff as well.
- */
-void __ref free_initmem(void)
-{
-}
-
 /*
  * free_initrd_mem - frees...  initrd memory.
  * @start - start of init memory
index 73a26f0..7468d8e 100644 (file)
@@ -33,7 +33,6 @@ config IA64
        select ARCH_HAS_DMA_COHERENT_TO_PFN if SWIOTLB
        select ARCH_HAS_SYNC_DMA_FOR_CPU if SWIOTLB
        select VIRT_TO_BUS
-       select ARCH_DISCARD_MEMBLOCK
        select GENERIC_IRQ_PROBE
        select GENERIC_PENDING_IRQ if SMP
        select GENERIC_IRQ_SHOW
diff --git a/arch/ia64/include/asm/segment.h b/arch/ia64/include/asm/segment.h
deleted file mode 100644 (file)
index b89e2b3..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_IA64_SEGMENT_H
-#define _ASM_IA64_SEGMENT_H
-
-/* Only here because we have some old header files that expect it.. */
-
-#endif /* _ASM_IA64_SEGMENT_H */
index 1b604d0..ebd8253 100644 (file)
@@ -10,7 +10,9 @@
 
 #include <asm/page.h>
 
-struct ia64_machine_vector ia64_mv;
+struct ia64_machine_vector ia64_mv = {
+       .mmiowb = ___ia64_mmiowb
+};
 EXPORT_SYMBOL(ia64_mv);
 
 static struct ia64_machine_vector * __init
index e49200e..d28e291 100644 (file)
@@ -666,14 +666,14 @@ mem_init (void)
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
-               bool want_memblock)
+int arch_add_memory(int nid, u64 start, u64 size,
+                       struct mhp_restrictions *restrictions)
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
        int ret;
 
-       ret = __add_pages(nid, start_pfn, nr_pages, altmap, want_memblock);
+       ret = __add_pages(nid, start_pfn, nr_pages, restrictions);
        if (ret)
                printk("%s: Problem encountered in __add_pages() as ret=%d\n",
                       __func__,  ret);
@@ -682,20 +682,15 @@ int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-int arch_remove_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap)
+void arch_remove_memory(int nid, u64 start, u64 size,
+                       struct vmem_altmap *altmap)
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
        struct zone *zone;
-       int ret;
 
        zone = page_zone(pfn_to_page(start_pfn));
-       ret = __remove_pages(zone, start_pfn, nr_pages, altmap);
-       if (ret)
-               pr_warn("%s: Problem encountered in __remove_pages() as"
-                       " ret=%d\n", __func__,  ret);
-
-       return ret;
+       __remove_pages(zone, start_pfn, nr_pages, altmap);
 }
 #endif
 #endif
index fe5cc2d..218e037 100644 (file)
@@ -26,7 +26,6 @@ config M68K
        select MODULES_USE_ELF_RELA
        select OLD_SIGSUSPEND3
        select OLD_SIGACTION
-       select ARCH_DISCARD_MEMBLOCK
        select MMU_GATHER_NO_RANGE if MMU
 
 config CPU_BIG_ENDIAN
index 8868a4c..778cacb 100644 (file)
@@ -147,10 +147,3 @@ void __init mem_init(void)
        init_pointer_tables();
        mem_init_print_info(NULL);
 }
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
index 7e97d44..a015a95 100644 (file)
@@ -186,18 +186,6 @@ void __init setup_memory(void)
        paging_init();
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
-
-void free_initmem(void)
-{
-       free_initmem_default(-1);
-}
-
 void __init mem_init(void)
 {
        high_memory = (void *)__va(memory_start + lowmem_size - 1);
index ff8cff9..677e5bf 100644 (file)
@@ -5,7 +5,6 @@ config MIPS
        select ARCH_32BIT_OFF_T if !64BIT
        select ARCH_BINFMT_ELF_STATE if MIPS_FP_SUPPORT
        select ARCH_CLOCKSOURCE_DATA
-       select ARCH_DISCARD_MEMBLOCK
        select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_HAS_UBSAN_SANITIZE_ALL
index d4ca97e..228cdc7 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
index 25a5789..298b46b 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/memblock.h>
 #include <linux/err.h>
 #include <linux/clk.h>
index ff40fbc..21a1168 100644 (file)
@@ -228,7 +228,7 @@ CONFIG_SERIAL_IP22_ZILOG=m
 # CONFIG_HW_RANDOM is not set
 CONFIG_RAW_DRIVER=m
 # CONFIG_HWMON is not set
-CONFIG_THERMAL=m
+CONFIG_THERMAL=y
 CONFIG_WATCHDOG=y
 CONFIG_INDYDOG=m
 # CONFIG_VGA_CONSOLE is not set
index 81c47e1..54db5de 100644 (file)
@@ -271,7 +271,7 @@ CONFIG_I2C_PARPORT_LIGHT=m
 CONFIG_I2C_TAOS_EVM=m
 CONFIG_I2C_STUB=m
 # CONFIG_HWMON is not set
-CONFIG_THERMAL=m
+CONFIG_THERMAL=y
 CONFIG_MFD_PCF50633=m
 CONFIG_PCF50633_ADC=m
 CONFIG_PCF50633_GPIO=m
index 87b86cd..a03cd4e 100644 (file)
@@ -19,7 +19,6 @@ generic-y += preempt.h
 generic-y += qrwlock.h
 generic-y += qspinlock.h
 generic-y += sections.h
-generic-y += segment.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
 generic-y += user.h
index 830c93a..9a466dd 100644 (file)
@@ -482,7 +482,7 @@ static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long *
  * Return the bit position (0..63) of the most significant 1 bit in a word
  * Returns -1 if no 1 bit exists
  */
-static inline unsigned long __fls(unsigned long word)
+static __always_inline unsigned long __fls(unsigned long word)
 {
        int num;
 
@@ -548,7 +548,7 @@ static inline unsigned long __fls(unsigned long word)
  * Returns 0..SZLONG-1
  * Undefined if no bit exists, so code should check against 0 first.
  */
-static inline unsigned long __ffs(unsigned long word)
+static __always_inline unsigned long __ffs(unsigned long word)
 {
        return __fls(word & -word);
 }
index bada74a..c04b97a 100644 (file)
@@ -42,8 +42,8 @@ static inline void align_mod(const int align, const int mod)
                : "n"(align), "n"(mod));
 }
 
-static inline void mult_sh_align_mod(long *v1, long *v2, long *w,
-                                    const int align, const int mod)
+static __always_inline void mult_sh_align_mod(long *v1, long *v2, long *w,
+                                             const int align, const int mod)
 {
        unsigned long flags;
        int m1, m2;
index 0d14e0d..4c2b448 100644 (file)
@@ -235,7 +235,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
  * get_user_pages_fast() - pin user pages in memory
  * @start:     starting user address
  * @nr_pages:  number of pages from start to pin
- * @write:     whether pages will be written to
+ * @gup_flags: flags modifying pin behaviour
  * @pages:     array that receives pointers to the pages pinned.
  *             Should be at least nr_pages long.
  *
@@ -247,8 +247,8 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
  * requested. If nr_pages is 0 or negative, returns 0. If no pages
  * were pinned, returns -errno.
  */
-int get_user_pages_fast(unsigned long start, int nr_pages, int write,
-                       struct page **pages)
+int get_user_pages_fast(unsigned long start, int nr_pages,
+                       unsigned int gup_flags, struct page **pages)
 {
        struct mm_struct *mm = current->mm;
        unsigned long addr, len, end;
@@ -273,7 +273,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
                next = pgd_addr_end(addr, end);
                if (pgd_none(pgd))
                        goto slow;
-               if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
+               if (!gup_pud_range(pgd, addr, next, gup_flags & FOLL_WRITE,
+                                  pages, &nr))
                        goto slow;
        } while (pgdp++, addr = next, addr != end);
        local_irq_enable();
@@ -289,7 +290,7 @@ slow_irqon:
        pages += nr;
 
        ret = get_user_pages_unlocked(start, (end - start) >> PAGE_SHIFT,
-                                     pages, write ? FOLL_WRITE : 0);
+                                     pages, gup_flags);
 
        /* Have to be a bit careful with return values */
        if (nr > 0) {
index bbb196a..8a038b3 100644 (file)
@@ -504,14 +504,6 @@ void free_init_pages(const char *what, unsigned long begin, unsigned long end)
        printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, POISON_FREE_INITMEM,
-                          "initrd");
-}
-#endif
-
 void (*free_init_pages_eva)(void *begin, void *end) = NULL;
 
 void __ref free_initmem(void)
index 70a1ab6..46537c2 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/leds.h>
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <linux/irq.h>
 #include <asm/bootinfo.h>
 #include <asm/idle.h>
index 688b6ed..d8ce778 100644 (file)
@@ -37,9 +37,7 @@ generic-y += pci.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += sections.h
-generic-y += segment.h
 generic-y += serial.h
-generic-y += sizes.h
 generic-y += switch_to.h
 generic-y += timex.h
 generic-y += topology.h
index 9f52db9..ee59c1f 100644 (file)
@@ -6,7 +6,7 @@
 
 #define __PAGETABLE_PMD_FOLDED 1
 #include <asm-generic/4level-fixup.h>
-#include <asm-generic/sizes.h>
+#include <linux/sizes.h>
 
 #include <asm/memory.h>
 #include <asm/nds32.h>
index 8a41372..fd2a54b 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef CONFIG_DYNAMIC_FTRACE
 extern void (*ftrace_trace_function)(unsigned long, unsigned long,
                                     struct ftrace_ops*, struct pt_regs*);
-extern int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace);
 extern void ftrace_graph_caller(void);
 
 noinline void __naked ftrace_stub(unsigned long ip, unsigned long parent_ip,
index db64b78..fcefb62 100644 (file)
@@ -7,7 +7,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/thread_info.h>
 
 #ifdef CONFIG_CPU_BIG_ENDIAN
index 1d03633..1a4ab1b 100644 (file)
@@ -252,18 +252,6 @@ void __init mem_init(void)
        return;
 }
 
-void free_initmem(void)
-{
-       free_initmem_default(-1);
-}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
-
 void __set_fixmap(enum fixed_addresses idx,
                               phys_addr_t phys, pgprot_t flags)
 {
index ea37394..26a9c76 100644 (file)
@@ -23,7 +23,6 @@ config NIOS2
        select SPARSE_IRQ
        select USB_ARCH_HAS_HCD if USB_SUPPORT
        select CPU_NO_EFFICIENT_FFS
-       select ARCH_DISCARD_MEMBLOCK
        select MMU_GATHER_NO_RANGE if MMU
 
 config GENERIC_CSUM
index d7ef351..a8ffdd0 100644 (file)
@@ -33,7 +33,6 @@ generic-y += pci.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += sections.h
-generic-y += segment.h
 generic-y += serial.h
 generic-y += spinlock.h
 generic-y += topology.h
index 16cea57..2c609c2 100644 (file)
@@ -82,18 +82,6 @@ void __init mmu_init(void)
        flush_tlb_all();
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void __init free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
-
-void __ref free_initmem(void)
-{
-       free_initmem_default(-1);
-}
-
 #define __page_aligned(order) __aligned(PAGE_SIZE << (order))
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned(PGD_ORDER);
 pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned(PTE_ORDER);
index 1919cc5..164be10 100644 (file)
@@ -34,7 +34,6 @@ generic-y += qspinlock.h
 generic-y += qrwlock_types.h
 generic-y += qrwlock.h
 generic-y += sections.h
-generic-y += segment.h
 generic-y += shmparam.h
 generic-y += switch_to.h
 generic-y += topology.h
index eb97a8e..e8fb2a7 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/elf.h>
 
 #include <asm/thread_info.h>
-#include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 
index c605bda..17c00d0 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/device.h>
 
 #include <asm/sections.h>
-#include <asm/segment.h>
 #include <asm/pgtable.h>
 #include <asm/types.h>
 #include <asm/setup.h>
index d8981cb..6ed7293 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/kallsyms.h>
 #include <linux/uaccess.h>
 
-#include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/unwinder.h>
index caeb418..e63cb4a 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/blkdev.h>      /* for initrd_* */
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/dma.h>
@@ -223,15 +222,3 @@ void __init mem_init(void)
        mem_init_done = 1;
        return;
 }
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
-
-void free_initmem(void)
-{
-       free_initmem_default(-1);
-}
index 6c253a2..7f9f501 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 
-#include <asm/segment.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
index ed2d8cc..005ee8a 100644 (file)
@@ -19,7 +19,6 @@ generic-y += mmiowb.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += seccomp.h
-generic-y += segment.h
 generic-y += trace_clock.h
 generic-y += user.h
 generic-y += vga.h
index 4016fe1..73ca89a 100644 (file)
@@ -24,9 +24,6 @@
 
 #define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
-/* Read-only memory is marked before mark_rodata_ro() is called. */
-#define __ro_after_init        __read_mostly
-
 void parisc_cache_init(void);  /* initializes cache-flushing */
 void disable_sr_hashing_asm(int); /* low level support for above */
 void disable_sr_hashing(void);   /* turns off space register hashing */
index 0338561..a82b3ea 100644 (file)
@@ -29,9 +29,9 @@
 #include <asm/sections.h>
 #include <asm/shmparam.h>
 
-int split_tlb __read_mostly;
-int dcache_stride __read_mostly;
-int icache_stride __read_mostly;
+int split_tlb __ro_after_init;
+int dcache_stride __ro_after_init;
+int icache_stride __ro_after_init;
 EXPORT_SYMBOL(dcache_stride);
 
 void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
@@ -51,12 +51,12 @@ DEFINE_SPINLOCK(pa_tlb_flush_lock);
 DEFINE_SPINLOCK(pa_swapper_pg_lock);
 
 #if defined(CONFIG_64BIT) && defined(CONFIG_SMP)
-int pa_serialize_tlb_flushes __read_mostly;
+int pa_serialize_tlb_flushes __ro_after_init;
 #endif
 
-struct pdc_cache_info cache_info __read_mostly;
+struct pdc_cache_info cache_info __ro_after_init;
 #ifndef CONFIG_PA20
-static struct pdc_btlb_info btlb_info __read_mostly;
+static struct pdc_btlb_info btlb_info __ro_after_init;
 #endif
 
 #ifdef CONFIG_SMP
@@ -381,10 +381,10 @@ EXPORT_SYMBOL(flush_data_cache_local);
 EXPORT_SYMBOL(flush_kernel_icache_range_asm);
 
 #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
-static unsigned long parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD;
+static unsigned long parisc_cache_flush_threshold __ro_after_init = FLUSH_THRESHOLD;
 
 #define FLUSH_TLB_THRESHOLD (16*1024) /* 16 KiB minimum TLB threshold */
-static unsigned long parisc_tlb_flush_threshold __read_mostly = FLUSH_TLB_THRESHOLD;
+static unsigned long parisc_tlb_flush_threshold __ro_after_init = FLUSH_TLB_THRESHOLD;
 
 void __init parisc_setup_cache_timing(void)
 {
index 15e7b3b..00a181f 100644 (file)
@@ -41,7 +41,7 @@
 #include <asm/ropes.h>
 
 /* See comments in include/asm-parisc/pci.h */
-const struct dma_map_ops *hppa_dma_ops __read_mostly;
+const struct dma_map_ops *hppa_dma_ops __ro_after_init;
 EXPORT_SYMBOL(hppa_dma_ops);
 
 static struct device root = {
index 7a17551..f01e102 100644 (file)
@@ -87,7 +87,7 @@ extern unsigned long pdc_result2[NUM_PDC_RESULT];
 
 /* Firmware needs to be initially set to narrow to determine the 
  * actual firmware width. */
-int parisc_narrow_firmware __read_mostly = 1;
+int parisc_narrow_firmware __ro_after_init = 1;
 #endif
 
 /* On most currently-supported platforms, IODC I/O calls are 32-bit calls
index e46a415..a28f915 100644 (file)
@@ -51,7 +51,6 @@ void notrace __hot ftrace_function_trampoline(unsigned long parent,
                                unsigned long org_sp_gr3)
 {
        extern ftrace_func_t ftrace_trace_function;  /* depends on CONFIG_DYNAMIC_FTRACE */
-       extern int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace);
 
        if (ftrace_trace_function != ftrace_stub) {
                /* struct ftrace_ops *op, struct pt_regs *regs); */
index d12de2a..951a339 100644 (file)
@@ -376,7 +376,7 @@ smp_slave_stext:
 ENDPROC(parisc_kernel_start)
 
 #ifndef CONFIG_64BIT
-       .section .data..read_mostly
+       .section .data..ro_after_init
 
        .align  4
        .export $global$,data
index 6f2d611..3f4a91c 100644 (file)
 */
 #undef DEBUG_PAT
 
-int pdc_type __read_mostly = PDC_TYPE_ILLEGAL;
+int pdc_type __ro_after_init = PDC_TYPE_ILLEGAL;
 
 /* cell number and location (PAT firmware only) */
-unsigned long parisc_cell_num __read_mostly;
-unsigned long parisc_cell_loc __read_mostly;
-unsigned long parisc_pat_pdc_cap __read_mostly;
+unsigned long parisc_cell_num __ro_after_init;
+unsigned long parisc_cell_loc __ro_after_init;
+unsigned long parisc_pat_pdc_cap __ro_after_init;
 
 
 void __init setup_pdc(void)
index ae684ac..bc41ca2 100644 (file)
  * #define pci_post_reset_delay 50
  */
 
-struct pci_port_ops *pci_port __read_mostly;
-struct pci_bios_ops *pci_bios __read_mostly;
+struct pci_port_ops *pci_port __ro_after_init;
+struct pci_bios_ops *pci_bios __ro_after_init;
 
-static int pci_hba_count __read_mostly;
+static int pci_hba_count __ro_after_init;
 
 /* parisc_pci_hba used by pci_port->in/out() ops to lookup bus data.  */
 #define PCI_HBA_MAX 32
-static struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX] __read_mostly;
+static struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX] __ro_after_init;
 
 
 /********************************************************************
index 7fef964..c108fee 100644 (file)
@@ -25,7 +25,7 @@
 
 #define PCXU_IMAGE_SIZE 584
 
-static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] __read_mostly = {
+static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] __ro_after_init = {
 /*
  * CPI:
  *
@@ -2093,7 +2093,7 @@ static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] __read_mostly =
 };
 #define PCXW_IMAGE_SIZE 576
 
-static uint32_t cuda_images[][PCXW_IMAGE_SIZE/sizeof(uint32_t)] __read_mostly = {
+static uint32_t cuda_images[][PCXW_IMAGE_SIZE/sizeof(uint32_t)] __ro_after_init = {
 /*
  * CPI:     FROM CPI.IDF (Image 0)
  *
index 97c2067..89e4f44 100644 (file)
@@ -192,7 +192,7 @@ int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r)
  * QEMU idle the host too.
  */
 
-int running_on_qemu __read_mostly;
+int running_on_qemu __ro_after_init;
 EXPORT_SYMBOL(running_on_qemu);
 
 void __cpuidle arch_cpu_idle_dead(void)
index e0a81de..e715871 100644 (file)
 #include <asm/irq.h>           /* for struct irq_region */
 #include <asm/parisc-device.h>
 
-struct system_cpuinfo_parisc boot_cpu_data __read_mostly;
+struct system_cpuinfo_parisc boot_cpu_data __ro_after_init;
 EXPORT_SYMBOL(boot_cpu_data);
 #ifdef CONFIG_PA8X00
-int _parisc_requires_coherency __read_mostly;
+int _parisc_requires_coherency __ro_after_init;
 EXPORT_SYMBOL(_parisc_requires_coherency);
 #endif
 
index e54d5e4..97ac707 100644 (file)
@@ -641,7 +641,8 @@ cas_action:
 2:     stw     %r24, 0(%r26)
        /* Free lock */
 #ifdef CONFIG_SMP
-       LDCW    0(%sr2,%r20), %r1                       /* Barrier */
+98:    LDCW    0(%sr2,%r20), %r1                       /* Barrier */
+99:    ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
 #endif
        stw     %r20, 0(%sr2,%r20)
 #if ENABLE_LWS_DEBUG
@@ -658,7 +659,8 @@ cas_action:
        /* Error occurred on load or store */
        /* Free lock */
 #ifdef CONFIG_SMP
-       LDCW    0(%sr2,%r20), %r1                       /* Barrier */
+98:    LDCW    0(%sr2,%r20), %r1                       /* Barrier */
+99:    ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
 #endif
        stw     %r20, 0(%sr2,%r20)
 #if ENABLE_LWS_DEBUG
@@ -862,7 +864,8 @@ cas2_action:
 cas2_end:
        /* Free lock */
 #ifdef CONFIG_SMP
-       LDCW    0(%sr2,%r20), %r1                       /* Barrier */
+98:    LDCW    0(%sr2,%r20), %r1                       /* Barrier */
+99:    ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
 #endif
        stw     %r20, 0(%sr2,%r20)
        /* Enable interrupts */
@@ -875,7 +878,8 @@ cas2_end:
        /* Error occurred on load or store */
        /* Free lock */
 #ifdef CONFIG_SMP
-       LDCW    0(%sr2,%r20), %r1                       /* Barrier */
+98:    LDCW    0(%sr2,%r20), %r1                       /* Barrier */
+99:    ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
 #endif
        stw     %r20, 0(%sr2,%r20)
        ssm     PSW_SM_I, %r0
index a1e772f..0450815 100644 (file)
@@ -40,7 +40,7 @@
 
 #include <linux/timex.h>
 
-static unsigned long clocktick __read_mostly;  /* timer cycles per tick */
+static unsigned long clocktick __ro_after_init;        /* timer cycles per tick */
 
 /*
  * We keep time on PA-RISC Linux by using the Interval Timer which is
index 2d14f17..87ae476 100644 (file)
@@ -40,7 +40,7 @@ static DEFINE_SPINLOCK(unwind_lock);
  * we can call unwind_init as early in the bootup process as 
  * possible (before the slab allocator is initialized)
  */
-static struct unwind_table kernel_unwind_table __read_mostly;
+static struct unwind_table kernel_unwind_table __ro_after_init;
 static LIST_HEAD(unwind_tables);
 
 static inline const struct unwind_table_entry *
index a8be7a4..c3b1b9c 100644 (file)
@@ -18,9 +18,6 @@
                                *(.data..vm0.pgd) \
                                *(.data..vm0.pte)
 
-/* No __ro_after_init data in the .rodata section - which will always be ro */
-#define RO_AFTER_INIT_DATA
-
 #include <asm-generic/vmlinux.lds.h>
 
 /* needed for the processor specific cache alignment size */   
index 3b0f9ea..ddca828 100644 (file)
@@ -66,7 +66,7 @@ static struct resource pdcdata_resource = {
        .flags  = IORESOURCE_BUSY | IORESOURCE_MEM,
 };
 
-static struct resource sysram_resources[MAX_PHYSMEM_RANGES] __read_mostly;
+static struct resource sysram_resources[MAX_PHYSMEM_RANGES] __ro_after_init;
 
 /* The following array is initialized from the firmware specific
  * information retrieved in kernel/inventory.c.
@@ -345,16 +345,7 @@ static void __init setup_bootmem(void)
        memblock_dump_all();
 }
 
-static int __init parisc_text_address(unsigned long vaddr)
-{
-       static unsigned long head_ptr __initdata;
-
-       if (!head_ptr)
-               head_ptr = PAGE_MASK & (unsigned long)
-                       dereference_function_descriptor(&parisc_kernel_start);
-
-       return core_kernel_text(vaddr) || vaddr == head_ptr;
-}
+static bool kernel_set_to_readonly;
 
 static void __init map_pages(unsigned long start_vaddr,
                             unsigned long start_paddr, unsigned long size,
@@ -372,10 +363,11 @@ static void __init map_pages(unsigned long start_vaddr,
        unsigned long vaddr;
        unsigned long ro_start;
        unsigned long ro_end;
-       unsigned long kernel_end;
+       unsigned long kernel_start, kernel_end;
 
        ro_start = __pa((unsigned long)_text);
        ro_end   = __pa((unsigned long)&data_start);
+       kernel_start = __pa((unsigned long)&__init_begin);
        kernel_end  = __pa((unsigned long)&_end);
 
        end_paddr = start_paddr + size;
@@ -438,26 +430,30 @@ static void __init map_pages(unsigned long start_vaddr,
                        pg_table = (pte_t *) __va(pg_table) + start_pte;
                        for (tmp2 = start_pte; tmp2 < PTRS_PER_PTE; tmp2++, pg_table++) {
                                pte_t pte;
-
-                               if (force)
-                                       pte =  __mk_pte(address, pgprot);
-                               else if (parisc_text_address(vaddr)) {
-                                       pte = __mk_pte(address, PAGE_KERNEL_EXEC);
-                                       if (address >= ro_start && address < kernel_end)
-                                               pte = pte_mkhuge(pte);
+                               pgprot_t prot;
+                               bool huge = false;
+
+                               if (force) {
+                                       prot = pgprot;
+                               } else if (address < kernel_start || address >= kernel_end) {
+                                       /* outside kernel memory */
+                                       prot = PAGE_KERNEL;
+                               } else if (!kernel_set_to_readonly) {
+                                       /* still initializing, allow writing to RO memory */
+                                       prot = PAGE_KERNEL_RWX;
+                                       huge = true;
+                               } else if (address >= ro_start) {
+                                       /* Code (ro) and Data areas */
+                                       prot = (address < ro_end) ?
+                                               PAGE_KERNEL_EXEC : PAGE_KERNEL;
+                                       huge = true;
+                               } else {
+                                       prot = PAGE_KERNEL;
                                }
-                               else
-#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
-                               if (address >= ro_start && address < ro_end) {
-                                       pte = __mk_pte(address, PAGE_KERNEL_EXEC);
+
+                               pte = __mk_pte(address, prot);
+                               if (huge)
                                        pte = pte_mkhuge(pte);
-                               } else
-#endif
-                               {
-                                       pte = __mk_pte(address, pgprot);
-                                       if (address >= ro_start && address < kernel_end)
-                                               pte = pte_mkhuge(pte);
-                               }
 
                                if (address >= end_paddr)
                                        break;
@@ -493,6 +489,12 @@ void __ref free_initmem(void)
 {
        unsigned long init_begin = (unsigned long)__init_begin;
        unsigned long init_end = (unsigned long)__init_end;
+       unsigned long kernel_end  = (unsigned long)&_end;
+
+       /* Remap kernel text and data, but do not touch init section yet. */
+       kernel_set_to_readonly = true;
+       map_pages(init_end, __pa(init_end), kernel_end - init_end,
+                 PAGE_KERNEL, 0);
 
        /* The init text pages are marked R-X.  We have to
         * flush the icache and mark them RW-
@@ -509,7 +511,7 @@ void __ref free_initmem(void)
                  PAGE_KERNEL, 1);
 
        /* force the kernel to see the new TLB entries */
-       __flush_tlb_range(0, init_begin, init_end);
+       __flush_tlb_range(0, init_begin, kernel_end);
 
        /* finally dump all the instructions which were cached, since the
         * pages are no-longer executable */
@@ -527,8 +529,9 @@ void mark_rodata_ro(void)
 {
        /* rodata memory was already mapped with KERNEL_RO access rights by
            pagetable_init() and map_pages(). No need to do additional stuff here */
-       printk (KERN_INFO "Write protecting the kernel read-only data: %luk\n",
-               (unsigned long)(__end_rodata - __start_rodata) >> 10);
+       unsigned long roai_size = __end_ro_after_init - __start_ro_after_init;
+
+       pr_info("Write protected read-only-after-init data: %luk\n", roai_size >> 10);
 }
 #endif
 
@@ -554,11 +557,11 @@ void mark_rodata_ro(void)
 #define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \
                                     & ~(VM_MAP_OFFSET-1)))
 
-void *parisc_vmalloc_start __read_mostly;
+void *parisc_vmalloc_start __ro_after_init;
 EXPORT_SYMBOL(parisc_vmalloc_start);
 
 #ifdef CONFIG_PA11
-unsigned long pcxl_dma_start __read_mostly;
+unsigned long pcxl_dma_start __ro_after_init;
 #endif
 
 void __init mem_init(void)
@@ -632,7 +635,7 @@ void __init mem_init(void)
 #endif
 }
 
-unsigned long *empty_zero_page __read_mostly;
+unsigned long *empty_zero_page __ro_after_init;
 EXPORT_SYMBOL(empty_zero_page);
 
 /*
@@ -917,10 +920,3 @@ void flush_tlb_all(void)
        spin_unlock(&sid_lock);
 }
 #endif
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
index d7996cf..8c1c636 100644 (file)
@@ -137,6 +137,7 @@ config PPC
        select ARCH_HAS_UBSAN_SANITIZE_ALL
        select ARCH_HAS_ZONE_DEVICE             if PPC_BOOK3S_64
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
+       select ARCH_KEEP_MEMBLOCK
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_MIGHT_HAVE_PC_SERIO
        select ARCH_OPTIONAL_KERNEL_RWX         if ARCH_HAS_STRICT_KERNEL_RWX
index 56140d1..12e150e 100644 (file)
@@ -36,8 +36,8 @@ static inline int hstate_get_psize(struct hstate *hstate)
        }
 }
 
-#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE
-static inline bool gigantic_page_supported(void)
+#define __HAVE_ARCH_GIGANTIC_PAGE_RUNTIME_SUPPORTED
+static inline bool gigantic_page_runtime_supported(void)
 {
        /*
         * We used gigantic page reservation with hypervisor assist in some case.
@@ -49,7 +49,6 @@ static inline bool gigantic_page_supported(void)
 
        return true;
 }
-#endif
 
 /* hugepd entry valid bit */
 #define HUGEPD_VAL_BITS                (0x8000000000000000UL)
index 5070df1..c005aee 100644 (file)
 #include <linux/sched/task_stack.h>
 
 #ifdef CONFIG_LIVEPATCH
-static inline int klp_check_compiler_support(void)
-{
-       return 0;
-}
-
 static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 {
        regs->nip = ip;
index 523bb99..00682b8 100644 (file)
@@ -628,14 +628,14 @@ static int __init prom_next_node(phandle *nodep)
        }
 }
 
-static inline int prom_getprop(phandle node, const char *pname,
-                              void *value, size_t valuelen)
+static inline int __init prom_getprop(phandle node, const char *pname,
+                                     void *value, size_t valuelen)
 {
        return call_prom("getprop", 4, 1, node, ADDR(pname),
                         (u32)(unsigned long) value, (u32) valuelen);
 }
 
-static inline int prom_getproplen(phandle node, const char *pname)
+static inline int __init prom_getproplen(phandle node, const char *pname)
 {
        return call_prom("getproplen", 2, 1, node, ADDR(pname));
 }
index e8e93c2..7a17088 100644 (file)
@@ -610,7 +610,7 @@ SYSFS_PMCSETUP(pa6t_pmc2, SPRN_PA6T_PMC2);
 SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3);
 SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4);
 SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5);
-#ifdef CONFIG_DEBUG_KERNEL
+#ifdef CONFIG_DEBUG_MISC
 SYSFS_SPRSETUP(hid0, SPRN_HID0);
 SYSFS_SPRSETUP(hid1, SPRN_HID1);
 SYSFS_SPRSETUP(hid4, SPRN_HID4);
@@ -639,7 +639,7 @@ SYSFS_SPRSETUP(tsr0, SPRN_PA6T_TSR0);
 SYSFS_SPRSETUP(tsr1, SPRN_PA6T_TSR1);
 SYSFS_SPRSETUP(tsr2, SPRN_PA6T_TSR2);
 SYSFS_SPRSETUP(tsr3, SPRN_PA6T_TSR3);
-#endif /* CONFIG_DEBUG_KERNEL */
+#endif /* CONFIG_DEBUG_MISC */
 #endif /* HAS_PPC_PMC_PA6T */
 
 #ifdef HAS_PPC_PMC_IBM
@@ -680,7 +680,7 @@ static struct device_attribute pa6t_attrs[] = {
        __ATTR(pmc3, 0600, show_pa6t_pmc3, store_pa6t_pmc3),
        __ATTR(pmc4, 0600, show_pa6t_pmc4, store_pa6t_pmc4),
        __ATTR(pmc5, 0600, show_pa6t_pmc5, store_pa6t_pmc5),
-#ifdef CONFIG_DEBUG_KERNEL
+#ifdef CONFIG_DEBUG_MISC
        __ATTR(hid0, 0600, show_hid0, store_hid0),
        __ATTR(hid1, 0600, show_hid1, store_hid1),
        __ATTR(hid4, 0600, show_hid4, store_hid4),
@@ -709,7 +709,7 @@ static struct device_attribute pa6t_attrs[] = {
        __ATTR(tsr1, 0600, show_tsr1, store_tsr1),
        __ATTR(tsr2, 0600, show_tsr2, store_tsr2),
        __ATTR(tsr3, 0600, show_tsr3, store_tsr3),
-#endif /* CONFIG_DEBUG_KERNEL */
+#endif /* CONFIG_DEBUG_MISC */
 };
 #endif /* HAS_PPC_PMC_PA6T */
 #endif /* HAS_PPC_PMC_CLASSIC */
index be7bc07..ab3d484 100644 (file)
@@ -600,7 +600,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
        /* If writing != 0, then the HPTE must allow writing, if we get here */
        write_ok = writing;
        hva = gfn_to_hva_memslot(memslot, gfn);
-       npages = get_user_pages_fast(hva, 1, writing, pages);
+       npages = get_user_pages_fast(hva, 1, writing ? FOLL_WRITE : 0, pages);
        if (npages < 1) {
                /* Check if it's an I/O mapping */
                down_read(&current->mm->mmap_sem);
@@ -1193,7 +1193,7 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
        if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
                goto err;
        hva = gfn_to_hva_memslot(memslot, gfn);
-       npages = get_user_pages_fast(hva, 1, 1, pages);
+       npages = get_user_pages_fast(hva, 1, FOLL_WRITE, pages);
        if (npages < 1)
                goto err;
        page = pages[0];
index 24296f4..e0af53f 100644 (file)
@@ -783,7 +783,7 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
        if (!pages)
                return -ENOMEM;
 
-       ret = get_user_pages_fast(cfg->array, num_pages, 1, pages);
+       ret = get_user_pages_fast(cfg->array, num_pages, FOLL_WRITE, pages);
        if (ret < 0)
                goto free_pages;
 
index 8330f13..5c521f3 100644 (file)
@@ -141,8 +141,9 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua,
        for (entry = 0; entry < entries; entry += chunk) {
                unsigned long n = min(entries - entry, chunk);
 
-               ret = get_user_pages_longterm(ua + (entry << PAGE_SHIFT), n,
-                               FOLL_WRITE, mem->hpages + entry, NULL);
+               ret = get_user_pages(ua + (entry << PAGE_SHIFT), n,
+                               FOLL_WRITE | FOLL_LONGTERM,
+                               mem->hpages + entry, NULL);
                if (ret == n) {
                        pinned += n;
                        continue;
index 6a23b9e..4d84136 100644 (file)
@@ -90,7 +90,7 @@ void radix__tlbiel_all(unsigned int action)
        asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory");
 }
 
-static inline void __tlbiel_pid(unsigned long pid, int set,
+static __always_inline void __tlbiel_pid(unsigned long pid, int set,
                                unsigned long ric)
 {
        unsigned long rb,rs,prs,r;
@@ -106,7 +106,7 @@ static inline void __tlbiel_pid(unsigned long pid, int set,
        trace_tlbie(0, 1, rb, rs, ric, prs, r);
 }
 
-static inline void __tlbie_pid(unsigned long pid, unsigned long ric)
+static __always_inline void __tlbie_pid(unsigned long pid, unsigned long ric)
 {
        unsigned long rb,rs,prs,r;
 
@@ -120,7 +120,7 @@ static inline void __tlbie_pid(unsigned long pid, unsigned long ric)
        trace_tlbie(0, 0, rb, rs, ric, prs, r);
 }
 
-static inline void __tlbiel_lpid(unsigned long lpid, int set,
+static __always_inline void __tlbiel_lpid(unsigned long lpid, int set,
                                unsigned long ric)
 {
        unsigned long rb,rs,prs,r;
@@ -136,7 +136,7 @@ static inline void __tlbiel_lpid(unsigned long lpid, int set,
        trace_tlbie(lpid, 1, rb, rs, ric, prs, r);
 }
 
-static inline void __tlbie_lpid(unsigned long lpid, unsigned long ric)
+static __always_inline void __tlbie_lpid(unsigned long lpid, unsigned long ric)
 {
        unsigned long rb,rs,prs,r;
 
@@ -928,7 +928,7 @@ void radix__tlb_flush(struct mmu_gather *tlb)
        tlb->need_flush_all = 0;
 }
 
-static inline void __radix__flush_tlb_range_psize(struct mm_struct *mm,
+static __always_inline void __radix__flush_tlb_range_psize(struct mm_struct *mm,
                                unsigned long start, unsigned long end,
                                int psize, bool also_pwc)
 {
index cd525d7..e885fe2 100644 (file)
@@ -109,8 +109,8 @@ int __weak remove_section_mapping(unsigned long start, unsigned long end)
        return -ENODEV;
 }
 
-int __ref arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
-                         bool want_memblock)
+int __ref arch_add_memory(int nid, u64 start, u64 size,
+                       struct mhp_restrictions *restrictions)
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
@@ -127,11 +127,11 @@ int __ref arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altm
        }
        flush_inval_dcache_range(start, start + size);
 
-       return __add_pages(nid, start_pfn, nr_pages, altmap, want_memblock);
+       return __add_pages(nid, start_pfn, nr_pages, restrictions);
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-int __ref arch_remove_memory(int nid, u64 start, u64 size,
+void __ref arch_remove_memory(int nid, u64 start, u64 size,
                             struct vmem_altmap *altmap)
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
@@ -147,14 +147,13 @@ int __ref arch_remove_memory(int nid, u64 start, u64 size,
        if (altmap)
                page += vmem_altmap_offset(altmap);
 
-       ret = __remove_pages(page_zone(page), start_pfn, nr_pages, altmap);
-       if (ret)
-               return ret;
+       __remove_pages(page_zone(page), start_pfn, nr_pages, altmap);
 
        /* Remove htab bolted mappings for this section of memory */
        start = (unsigned long)__va(start);
        flush_inval_dcache_range(start, start + size);
        ret = remove_section_mapping(start, start + size);
+       WARN_ON_ONCE(ret);
 
        /* Ensure all vmalloc mappings are flushed in case they also
         * hit that section of memory
@@ -163,8 +162,6 @@ int __ref arch_remove_memory(int nid, u64 start, u64 size,
 
        if (resize_hpt_for_hotplug(memblock_phys_mem_size()) == -ENOSPC)
                pr_warn("Hash collision while resizing HPT\n");
-
-       return ret;
 }
 #endif
 #endif /* CONFIG_MEMORY_HOTPLUG */
@@ -338,13 +335,6 @@ void free_initmem(void)
        free_initmem_default(POISON_FREE_INITMEM);
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void __init free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
-
 /*
  * This is called when a page has been modified by the kernel.
  * It just marks the page as not i-cache clean.  We do the i-cache
index d0e172d..2794235 100644 (file)
@@ -331,7 +331,7 @@ config ARCH_ENABLE_SPLIT_PMD_PTLOCK
 config PPC_RADIX_MMU
        bool "Radix MMU Support"
        depends on PPC_BOOK3S_64 && HUGETLB_PAGE
-       select ARCH_HAS_GIGANTIC_PAGE if (MEMORY_ISOLATION && COMPACTION) || CMA
+       select ARCH_HAS_GIGANTIC_PAGE
        select PPC_HAVE_KUEP
        select PPC_HAVE_KUAP
        default y
index dc23d9d..4955504 100644 (file)
@@ -1213,9 +1213,8 @@ int pnv_npu2_map_lpar_dev(struct pci_dev *gpdev, unsigned int lparid,
         * Currently we only support radix and non-zero LPCR only makes sense
         * for hash tables so skiboot expects the LPCR parameter to be a zero.
         */
-       ret = opal_npu_map_lpar(nphb->opal_id,
-                       PCI_DEVID(gpdev->bus->number, gpdev->devfn), lparid,
-                       0 /* LPCR bits */);
+       ret = opal_npu_map_lpar(nphb->opal_id, pci_dev_id(gpdev), lparid,
+                               0 /* LPCR bits */);
        if (ret) {
                dev_err(&gpdev->dev, "Error %d mapping device to LPAR\n", ret);
                return ret;
@@ -1224,7 +1223,7 @@ int pnv_npu2_map_lpar_dev(struct pci_dev *gpdev, unsigned int lparid,
        dev_dbg(&gpdev->dev, "init context opalid=%llu msr=%lx\n",
                        nphb->opal_id, msr);
        ret = opal_npu_init_context(nphb->opal_id, 0/*__unused*/, msr,
-                       PCI_DEVID(gpdev->bus->number, gpdev->devfn));
+                                   pci_dev_id(gpdev));
        if (ret < 0)
                dev_err(&gpdev->dev, "Failed to init context: %d\n", ret);
        else
@@ -1258,7 +1257,7 @@ int pnv_npu2_unmap_lpar_dev(struct pci_dev *gpdev)
        dev_dbg(&gpdev->dev, "destroy context opalid=%llu\n",
                        nphb->opal_id);
        ret = opal_npu_destroy_context(nphb->opal_id, 0/*__unused*/,
-                       PCI_DEVID(gpdev->bus->number, gpdev->devfn));
+                                      pci_dev_id(gpdev));
        if (ret < 0) {
                dev_err(&gpdev->dev, "Failed to destroy context: %d\n", ret);
                return ret;
@@ -1266,9 +1265,8 @@ int pnv_npu2_unmap_lpar_dev(struct pci_dev *gpdev)
 
        /* Set LPID to 0 anyway, just to be safe */
        dev_dbg(&gpdev->dev, "Map LPAR opalid=%llu lparid=0\n", nphb->opal_id);
-       ret = opal_npu_map_lpar(nphb->opal_id,
-                       PCI_DEVID(gpdev->bus->number, gpdev->devfn), 0 /*LPID*/,
-                       0 /* LPCR bits */);
+       ret = opal_npu_map_lpar(nphb->opal_id, pci_dev_id(gpdev), 0 /*LPID*/,
+                               0 /* LPCR bits */);
        if (ret)
                dev_err(&gpdev->dev, "Error %d mapping device to LPAR\n", ret);
 
index c92dcac..026619c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/irq.h>
 #include <linux/export.h>
 #include <linux/device.h>
+#include <linux/etherdevice.h>
 #include <linux/platform_device.h>
 #include <linux/of_net.h>
 #include <asm/tsi108.h>
@@ -106,7 +107,7 @@ static int __init tsi108_eth_of_init(void)
 
                mac_addr = of_get_mac_address(np);
                if (!IS_ERR(mac_addr))
-                       memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
+                       ether_addr_copy(tsi_eth_data.mac_addr, mac_addr);
 
                ph = of_get_property(np, "mdio-handle", NULL);
                mdio = of_find_node_by_phandle(*ph);
index bc7b77e..8bf6f9c 100644 (file)
@@ -66,11 +66,6 @@ void __init mem_init(void)
        mem_init_print_info(NULL);
 }
 
-void free_initmem(void)
-{
-       free_initmem_default(0);
-}
-
 #ifdef CONFIG_BLK_DEV_INITRD
 static void __init setup_initrd(void)
 {
index 0748558..109243f 100644 (file)
@@ -63,7 +63,7 @@ config S390
        select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_FORTIFY_SOURCE
        select ARCH_HAS_GCOV_PROFILE_ALL
-       select ARCH_HAS_GIGANTIC_PAGE if (MEMORY_ISOLATION && COMPACTION) || CMA
+       select ARCH_HAS_GIGANTIC_PAGE
        select ARCH_HAS_KCOV
        select ARCH_HAS_PTE_SPECIAL
        select ARCH_HAS_SET_MEMORY
@@ -100,6 +100,7 @@ config S390
        select ARCH_INLINE_WRITE_UNLOCK_BH
        select ARCH_INLINE_WRITE_UNLOCK_IRQ
        select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
+       select ARCH_KEEP_MEMBLOCK
        select ARCH_SAVE_PAGE_KEYS if HIBERNATION
        select ARCH_SUPPORTS_ATOMIC_RMW
        select ARCH_SUPPORTS_NUMA_BALANCING
index 3cc52e3..f316de4 100644 (file)
@@ -202,7 +202,7 @@ static inline int __cpacf_check_opcode(unsigned int opcode)
        }
 }
 
-static inline int cpacf_query(unsigned int opcode, cpacf_mask_t *mask)
+static __always_inline int cpacf_query(unsigned int opcode, cpacf_mask_t *mask)
 {
        if (__cpacf_check_opcode(opcode)) {
                __cpacf_query(opcode, mask);
index 2d1afa5..bb59dd9 100644 (file)
@@ -116,7 +116,9 @@ static inline pte_t huge_pte_modify(pte_t pte, pgprot_t newprot)
        return pte_modify(pte, newprot);
 }
 
-#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE
-static inline bool gigantic_page_supported(void) { return true; }
-#endif
+static inline bool gigantic_page_runtime_supported(void)
+{
+       return true;
+}
+
 #endif /* _ASM_S390_HUGETLB_H */
index 672f95b..818612b 100644 (file)
 
 #include <asm/ptrace.h>
 
-static inline int klp_check_compiler_support(void)
-{
-       return 0;
-}
-
 static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 {
        regs->psw.addr = ip;
diff --git a/arch/s390/include/asm/segment.h b/arch/s390/include/asm/segment.h
deleted file mode 100644 (file)
index 97a0582..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_SEGMENT_H
-#define _ASM_SEGMENT_H
-
-#endif
index cd3df55..ad71132 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/seccomp.h>
 #include <linux/compat.h>
 #include <trace/syscall.h>
-#include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
index 37503ae..1fd706f 100644 (file)
@@ -2376,7 +2376,7 @@ static int kvm_s390_adapter_map(struct kvm *kvm, unsigned int id, __u64 addr)
                ret = -EFAULT;
                goto out;
        }
-       ret = get_user_pages_fast(map->addr, 1, 1, &map->page);
+       ret = get_user_pages_fast(map->addr, 1, FOLL_WRITE, &map->page);
        if (ret < 0)
                goto out;
        BUG_ON(ret != 1);
index 7cf48ee..14d1eae 100644 (file)
@@ -157,14 +157,6 @@ void free_initmem(void)
        free_initmem_default(POISON_FREE_INITMEM);
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void __init free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, POISON_FREE_INITMEM,
-                          "initrd");
-}
-#endif
-
 unsigned long memory_block_size_bytes(void)
 {
        /*
@@ -227,8 +219,8 @@ device_initcall(s390_cma_mem_init);
 
 #endif /* CONFIG_CMA */
 
-int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
-               bool want_memblock)
+int arch_add_memory(int nid, u64 start, u64 size,
+               struct mhp_restrictions *restrictions)
 {
        unsigned long start_pfn = PFN_DOWN(start);
        unsigned long size_pages = PFN_DOWN(size);
@@ -238,21 +230,22 @@ int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
        if (rc)
                return rc;
 
-       rc = __add_pages(nid, start_pfn, size_pages, altmap, want_memblock);
+       rc = __add_pages(nid, start_pfn, size_pages, restrictions);
        if (rc)
                vmem_remove_mapping(start, size);
        return rc;
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-int arch_remove_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap)
+void arch_remove_memory(int nid, u64 start, u64 size,
+                       struct vmem_altmap *altmap)
 {
        /*
         * There is no hardware or firmware interface which could trigger a
         * hot memory remove on s390. So there is nothing that needs to be
         * implemented.
         */
-       return -EBUSY;
+       BUG();
 }
 #endif
 #endif /* CONFIG_MEMORY_HOTPLUG */
index 0be08d5..b77f512 100644 (file)
@@ -10,7 +10,6 @@ config SUPERH
        select DMA_DECLARE_COHERENT
        select HAVE_IDE if HAS_IOPORT_MAP
        select HAVE_MEMBLOCK_NODE_MAP
-       select ARCH_DISCARD_MEMBLOCK
        select HAVE_OPROFILE
        select HAVE_ARCH_TRACEHOOK
        select HAVE_PERF_EVENTS
@@ -53,6 +52,7 @@ config SUPERH
        select HAVE_FUTEX_CMPXCHG if FUTEX
        select HAVE_NMI
        select NEED_SG_DMA_LENGTH
+       select ARCH_HAS_GIGANTIC_PAGE
 
        help
          The SuperH is a RISC processor targeted for use in embedded systems
index 346eda7..abf19a9 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/irq.h>
 #include <linux/clk.h>
 #include <asm/machvec.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/clock.h>
 
 static struct mtd_partition nor_flash_partitions[] = {
index 4efa9c5..fa031a1 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/irq.h>
 #include <linux/clk.h>
 #include <asm/machvec.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 /* Dummy supplies, where voltage doesn't matter */
 static struct regulator_consumer_supply dummy_supplies[] = {
index 67a8803..0de7d60 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/smc91x.h>
 #include <linux/sh_intc.h>
 #include <asm/machvec.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #define SMC_IOBASE     0xA2000000
 #define SMC_IO_OFFSET  0x300
index 0fbe91c..7569d85 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/addrspace.h>
 #include <asm/delay.h>
 #include <asm/i2c-sh7760.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 /* Bus state controller registers for CS4 area */
 #define BSC_CS4BCR     0xA4FD0010
index f478fee..6e784b5 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/sh_eth.h>
 #include <linux/sh_intc.h>
 #include <asm/machvec.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 /* NOR Flash */
 static struct mtd_partition espt_nor_flash_partitions[] = {
index 799af57..dad2b3b 100644 (file)
@@ -21,7 +21,7 @@
 #include <mach/urquell.h>
 #include <cpu/sh7786.h>
 #include <asm/heartbeat.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/smp-ops.h>
 
 /*
index a929f76..cc06e4c 100644 (file)
@@ -10,7 +10,6 @@
  */
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <linux/irq.h>
 #include <linux/export.h>
 #include <linux/err.h>
 #include <mach/sysasic.h>
index 706b48f..f4a777f 100644 (file)
@@ -15,7 +15,7 @@
 #include <mach/microdev.h>
 #include <asm/io.h>
 #include <asm/machvec.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 static struct resource smc91x_resources[] = {
        [0] = {
index 6d2a3d3..895576f 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/io.h>
 #include <linux/bcd.h>
 #include <mach/fpga.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #define FPGA_REGS_OFFSET       0x03fff800
 #define FPGA_REGS_SIZE         0x490
index 65721c3..d183026 100644 (file)
@@ -19,7 +19,7 @@
 #include <mach/irq.h>
 #include <asm/machvec.h>
 #include <asm/heartbeat.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/clock.h>
 #include <asm/reboot.h>
 #include <asm/smp-ops.h>
index d76cdb7..7c6ca97 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/string.h>
 #include <mach/fpga.h>
 #include <asm/sram.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 static int __init fpga_sram_init(void)
 {
index 39a3175..1aedbfe 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/irqdomain.h>
 #include <linux/io.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <mach-se/mach/se7343.h>
 
 #define PA_CPLD_BASE_ADDR      0x11400000
index f6e3009..6d34592 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/irqdomain.h>
 #include <linux/io.h>
 #include <linux/err.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <mach-se/mach/se7722.h>
 
 #define IRQ01_BASE_ADDR        0x11800000
index 1b9e5ca..11ed21c 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/io.h>
 #include "pci-sh4.h"
 #include <asm/addrspace.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 static int __init __area_sdram_check(struct pci_channel *chan,
                                     unsigned int area)
index 3fd0f39..287b3a6 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/log2.h>
 #include "pci-sh4.h"
 #include <asm/mmu.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #if defined(CONFIG_CPU_BIG_ENDIAN)
 # define PCICR_ENDIANNESS SH4_PCICR_BSWP
index a58b77c..e0b568a 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/sh_intc.h>
 #include <cpu/sh7786.h>
 #include "pcie-sh7786.h"
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 struct sh7786_pcie_port {
        struct pci_channel      *hose;
index 73fff39..51a54df 100644 (file)
@@ -18,6 +18,5 @@ generic-y += parport.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += serial.h
-generic-y += sizes.h
 generic-y += trace_clock.h
 generic-y += xor.h
index 3e27f6d..277c882 100644 (file)
@@ -204,7 +204,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
  * get_user_pages_fast() - pin user pages in memory
  * @start:     starting user address
  * @nr_pages:  number of pages from start to pin
- * @write:     whether pages will be written to
+ * @gup_flags: flags modifying pin behaviour
  * @pages:     array that receives pointers to the pages pinned.
  *             Should be at least nr_pages long.
  *
@@ -216,8 +216,8 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
  * requested. If nr_pages is 0 or negative, returns 0. If no pages
  * were pinned, returns -errno.
  */
-int get_user_pages_fast(unsigned long start, int nr_pages, int write,
-                       struct page **pages)
+int get_user_pages_fast(unsigned long start, int nr_pages,
+                       unsigned int gup_flags, struct page **pages)
 {
        struct mm_struct *mm = current->mm;
        unsigned long addr, len, end;
@@ -241,7 +241,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
                next = pgd_addr_end(addr, end);
                if (pgd_none(pgd))
                        goto slow;
-               if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
+               if (!gup_pud_range(pgd, addr, next, gup_flags & FOLL_WRITE,
+                                  pages, &nr))
                        goto slow;
        } while (pgdp++, addr = next, addr != end);
        local_irq_enable();
@@ -261,7 +262,7 @@ slow_irqon:
 
                ret = get_user_pages_unlocked(start,
                        (end - start) >> PAGE_SHIFT, pages,
-                       write ? FOLL_WRITE : 0);
+                       gup_flags);
 
                /* Have to be a bit careful with return values */
                if (nr > 0) {
index 7062132..5aeb4d7 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/cache.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
@@ -403,28 +403,16 @@ void __init mem_init(void)
        mem_init_done = 1;
 }
 
-void free_initmem(void)
-{
-       free_initmem_default(-1);
-}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
-
 #ifdef CONFIG_MEMORY_HOTPLUG
-int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
-               bool want_memblock)
+int arch_add_memory(int nid, u64 start, u64 size,
+                       struct mhp_restrictions *restrictions)
 {
        unsigned long start_pfn = PFN_DOWN(start);
        unsigned long nr_pages = size >> PAGE_SHIFT;
        int ret;
 
        /* We only have ZONE_NORMAL, so this is easy.. */
-       ret = __add_pages(nid, start_pfn, nr_pages, altmap, want_memblock);
+       ret = __add_pages(nid, start_pfn, nr_pages, restrictions);
        if (unlikely(ret))
                printk("%s: Failed, __add_pages() == %d\n", __func__, ret);
 
@@ -441,20 +429,15 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
 #endif
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-int arch_remove_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap)
+void arch_remove_memory(int nid, u64 start, u64 size,
+                       struct vmem_altmap *altmap)
 {
        unsigned long start_pfn = PFN_DOWN(start);
        unsigned long nr_pages = size >> PAGE_SHIFT;
        struct zone *zone;
-       int ret;
 
        zone = page_zone(pfn_to_page(start_pfn));
-       ret = __remove_pages(zone, start_pfn, nr_pages, altmap);
-       if (unlikely(ret))
-               pr_warn("%s: Failed, __remove_pages() == %d\n", __func__,
-                       ret);
-
-       return ret;
+       __remove_pages(zone, start_pfn, nr_pages, altmap);
 }
 #endif
 #endif /* CONFIG_MEMORY_HOTPLUG */
index 7b2cc49..a53a040 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/spinlock.h>
 #include <linux/vmalloc.h>
 #include <asm/cacheflush.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
index 010010b..bd1585e 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/init.h>
 #include <linux/module.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/page.h>
 #include <asm/addrspace.h>
 
index f6421c9..7c93f31 100644 (file)
@@ -92,6 +92,7 @@ config SPARC64
        select ARCH_CLOCKSOURCE_DATA
        select ARCH_HAS_PTE_SPECIAL
        select PCI_DOMAINS if PCI
+       select ARCH_HAS_GIGANTIC_PAGE
 
 config ARCH_DEFCONFIG
        string
index 1393a8a..22500c3 100644 (file)
@@ -231,36 +231,6 @@ extern unsigned long _PAGE_ALL_SZ_BITS;
 extern struct page *mem_map_zero;
 #define ZERO_PAGE(vaddr)       (mem_map_zero)
 
-/* This macro must be updated when the size of struct page grows above 80
- * or reduces below 64.
- * The idea that compiler optimizes out switch() statement, and only
- * leaves clrx instructions
- */
-#define        mm_zero_struct_page(pp) do {                                    \
-       unsigned long *_pp = (void *)(pp);                              \
-                                                                       \
-        /* Check that struct page is either 64, 72, or 80 bytes */     \
-       BUILD_BUG_ON(sizeof(struct page) & 7);                          \
-       BUILD_BUG_ON(sizeof(struct page) < 64);                         \
-       BUILD_BUG_ON(sizeof(struct page) > 80);                         \
-                                                                       \
-       switch (sizeof(struct page)) {                                  \
-       case 80:                                                        \
-               _pp[9] = 0;     /* fallthrough */                       \
-       case 72:                                                        \
-               _pp[8] = 0;     /* fallthrough */                       \
-       default:                                                        \
-               _pp[7] = 0;                                             \
-               _pp[6] = 0;                                             \
-               _pp[5] = 0;                                             \
-               _pp[4] = 0;                                             \
-               _pp[3] = 0;                                             \
-               _pp[2] = 0;                                             \
-               _pp[1] = 0;                                             \
-               _pp[0] = 0;                                             \
-       }                                                               \
-} while (0)
-
 /* PFNs are real physical page numbers.  However, mem_map only begins to record
  * per-page information starting at pfn_base.  This is to handle systems where
  * the first physical page in the machine is at some huge physical address,
index 3eb7794..89fb05f 100644 (file)
@@ -653,19 +653,23 @@ static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val
                                    void *data)
 {
        struct cpufreq_freqs *freq = data;
-       unsigned int cpu = freq->cpu;
-       struct freq_table *ft = &per_cpu(sparc64_freq_table, cpu);
+       unsigned int cpu;
+       struct freq_table *ft;
 
-       if (!ft->ref_freq) {
-               ft->ref_freq = freq->old;
-               ft->clock_tick_ref = cpu_data(cpu).clock_tick;
-       }
-       if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
-           (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
-               cpu_data(cpu).clock_tick =
-                       cpufreq_scale(ft->clock_tick_ref,
-                                     ft->ref_freq,
-                                     freq->new);
+       for_each_cpu(cpu, freq->policy->cpus) {
+               ft = &per_cpu(sparc64_freq_table, cpu);
+
+               if (!ft->ref_freq) {
+                       ft->ref_freq = freq->old;
+                       ft->clock_tick_ref = cpu_data(cpu).clock_tick;
+               }
+
+               if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
+                   (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
+                       cpu_data(cpu).clock_tick =
+                               cpufreq_scale(ft->clock_tick_ref, ft->ref_freq,
+                                             freq->new);
+               }
        }
 
        return 0;
index aee6dba..1e770a5 100644 (file)
@@ -245,8 +245,8 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
        return nr;
 }
 
-int get_user_pages_fast(unsigned long start, int nr_pages, int write,
-                       struct page **pages)
+int get_user_pages_fast(unsigned long start, int nr_pages,
+                       unsigned int gup_flags, struct page **pages)
 {
        struct mm_struct *mm = current->mm;
        unsigned long addr, len, end;
@@ -303,7 +303,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
                next = pgd_addr_end(addr, end);
                if (pgd_none(pgd))
                        goto slow;
-               if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
+               if (!gup_pud_range(pgd, addr, next, gup_flags & FOLL_WRITE,
+                                  pages, &nr))
                        goto slow;
        } while (pgdp++, addr = next, addr != end);
 
@@ -324,7 +325,7 @@ slow:
 
                ret = get_user_pages_unlocked(start,
                        (end - start) >> PAGE_SHIFT, pages,
-                       write ? FOLL_WRITE : 0);
+                       gup_flags);
 
                /* Have to be a bit careful with return values */
                if (nr > 0) {
index a8ff298..046ab11 100644 (file)
@@ -294,19 +294,6 @@ void __init mem_init(void)
        mem_init_print_info(NULL);
 }
 
-void free_initmem (void)
-{
-       free_initmem_default(POISON_FREE_INITMEM);
-}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, POISON_FREE_INITMEM,
-                          "initrd");
-}
-#endif
-
 void sparc_flush_page_to_ram(struct page *page)
 {
        unsigned long vaddr = (unsigned long)page_address(page);
index bc2aaa4..4b099dd 100644 (file)
@@ -2572,14 +2572,6 @@ void free_initmem(void)
        }
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, POISON_FREE_INITMEM,
-                          "initrd");
-}
-#endif
-
 pgprot_t PAGE_KERNEL __read_mostly;
 EXPORT_SYMBOL(PAGE_KERNEL);
 
index 99aa11b..a9c9a94 100644 (file)
@@ -188,13 +188,6 @@ void free_initmem(void)
 {
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
-
 /* Allocate and free page tables. */
 
 pgd_t *pgd_alloc(struct mm_struct *mm)
index 2445dfc..41fe944 100644 (file)
@@ -3,6 +3,7 @@ config UNICORE32
        def_bool y
        select ARCH_32BIT_OFF_T
        select ARCH_HAS_DEVMEM_IS_ALLOWED
+       select ARCH_HAS_KEEPINITRD
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_MIGHT_HAVE_PC_SERIO
        select HAVE_KERNEL_GZIP
@@ -190,7 +191,6 @@ config I2C_EEPROM_AT24
 
 config LCD_BACKLIGHT
        tristate "LCD Backlight support"
-       select BACKLIGHT_LCD_SUPPORT
        select BACKLIGHT_PWM
 
 endmenu
index aebd01f..360cc9a 100644 (file)
@@ -119,7 +119,7 @@ CONFIG_I2C_PUV3=y
 #      Hardware Monitoring support
 #CONFIG_SENSORS_LM75=m
 #      Generic Thermal sysfs driver
-#CONFIG_THERMAL=m
+#CONFIG_THERMAL=y
 #CONFIG_THERMAL_HWMON=y
 
 #      Multimedia support
index b301a0b..5fe2426 100644 (file)
@@ -28,10 +28,8 @@ generic-y += parport.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += sections.h
-generic-y += segment.h
 generic-y += serial.h
 generic-y += shmparam.h
-generic-y += sizes.h
 generic-y += syscalls.h
 generic-y += topology.h
 generic-y += trace_clock.h
index 66bb9f6..46cf27e 100644 (file)
@@ -16,7 +16,7 @@
 
 #include <linux/compiler.h>
 #include <linux/const.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <mach/memory.h>
 
 /*
index 74b6a2e..c994cdf 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <asm/sections.h>
 #include <asm/setup.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/tlb.h>
 #include <asm/memblock.h>
 #include <mach/map.h>
@@ -287,27 +287,3 @@ void __init mem_init(void)
                sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
        }
 }
-
-void free_initmem(void)
-{
-       free_initmem_default(-1);
-}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-
-static int keep_initrd;
-
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-       if (!keep_initrd)
-               free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-
-static int __init keepinitrd_setup(char *__unused)
-{
-       keep_initrd = 1;
-       return 1;
-}
-
-__setup("keepinitrd", keepinitrd_setup);
-#endif
index bf012b2..b69cb18 100644 (file)
@@ -34,7 +34,7 @@
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <mach/map.h>
 #include "mm.h"
index aa2060b..f0ae623 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/cputype.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/tlb.h>
 #include <asm/memblock.h>
 
index e721273..2bbbd4d 100644 (file)
@@ -22,7 +22,7 @@ config X86_64
        def_bool y
        depends on 64BIT
        # Options that are inherently 64-bit kernel only:
-       select ARCH_HAS_GIGANTIC_PAGE if (MEMORY_ISOLATION && COMPACTION) || CMA
+       select ARCH_HAS_GIGANTIC_PAGE
        select ARCH_SUPPORTS_INT128
        select ARCH_USE_CMPXCHG_LOCKREF
        select HAVE_ARCH_SOFT_DIRTY
@@ -31,6 +31,17 @@ config X86_64
        select SWIOTLB
        select ARCH_HAS_SYSCALL_WRAPPER
 
+config FORCE_DYNAMIC_FTRACE
+       def_bool y
+       depends on X86_32
+       depends on FUNCTION_TRACER
+       select DYNAMIC_FTRACE
+       help
+        We keep the static function tracing (!DYNAMIC_FTRACE) around
+        in order to test the non static function tracing in the
+        generic code, as other architectures still use it. But we
+        only need to keep it around for x86_64. No need to keep it
+        for x86_32. For x86_32, force DYNAMIC_FTRACE. 
 #
 # Arch settings
 #
@@ -47,7 +58,6 @@ config X86
        select ARCH_32BIT_OFF_T                 if X86_32
        select ARCH_CLOCKSOURCE_DATA
        select ARCH_CLOCKSOURCE_INIT
-       select ARCH_DISCARD_MEMBLOCK
        select ARCH_HAS_ACPI_TABLE_UPGRADE      if ACPI
        select ARCH_HAS_DEBUG_VIRTUAL
        select ARCH_HAS_DEVMEM_IS_ALLOWED
@@ -260,9 +270,6 @@ config GENERIC_BUG
 config GENERIC_BUG_RELATIVE_POINTERS
        bool
 
-config GENERIC_HWEIGHT
-       def_bool y
-
 config ARCH_MAY_HAVE_PC_FDC
        def_bool y
        depends on ISA_DMA_API
@@ -306,9 +313,6 @@ config ZONE_DMA32
 config AUDIT_ARCH
        def_bool y if X86_64
 
-config ARCH_SUPPORTS_OPTIMIZED_INLINING
-       def_bool y
-
 config ARCH_SUPPORTS_DEBUG_PAGEALLOC
        def_bool y
 
index 15d0fbe..f730680 100644 (file)
@@ -266,20 +266,6 @@ config CPA_DEBUG
        ---help---
          Do change_page_attr() self-tests every 30 seconds.
 
-config OPTIMIZE_INLINING
-       bool "Allow gcc to uninline functions marked 'inline'"
-       ---help---
-         This option determines if the kernel forces gcc to inline the functions
-         developers have marked 'inline'. Doing so takes away freedom from gcc to
-         do what it thinks is best, which is desirable for the gcc 3.x series of
-         compilers. The gcc 4.x series have a rewritten inlining algorithm and
-         enabling this option will generate a smaller kernel there. Hopefully
-         this algorithm is so good that allowing gcc 4.x and above to make the
-         decision will become the default in the future. Until then this option
-         is there to test gcc for this.
-
-         If unsure, say N.
-
 config DEBUG_ENTRY
        bool "Debug low-level entry code"
        depends on DEBUG_KERNEL
index 51beb8d..a986b3c 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/vdso.h>
 #include <asm/cpufeature.h>
 #include <asm/fpu/api.h>
+#include <asm/nospec-branch.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
@@ -220,6 +221,8 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
 #endif
 
        user_enter_irqoff();
+
+       mds_user_clear_cpu_buffers();
 }
 
 #define SYSCALL_EXIT_WORK_FLAGS                                \
index 20e45d9..11aa3b2 100644 (file)
@@ -878,7 +878,7 @@ apicinterrupt IRQ_WORK_VECTOR                       irq_work_interrupt              smp_irq_work_interrupt
  * @paranoid == 2 is special: the stub will never switch stacks.  This is for
  * #DF: if the thread stack is somehow unusable, we'll still get a useful OOPS.
  */
-.macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1 ist_offset=0
+.macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1 ist_offset=0 create_gap=0
 ENTRY(\sym)
        UNWIND_HINT_IRET_REGS offset=\has_error_code*8
 
@@ -898,6 +898,20 @@ ENTRY(\sym)
        jnz     .Lfrom_usermode_switch_stack_\@
        .endif
 
+       .if \create_gap == 1
+       /*
+        * If coming from kernel space, create a 6-word gap to allow the
+        * int3 handler to emulate a call instruction.
+        */
+       testb   $3, CS-ORIG_RAX(%rsp)
+       jnz     .Lfrom_usermode_no_gap_\@
+       .rept   6
+       pushq   5*8(%rsp)
+       .endr
+       UNWIND_HINT_IRET_REGS offset=8
+.Lfrom_usermode_no_gap_\@:
+       .endif
+
        .if \paranoid
        call    paranoid_entry
        .else
@@ -1129,7 +1143,7 @@ apicinterrupt3 HYPERV_STIMER0_VECTOR \
 #endif /* CONFIG_HYPERV */
 
 idtentry debug                 do_debug                has_error_code=0        paranoid=1 shift_ist=IST_INDEX_DB ist_offset=DB_STACK_OFFSET
-idtentry int3                  do_int3                 has_error_code=0
+idtentry int3                  do_int3                 has_error_code=0        create_gap=1
 idtentry stack_segment         do_stack_segment        has_error_code=1
 
 #ifdef CONFIG_XEN_PV
index 8e470b0..3a4d8d4 100644 (file)
@@ -73,14 +73,12 @@ const char *outfilename;
 enum {
        sym_vvar_start,
        sym_vvar_page,
-       sym_hpet_page,
        sym_pvclock_page,
        sym_hvclock_page,
 };
 
 const int special_pages[] = {
        sym_vvar_page,
-       sym_hpet_page,
        sym_pvclock_page,
        sym_hvclock_page,
 };
@@ -93,7 +91,6 @@ struct vdso_sym {
 struct vdso_sym required_syms[] = {
        [sym_vvar_start] = {"vvar_start", true},
        [sym_vvar_page] = {"vvar_page", true},
-       [sym_hpet_page] = {"hpet_page", true},
        [sym_pvclock_page] = {"pvclock_page", true},
        [sym_hvclock_page] = {"hvclock_page", true},
        {"VDSO32_NOTE_MASK", true},
index 7635c23..58a6993 100644 (file)
@@ -393,7 +393,7 @@ static __init int _init_events_attrs(void)
        return 0;
 }
 
-const struct attribute_group *amd_iommu_attr_groups[] = {
+static const struct attribute_group *amd_iommu_attr_groups[] = {
        &amd_iommu_format_group,
        &amd_iommu_cpumask_group,
        &amd_iommu_events_group,
index 7cdd7b1..890a3fb 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/device.h>
 #include <linux/coredump.h>
 
-#include <asm-generic/sizes.h>
+#include <linux/sizes.h>
 #include <asm/perf_event.h>
 
 #include "../perf_event.h"
index ef763f5..12ec402 100644 (file)
@@ -3265,7 +3265,7 @@ static int intel_pmu_hw_config(struct perf_event *event)
                return ret;
 
        if (event->attr.precise_ip) {
-               if (!(event->attr.freq || event->attr.wakeup_events)) {
+               if (!(event->attr.freq || (event->attr.wakeup_events && !event->attr.watermark))) {
                        event->hw.flags |= PERF_X86_EVENT_AUTO_RELOAD;
                        if (!(event->attr.sample_type &
                              ~intel_pmu_large_pebs_flags(event)))
index 07fc84b..a6ac2f4 100644 (file)
@@ -394,10 +394,10 @@ struct cpu_hw_events {
 
 /* Event constraint, but match on all event flags too. */
 #define INTEL_FLAGS_EVENT_CONSTRAINT(c, n) \
-       EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS)
+       EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT|X86_ALL_EVENT_FLAGS)
 
 #define INTEL_FLAGS_EVENT_CONSTRAINT_RANGE(c, e, n)                    \
-       EVENT_CONSTRAINT_RANGE(c, e, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS)
+       EVENT_CONSTRAINT_RANGE(c, e, n, ARCH_PERFMON_EVENTSEL_EVENT|X86_ALL_EVENT_FLAGS)
 
 /* Check only flags, but allow all event/umask */
 #define INTEL_ALL_EVENT_CONSTRAINT(code, n)    \
index fc06935..ba88edd 100644 (file)
@@ -12,8 +12,6 @@
 #define REG_OUT "a"
 #endif
 
-#define __HAVE_ARCH_SW_HWEIGHT
-
 static __always_inline unsigned int __arch_hweight32(unsigned int w)
 {
        unsigned int res;
index 981ff94..75f27ee 100644 (file)
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
 #define X86_FEATURE_AVX512_4VNNIW      (18*32+ 2) /* AVX-512 Neural Network Instructions */
 #define X86_FEATURE_AVX512_4FMAPS      (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
+#define X86_FEATURE_MD_CLEAR           (18*32+10) /* VERW clears CPU buffers */
 #define X86_FEATURE_TSX_FORCE_ABORT    (18*32+13) /* "" TSX_FORCE_ABORT */
 #define X86_FEATURE_PCONFIG            (18*32+18) /* Intel PCONFIG */
 #define X86_FEATURE_SPEC_CTRL          (18*32+26) /* "" Speculation Control (IBRS + IBPB) */
 #define X86_BUG_SPECTRE_V2             X86_BUG(16) /* CPU is affected by Spectre variant 2 attack with indirect branches */
 #define X86_BUG_SPEC_STORE_BYPASS      X86_BUG(17) /* CPU is affected by speculative store bypass attack */
 #define X86_BUG_L1TF                   X86_BUG(18) /* CPU is affected by L1 Terminal Fault */
+#define X86_BUG_MDS                    X86_BUG(19) /* CPU is affected by Microarchitectural data sampling */
+#define X86_BUG_MSBDS_ONLY             X86_BUG(20) /* CPU is only affected by the  MSDBS variant of BUG_MDS */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index cf35063..287f1f7 100644 (file)
@@ -3,12 +3,10 @@
 #define _ASM_X86_FTRACE_H
 
 #ifdef CONFIG_FUNCTION_TRACER
-#ifdef CC_USING_FENTRY
-# define MCOUNT_ADDR           ((unsigned long)(__fentry__))
-#else
-# define MCOUNT_ADDR           ((unsigned long)(mcount))
-# define HAVE_FUNCTION_GRAPH_FP_TEST
+#ifndef CC_USING_FENTRY
+# error Compiler does not support fentry?
 #endif
+# define MCOUNT_ADDR           ((unsigned long)(__fentry__))
 #define MCOUNT_INSN_SIZE       5 /* sizeof mcount call */
 
 #ifdef CONFIG_DYNAMIC_FTRACE
index 7469d32..f65cfb4 100644 (file)
@@ -17,8 +17,4 @@ static inline void arch_clear_hugepage_flags(struct page *page)
 {
 }
 
-#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE
-static inline bool gigantic_page_supported(void) { return true; }
-#endif
-
 #endif /* _ASM_X86_HUGETLB_H */
index 2bdbbbc..cdf44aa 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* SPDX-License-Identifier: GPL-2.0 */
 
 /*
  * This file contains definitions from Hyper-V Hypervisor Top-Level Functional
index 058e40f..8a0e56e 100644 (file)
@@ -6,6 +6,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/nospec-branch.h>
+
 /* Provide __cpuidle; we can't safely include <linux/cpu.h> */
 #define __cpuidle __attribute__((__section__(".cpuidle.text")))
 
@@ -54,11 +56,13 @@ static inline void native_irq_enable(void)
 
 static inline __cpuidle void native_safe_halt(void)
 {
+       mds_idle_clear_cpu_buffers();
        asm volatile("sti; hlt": : :"memory");
 }
 
 static inline __cpuidle void native_halt(void)
 {
+       mds_idle_clear_cpu_buffers();
        asm volatile("hlt": : :"memory");
 }
 
index ed80003..a66f670 100644 (file)
 #include <asm/setup.h>
 #include <linux/ftrace.h>
 
-static inline int klp_check_compiler_support(void)
-{
-#ifndef CC_USING_FENTRY
-       return 1;
-#endif
-       return 0;
-}
-
 static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 {
        regs->ip = ip;
index 1378518..88dd202 100644 (file)
@@ -2,6 +2,8 @@
 #ifndef _ASM_X86_MSR_INDEX_H
 #define _ASM_X86_MSR_INDEX_H
 
+#include <linux/bits.h>
+
 /*
  * CPU model specific register (MSR) numbers.
  *
 /* Intel MSRs. Some also available on other CPUs */
 
 #define MSR_IA32_SPEC_CTRL             0x00000048 /* Speculation Control */
-#define SPEC_CTRL_IBRS                 (1 << 0)   /* Indirect Branch Restricted Speculation */
+#define SPEC_CTRL_IBRS                 BIT(0)     /* Indirect Branch Restricted Speculation */
 #define SPEC_CTRL_STIBP_SHIFT          1          /* Single Thread Indirect Branch Predictor (STIBP) bit */
-#define SPEC_CTRL_STIBP                        (1 << SPEC_CTRL_STIBP_SHIFT)    /* STIBP mask */
+#define SPEC_CTRL_STIBP                        BIT(SPEC_CTRL_STIBP_SHIFT)      /* STIBP mask */
 #define SPEC_CTRL_SSBD_SHIFT           2          /* Speculative Store Bypass Disable bit */
-#define SPEC_CTRL_SSBD                 (1 << SPEC_CTRL_SSBD_SHIFT)     /* Speculative Store Bypass Disable */
+#define SPEC_CTRL_SSBD                 BIT(SPEC_CTRL_SSBD_SHIFT)       /* Speculative Store Bypass Disable */
 
 #define MSR_IA32_PRED_CMD              0x00000049 /* Prediction Command */
-#define PRED_CMD_IBPB                  (1 << 0)   /* Indirect Branch Prediction Barrier */
+#define PRED_CMD_IBPB                  BIT(0)     /* Indirect Branch Prediction Barrier */
 
 #define MSR_PPIN_CTL                   0x0000004e
 #define MSR_PPIN                       0x0000004f
 #define MSR_MTRRcap                    0x000000fe
 
 #define MSR_IA32_ARCH_CAPABILITIES     0x0000010a
-#define ARCH_CAP_RDCL_NO               (1 << 0)   /* Not susceptible to Meltdown */
-#define ARCH_CAP_IBRS_ALL              (1 << 1)   /* Enhanced IBRS support */
-#define ARCH_CAP_SKIP_VMENTRY_L1DFLUSH (1 << 3)   /* Skip L1D flush on vmentry */
-#define ARCH_CAP_SSB_NO                        (1 << 4)   /*
-                                                   * Not susceptible to Speculative Store Bypass
-                                                   * attack, so no Speculative Store Bypass
-                                                   * control required.
-                                                   */
+#define ARCH_CAP_RDCL_NO               BIT(0)  /* Not susceptible to Meltdown */
+#define ARCH_CAP_IBRS_ALL              BIT(1)  /* Enhanced IBRS support */
+#define ARCH_CAP_SKIP_VMENTRY_L1DFLUSH BIT(3)  /* Skip L1D flush on vmentry */
+#define ARCH_CAP_SSB_NO                        BIT(4)  /*
+                                                * Not susceptible to Speculative Store Bypass
+                                                * attack, so no Speculative Store Bypass
+                                                * control required.
+                                                */
+#define ARCH_CAP_MDS_NO                        BIT(5)   /*
+                                                 * Not susceptible to
+                                                 * Microarchitectural Data
+                                                 * Sampling (MDS) vulnerabilities.
+                                                 */
 
 #define MSR_IA32_FLUSH_CMD             0x0000010b
-#define L1D_FLUSH                      (1 << 0)   /*
-                                                   * Writeback and invalidate the
-                                                   * L1 data cache.
-                                                   */
+#define L1D_FLUSH                      BIT(0)  /*
+                                                * Writeback and invalidate the
+                                                * L1 data cache.
+                                                */
 
 #define MSR_IA32_BBL_CR_CTL            0x00000119
 #define MSR_IA32_BBL_CR_CTL3           0x0000011e
index 39a2fb2..eb0f80c 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/sched/idle.h>
 
 #include <asm/cpufeature.h>
+#include <asm/nospec-branch.h>
 
 #define MWAIT_SUBSTATE_MASK            0xf
 #define MWAIT_CSTATE_MASK              0xf
@@ -40,6 +41,8 @@ static inline void __monitorx(const void *eax, unsigned long ecx,
 
 static inline void __mwait(unsigned long eax, unsigned long ecx)
 {
+       mds_idle_clear_cpu_buffers();
+
        /* "mwait %eax, %ecx;" */
        asm volatile(".byte 0x0f, 0x01, 0xc9;"
                     :: "a" (eax), "c" (ecx));
@@ -74,6 +77,8 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
 static inline void __mwaitx(unsigned long eax, unsigned long ebx,
                            unsigned long ecx)
 {
+       /* No MDS buffer clear as this is AMD/HYGON only */
+
        /* "mwaitx %eax, %ebx, %ecx;" */
        asm volatile(".byte 0x0f, 0x01, 0xfb;"
                     :: "a" (eax), "b" (ebx), "c" (ecx));
@@ -81,6 +86,8 @@ static inline void __mwaitx(unsigned long eax, unsigned long ebx,
 
 static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
 {
+       mds_idle_clear_cpu_buffers();
+
        trace_hardirqs_on();
        /* "mwait %eax, %ecx;" */
        asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
index daf25b6..109f974 100644 (file)
@@ -308,6 +308,56 @@ DECLARE_STATIC_KEY_FALSE(switch_to_cond_stibp);
 DECLARE_STATIC_KEY_FALSE(switch_mm_cond_ibpb);
 DECLARE_STATIC_KEY_FALSE(switch_mm_always_ibpb);
 
+DECLARE_STATIC_KEY_FALSE(mds_user_clear);
+DECLARE_STATIC_KEY_FALSE(mds_idle_clear);
+
+#include <asm/segment.h>
+
+/**
+ * mds_clear_cpu_buffers - Mitigation for MDS vulnerability
+ *
+ * This uses the otherwise unused and obsolete VERW instruction in
+ * combination with microcode which triggers a CPU buffer flush when the
+ * instruction is executed.
+ */
+static inline void mds_clear_cpu_buffers(void)
+{
+       static const u16 ds = __KERNEL_DS;
+
+       /*
+        * Has to be the memory-operand variant because only that
+        * guarantees the CPU buffer flush functionality according to
+        * documentation. The register-operand variant does not.
+        * Works with any segment selector, but a valid writable
+        * data segment is the fastest variant.
+        *
+        * "cc" clobber is required because VERW modifies ZF.
+        */
+       asm volatile("verw %[ds]" : : [ds] "m" (ds) : "cc");
+}
+
+/**
+ * mds_user_clear_cpu_buffers - Mitigation for MDS vulnerability
+ *
+ * Clear CPU buffers if the corresponding static key is enabled
+ */
+static inline void mds_user_clear_cpu_buffers(void)
+{
+       if (static_branch_likely(&mds_user_clear))
+               mds_clear_cpu_buffers();
+}
+
+/**
+ * mds_idle_clear_cpu_buffers - Mitigation for MDS vulnerability
+ *
+ * Clear CPU buffers if the corresponding static key is enabled
+ */
+static inline void mds_idle_clear_cpu_buffers(void)
+{
+       if (static_branch_likely(&mds_idle_clear))
+               mds_clear_cpu_buffers();
+}
+
 #endif /* __ASSEMBLY__ */
 
 /*
index 7e99ef6..c34a35c 100644 (file)
@@ -978,4 +978,10 @@ enum l1tf_mitigations {
 
 extern enum l1tf_mitigations l1tf_mitigation;
 
+enum mds_mitigations {
+       MDS_MITIGATION_OFF,
+       MDS_MITIGATION_FULL,
+       MDS_MITIGATION_VMWERV,
+};
+
 #endif /* _ASM_X86_PROCESSOR_H */
index c90678f..880b551 100644 (file)
@@ -42,4 +42,34 @@ extern int after_bootmem;
 extern __ro_after_init struct mm_struct *poking_mm;
 extern __ro_after_init unsigned long poking_addr;
 
+#ifndef CONFIG_UML_X86
+static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip)
+{
+       regs->ip = ip;
+}
+
+#define INT3_INSN_SIZE 1
+#define CALL_INSN_SIZE 5
+
+#ifdef CONFIG_X86_64
+static inline void int3_emulate_push(struct pt_regs *regs, unsigned long val)
+{
+       /*
+        * The int3 handler in entry_64.S adds a gap between the
+        * stack where the break point happened, and the saving of
+        * pt_regs. We can extend the original stack because of
+        * this gap. See the idtentry macro's create_gap option.
+        */
+       regs->sp -= sizeof(unsigned long);
+       *(unsigned long *)regs->sp = val;
+}
+
+static inline void int3_emulate_call(struct pt_regs *regs, unsigned long func)
+{
+       int3_emulate_push(regs, regs->ip - INT3_INSN_SIZE + CALL_INSN_SIZE);
+       int3_emulate_jmp(regs, func);
+}
+#endif /* CONFIG_X86_64 */
+#endif /* !CONFIG_UML_X86 */
+
 #endif /* _ASM_X86_TEXT_PATCHING_H */
index 27566e5..230474e 100644 (file)
@@ -19,7 +19,6 @@ struct vdso_image {
        long sym_vvar_start;  /* Negative offset to the vvar area */
 
        long sym_vvar_page;
-       long sym_hpet_page;
        long sym_pvclock_page;
        long sym_hvclock_page;
        long sym_VDSO32_NOTE_MASK;
index 2963039..03b4cc0 100644 (file)
@@ -37,6 +37,7 @@
 static void __init spectre_v2_select_mitigation(void);
 static void __init ssb_select_mitigation(void);
 static void __init l1tf_select_mitigation(void);
+static void __init mds_select_mitigation(void);
 
 /* The base value of the SPEC_CTRL MSR that always has to be preserved. */
 u64 x86_spec_ctrl_base;
@@ -63,6 +64,13 @@ DEFINE_STATIC_KEY_FALSE(switch_mm_cond_ibpb);
 /* Control unconditional IBPB in switch_mm() */
 DEFINE_STATIC_KEY_FALSE(switch_mm_always_ibpb);
 
+/* Control MDS CPU buffer clear before returning to user space */
+DEFINE_STATIC_KEY_FALSE(mds_user_clear);
+EXPORT_SYMBOL_GPL(mds_user_clear);
+/* Control MDS CPU buffer clear before idling (halt, mwait) */
+DEFINE_STATIC_KEY_FALSE(mds_idle_clear);
+EXPORT_SYMBOL_GPL(mds_idle_clear);
+
 void __init check_bugs(void)
 {
        identify_boot_cpu();
@@ -101,6 +109,10 @@ void __init check_bugs(void)
 
        l1tf_select_mitigation();
 
+       mds_select_mitigation();
+
+       arch_smt_update();
+
 #ifdef CONFIG_X86_32
        /*
         * Check whether we are able to run this kernel safely on SMP.
@@ -206,6 +218,61 @@ static void x86_amd_ssb_disable(void)
                wrmsrl(MSR_AMD64_LS_CFG, msrval);
 }
 
+#undef pr_fmt
+#define pr_fmt(fmt)    "MDS: " fmt
+
+/* Default mitigation for MDS-affected CPUs */
+static enum mds_mitigations mds_mitigation __ro_after_init = MDS_MITIGATION_FULL;
+static bool mds_nosmt __ro_after_init = false;
+
+static const char * const mds_strings[] = {
+       [MDS_MITIGATION_OFF]    = "Vulnerable",
+       [MDS_MITIGATION_FULL]   = "Mitigation: Clear CPU buffers",
+       [MDS_MITIGATION_VMWERV] = "Vulnerable: Clear CPU buffers attempted, no microcode",
+};
+
+static void __init mds_select_mitigation(void)
+{
+       if (!boot_cpu_has_bug(X86_BUG_MDS) || cpu_mitigations_off()) {
+               mds_mitigation = MDS_MITIGATION_OFF;
+               return;
+       }
+
+       if (mds_mitigation == MDS_MITIGATION_FULL) {
+               if (!boot_cpu_has(X86_FEATURE_MD_CLEAR))
+                       mds_mitigation = MDS_MITIGATION_VMWERV;
+
+               static_branch_enable(&mds_user_clear);
+
+               if (!boot_cpu_has(X86_BUG_MSBDS_ONLY) &&
+                   (mds_nosmt || cpu_mitigations_auto_nosmt()))
+                       cpu_smt_disable(false);
+       }
+
+       pr_info("%s\n", mds_strings[mds_mitigation]);
+}
+
+static int __init mds_cmdline(char *str)
+{
+       if (!boot_cpu_has_bug(X86_BUG_MDS))
+               return 0;
+
+       if (!str)
+               return -EINVAL;
+
+       if (!strcmp(str, "off"))
+               mds_mitigation = MDS_MITIGATION_OFF;
+       else if (!strcmp(str, "full"))
+               mds_mitigation = MDS_MITIGATION_FULL;
+       else if (!strcmp(str, "full,nosmt")) {
+               mds_mitigation = MDS_MITIGATION_FULL;
+               mds_nosmt = true;
+       }
+
+       return 0;
+}
+early_param("mds", mds_cmdline);
+
 #undef pr_fmt
 #define pr_fmt(fmt)     "Spectre V2 : " fmt
 
@@ -575,9 +642,6 @@ specv2_set_mode:
 
        /* Set up IBPB and STIBP depending on the general spectre V2 command */
        spectre_v2_user_select_mitigation(cmd);
-
-       /* Enable STIBP if appropriate */
-       arch_smt_update();
 }
 
 static void update_stibp_msr(void * __unused)
@@ -611,6 +675,31 @@ static void update_indir_branch_cond(void)
                static_branch_disable(&switch_to_cond_stibp);
 }
 
+#undef pr_fmt
+#define pr_fmt(fmt) fmt
+
+/* Update the static key controlling the MDS CPU buffer clear in idle */
+static void update_mds_branch_idle(void)
+{
+       /*
+        * Enable the idle clearing if SMT is active on CPUs which are
+        * affected only by MSBDS and not any other MDS variant.
+        *
+        * The other variants cannot be mitigated when SMT is enabled, so
+        * clearing the buffers on idle just to prevent the Store Buffer
+        * repartitioning leak would be a window dressing exercise.
+        */
+       if (!boot_cpu_has_bug(X86_BUG_MSBDS_ONLY))
+               return;
+
+       if (sched_smt_active())
+               static_branch_enable(&mds_idle_clear);
+       else
+               static_branch_disable(&mds_idle_clear);
+}
+
+#define MDS_MSG_SMT "MDS CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/mds.html for more details.\n"
+
 void arch_smt_update(void)
 {
        /* Enhanced IBRS implies STIBP. No update required. */
@@ -632,6 +721,17 @@ void arch_smt_update(void)
                break;
        }
 
+       switch (mds_mitigation) {
+       case MDS_MITIGATION_FULL:
+       case MDS_MITIGATION_VMWERV:
+               if (sched_smt_active() && !boot_cpu_has(X86_BUG_MSBDS_ONLY))
+                       pr_warn_once(MDS_MSG_SMT);
+               update_mds_branch_idle();
+               break;
+       case MDS_MITIGATION_OFF:
+               break;
+       }
+
        mutex_unlock(&spec_ctrl_mutex);
 }
 
@@ -1043,7 +1143,7 @@ static void __init l1tf_select_mitigation(void)
                pr_info("You may make it effective by booting the kernel with mem=%llu parameter.\n",
                                half_pa);
                pr_info("However, doing so will make a part of your RAM unusable.\n");
-               pr_info("Reading https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html might help you decide.\n");
+               pr_info("Reading https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/l1tf.html might help you decide.\n");
                return;
        }
 
@@ -1076,6 +1176,7 @@ static int __init l1tf_cmdline(char *str)
 early_param("l1tf", l1tf_cmdline);
 
 #undef pr_fmt
+#define pr_fmt(fmt) fmt
 
 #ifdef CONFIG_SYSFS
 
@@ -1114,6 +1215,23 @@ static ssize_t l1tf_show_state(char *buf)
 }
 #endif
 
+static ssize_t mds_show_state(char *buf)
+{
+       if (!hypervisor_is_type(X86_HYPER_NATIVE)) {
+               return sprintf(buf, "%s; SMT Host state unknown\n",
+                              mds_strings[mds_mitigation]);
+       }
+
+       if (boot_cpu_has(X86_BUG_MSBDS_ONLY)) {
+               return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
+                              (mds_mitigation == MDS_MITIGATION_OFF ? "vulnerable" :
+                               sched_smt_active() ? "mitigated" : "disabled"));
+       }
+
+       return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
+                      sched_smt_active() ? "vulnerable" : "disabled");
+}
+
 static char *stibp_state(void)
 {
        if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
@@ -1180,6 +1298,10 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
                if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV))
                        return l1tf_show_state(buf);
                break;
+
+       case X86_BUG_MDS:
+               return mds_show_state(buf);
+
        default:
                break;
        }
@@ -1211,4 +1333,9 @@ ssize_t cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *b
 {
        return cpu_show_common(dev, attr, buf, X86_BUG_L1TF);
 }
+
+ssize_t cpu_show_mds(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       return cpu_show_common(dev, attr, buf, X86_BUG_MDS);
+}
 #endif
index 8739bdf..d7f55ad 100644 (file)
@@ -940,61 +940,77 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
 #endif
 }
 
-static const __initconst struct x86_cpu_id cpu_no_speculation[] = {
-       { X86_VENDOR_INTEL,     6, INTEL_FAM6_ATOM_SALTWELL,    X86_FEATURE_ANY },
-       { X86_VENDOR_INTEL,     6, INTEL_FAM6_ATOM_SALTWELL_TABLET,     X86_FEATURE_ANY },
-       { X86_VENDOR_INTEL,     6, INTEL_FAM6_ATOM_BONNELL_MID, X86_FEATURE_ANY },
-       { X86_VENDOR_INTEL,     6, INTEL_FAM6_ATOM_SALTWELL_MID,        X86_FEATURE_ANY },
-       { X86_VENDOR_INTEL,     6, INTEL_FAM6_ATOM_BONNELL,     X86_FEATURE_ANY },
-       { X86_VENDOR_CENTAUR,   5 },
-       { X86_VENDOR_INTEL,     5 },
-       { X86_VENDOR_NSC,       5 },
-       { X86_VENDOR_ANY,       4 },
+#define NO_SPECULATION BIT(0)
+#define NO_MELTDOWN    BIT(1)
+#define NO_SSB         BIT(2)
+#define NO_L1TF                BIT(3)
+#define NO_MDS         BIT(4)
+#define MSBDS_ONLY     BIT(5)
+
+#define VULNWL(_vendor, _family, _model, _whitelist)   \
+       { X86_VENDOR_##_vendor, _family, _model, X86_FEATURE_ANY, _whitelist }
+
+#define VULNWL_INTEL(model, whitelist)         \
+       VULNWL(INTEL, 6, INTEL_FAM6_##model, whitelist)
+
+#define VULNWL_AMD(family, whitelist)          \
+       VULNWL(AMD, family, X86_MODEL_ANY, whitelist)
+
+#define VULNWL_HYGON(family, whitelist)                \
+       VULNWL(HYGON, family, X86_MODEL_ANY, whitelist)
+
+static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
+       VULNWL(ANY,     4, X86_MODEL_ANY,       NO_SPECULATION),
+       VULNWL(CENTAUR, 5, X86_MODEL_ANY,       NO_SPECULATION),
+       VULNWL(INTEL,   5, X86_MODEL_ANY,       NO_SPECULATION),
+       VULNWL(NSC,     5, X86_MODEL_ANY,       NO_SPECULATION),
+
+       /* Intel Family 6 */
+       VULNWL_INTEL(ATOM_SALTWELL,             NO_SPECULATION),
+       VULNWL_INTEL(ATOM_SALTWELL_TABLET,      NO_SPECULATION),
+       VULNWL_INTEL(ATOM_SALTWELL_MID,         NO_SPECULATION),
+       VULNWL_INTEL(ATOM_BONNELL,              NO_SPECULATION),
+       VULNWL_INTEL(ATOM_BONNELL_MID,          NO_SPECULATION),
+
+       VULNWL_INTEL(ATOM_SILVERMONT,           NO_SSB | NO_L1TF | MSBDS_ONLY),
+       VULNWL_INTEL(ATOM_SILVERMONT_X,         NO_SSB | NO_L1TF | MSBDS_ONLY),
+       VULNWL_INTEL(ATOM_SILVERMONT_MID,       NO_SSB | NO_L1TF | MSBDS_ONLY),
+       VULNWL_INTEL(ATOM_AIRMONT,              NO_SSB | NO_L1TF | MSBDS_ONLY),
+       VULNWL_INTEL(XEON_PHI_KNL,              NO_SSB | NO_L1TF | MSBDS_ONLY),
+       VULNWL_INTEL(XEON_PHI_KNM,              NO_SSB | NO_L1TF | MSBDS_ONLY),
+
+       VULNWL_INTEL(CORE_YONAH,                NO_SSB),
+
+       VULNWL_INTEL(ATOM_AIRMONT_MID,          NO_L1TF | MSBDS_ONLY),
+
+       VULNWL_INTEL(ATOM_GOLDMONT,             NO_MDS | NO_L1TF),
+       VULNWL_INTEL(ATOM_GOLDMONT_X,           NO_MDS | NO_L1TF),
+       VULNWL_INTEL(ATOM_GOLDMONT_PLUS,        NO_MDS | NO_L1TF),
+
+       /* AMD Family 0xf - 0x12 */
+       VULNWL_AMD(0x0f,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
+       VULNWL_AMD(0x10,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
+       VULNWL_AMD(0x11,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
+       VULNWL_AMD(0x12,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
+
+       /* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
+       VULNWL_AMD(X86_FAMILY_ANY,      NO_MELTDOWN | NO_L1TF | NO_MDS),
+       VULNWL_HYGON(X86_FAMILY_ANY,    NO_MELTDOWN | NO_L1TF | NO_MDS),
        {}
 };
 
-static const __initconst struct x86_cpu_id cpu_no_meltdown[] = {
-       { X86_VENDOR_AMD },
-       { X86_VENDOR_HYGON },
-       {}
-};
-
-/* Only list CPUs which speculate but are non susceptible to SSB */
-static const __initconst struct x86_cpu_id cpu_no_spec_store_bypass[] = {
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_SILVERMONT      },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_AIRMONT         },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_SILVERMONT_X    },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_SILVERMONT_MID  },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_CORE_YONAH           },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_XEON_PHI_KNL         },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_XEON_PHI_KNM         },
-       { X86_VENDOR_AMD,       0x12,                                   },
-       { X86_VENDOR_AMD,       0x11,                                   },
-       { X86_VENDOR_AMD,       0x10,                                   },
-       { X86_VENDOR_AMD,       0xf,                                    },
-       {}
-};
+static bool __init cpu_matches(unsigned long which)
+{
+       const struct x86_cpu_id *m = x86_match_cpu(cpu_vuln_whitelist);
 
-static const __initconst struct x86_cpu_id cpu_no_l1tf[] = {
-       /* in addition to cpu_no_speculation */
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_SILVERMONT      },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_SILVERMONT_X    },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_AIRMONT         },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_SILVERMONT_MID  },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_AIRMONT_MID     },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_GOLDMONT        },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_GOLDMONT_X      },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_GOLDMONT_PLUS   },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_XEON_PHI_KNL         },
-       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_XEON_PHI_KNM         },
-       {}
-};
+       return m && !!(m->driver_data & which);
+}
 
 static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
 {
        u64 ia32_cap = 0;
 
-       if (x86_match_cpu(cpu_no_speculation))
+       if (cpu_matches(NO_SPECULATION))
                return;
 
        setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
@@ -1003,15 +1019,20 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
        if (cpu_has(c, X86_FEATURE_ARCH_CAPABILITIES))
                rdmsrl(MSR_IA32_ARCH_CAPABILITIES, ia32_cap);
 
-       if (!x86_match_cpu(cpu_no_spec_store_bypass) &&
-          !(ia32_cap & ARCH_CAP_SSB_NO) &&
+       if (!cpu_matches(NO_SSB) && !(ia32_cap & ARCH_CAP_SSB_NO) &&
           !cpu_has(c, X86_FEATURE_AMD_SSB_NO))
                setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
 
        if (ia32_cap & ARCH_CAP_IBRS_ALL)
                setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED);
 
-       if (x86_match_cpu(cpu_no_meltdown))
+       if (!cpu_matches(NO_MDS) && !(ia32_cap & ARCH_CAP_MDS_NO)) {
+               setup_force_cpu_bug(X86_BUG_MDS);
+               if (cpu_matches(MSBDS_ONLY))
+                       setup_force_cpu_bug(X86_BUG_MSBDS_ONLY);
+       }
+
+       if (cpu_matches(NO_MELTDOWN))
                return;
 
        /* Rogue Data Cache Load? No! */
@@ -1020,7 +1041,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
 
        setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
 
-       if (x86_match_cpu(cpu_no_l1tf))
+       if (cpu_matches(NO_L1TF))
                return;
 
        setup_force_cpu_bug(X86_BUG_L1TF);
index f4dd733..ebb14a2 100644 (file)
@@ -97,6 +97,7 @@ static void intel_epb_restore(void)
        wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, (epb & ~EPB_MASK) | val);
 }
 
+#ifdef CONFIG_PM
 static struct syscore_ops intel_epb_syscore_ops = {
        .suspend = intel_epb_save,
        .resume = intel_epb_restore,
@@ -193,6 +194,25 @@ static int intel_epb_offline(unsigned int cpu)
        return 0;
 }
 
+static inline void register_intel_ebp_syscore_ops(void)
+{
+       register_syscore_ops(&intel_epb_syscore_ops);
+}
+#else /* !CONFIG_PM */
+static int intel_epb_online(unsigned int cpu)
+{
+       intel_epb_restore();
+       return 0;
+}
+
+static int intel_epb_offline(unsigned int cpu)
+{
+       return intel_epb_save();
+}
+
+static inline void register_intel_ebp_syscore_ops(void) {}
+#endif
+
 static __init int intel_epb_init(void)
 {
        int ret;
@@ -206,7 +226,7 @@ static __init int intel_epb_init(void)
        if (ret < 0)
                goto err_out_online;
 
-       register_syscore_ops(&intel_epb_syscore_ops);
+       register_intel_ebp_syscore_ops();
        return 0;
 
 err_out_online:
index 0caf812..0927bb1 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/kprobes.h>
 #include <asm/ftrace.h>
 #include <asm/nops.h>
+#include <asm/text-patching.h>
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 
@@ -231,6 +232,7 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
 }
 
 static unsigned long ftrace_update_func;
+static unsigned long ftrace_update_func_call;
 
 static int update_ftrace_func(unsigned long ip, void *new)
 {
@@ -259,6 +261,8 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
        unsigned char *new;
        int ret;
 
+       ftrace_update_func_call = (unsigned long)func;
+
        new = ftrace_call_replace(ip, (unsigned long)func);
        ret = update_ftrace_func(ip, new);
 
@@ -294,13 +298,28 @@ int ftrace_int3_handler(struct pt_regs *regs)
        if (WARN_ON_ONCE(!regs))
                return 0;
 
-       ip = regs->ip - 1;
-       if (!ftrace_location(ip) && !is_ftrace_caller(ip))
-               return 0;
+       ip = regs->ip - INT3_INSN_SIZE;
 
-       regs->ip += MCOUNT_INSN_SIZE - 1;
+#ifdef CONFIG_X86_64
+       if (ftrace_location(ip)) {
+               int3_emulate_call(regs, (unsigned long)ftrace_regs_caller);
+               return 1;
+       } else if (is_ftrace_caller(ip)) {
+               if (!ftrace_update_func_call) {
+                       int3_emulate_jmp(regs, ip + CALL_INSN_SIZE);
+                       return 1;
+               }
+               int3_emulate_call(regs, ftrace_update_func_call);
+               return 1;
+       }
+#else
+       if (ftrace_location(ip) || is_ftrace_caller(ip)) {
+               int3_emulate_jmp(regs, ip + CALL_INSN_SIZE);
+               return 1;
+       }
+#endif
 
-       return 1;
+       return 0;
 }
 NOKPROBE_SYMBOL(ftrace_int3_handler);
 
@@ -865,6 +884,8 @@ void arch_ftrace_update_trampoline(struct ftrace_ops *ops)
 
        func = ftrace_ops_get_func(ops);
 
+       ftrace_update_func_call = (unsigned long)func;
+
        /* Do a safe modify in case the trampoline is executing */
        new = ftrace_call_replace(ip, (unsigned long)func);
        ret = update_ftrace_func(ip, new);
@@ -966,6 +987,7 @@ static int ftrace_mod_jmp(unsigned long ip, void *func)
 {
        unsigned char *new;
 
+       ftrace_update_func_call = 0UL;
        new = ftrace_jmp_replace(ip, (unsigned long)func);
 
        return update_ftrace_func(ip, new);
index 4c8440d..2ba914a 100644 (file)
 #include <asm/ftrace.h>
 #include <asm/nospec-branch.h>
 
-#ifdef CC_USING_FENTRY
 # define function_hook __fentry__
 EXPORT_SYMBOL(__fentry__)
-#else
-# define function_hook mcount
-EXPORT_SYMBOL(mcount)
-#endif
-
-#ifdef CONFIG_DYNAMIC_FTRACE
-
-/* mcount uses a frame pointer even if CONFIG_FRAME_POINTER is not set */
-#if !defined(CC_USING_FENTRY) || defined(CONFIG_FRAME_POINTER)
-# define USING_FRAME_POINTER
-#endif
 
-#ifdef USING_FRAME_POINTER
+#ifdef CONFIG_FRAME_POINTER
 # define MCOUNT_FRAME                  1       /* using frame = true  */
 #else
 # define MCOUNT_FRAME                  0       /* using frame = false */
@@ -37,8 +25,7 @@ END(function_hook)
 
 ENTRY(ftrace_caller)
 
-#ifdef USING_FRAME_POINTER
-# ifdef CC_USING_FENTRY
+#ifdef CONFIG_FRAME_POINTER
        /*
         * Frame pointers are of ip followed by bp.
         * Since fentry is an immediate jump, we are left with
@@ -49,7 +36,7 @@ ENTRY(ftrace_caller)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   2*4(%esp)                       /* function ip */
-# endif
+
        /* For mcount, the function ip is directly above */
        pushl   %ebp
        movl    %esp, %ebp
@@ -59,7 +46,7 @@ ENTRY(ftrace_caller)
        pushl   %edx
        pushl   $0                              /* Pass NULL as regs pointer */
 
-#ifdef USING_FRAME_POINTER
+#ifdef CONFIG_FRAME_POINTER
        /* Load parent ebp into edx */
        movl    4*4(%esp), %edx
 #else
@@ -82,13 +69,11 @@ ftrace_call:
        popl    %edx
        popl    %ecx
        popl    %eax
-#ifdef USING_FRAME_POINTER
+#ifdef CONFIG_FRAME_POINTER
        popl    %ebp
-# ifdef CC_USING_FENTRY
        addl    $4,%esp                         /* skip function ip */
        popl    %ebp                            /* this is the orig bp */
        addl    $4, %esp                        /* skip parent ip */
-# endif
 #endif
 .Lftrace_ret:
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -133,11 +118,7 @@ ENTRY(ftrace_regs_caller)
 
        movl    12*4(%esp), %eax                /* Load ip (1st parameter) */
        subl    $MCOUNT_INSN_SIZE, %eax         /* Adjust ip */
-#ifdef CC_USING_FENTRY
        movl    15*4(%esp), %edx                /* Load parent ip (2nd parameter) */
-#else
-       movl    0x4(%ebp), %edx                 /* Load parent ip (2nd parameter) */
-#endif
        movl    function_trace_op, %ecx         /* Save ftrace_pos in 3rd parameter */
        pushl   %esp                            /* Save pt_regs as 4th parameter */
 
@@ -170,43 +151,6 @@ GLOBAL(ftrace_regs_call)
        lea     3*4(%esp), %esp                 /* Skip orig_ax, ip and cs */
 
        jmp     .Lftrace_ret
-#else /* ! CONFIG_DYNAMIC_FTRACE */
-
-ENTRY(function_hook)
-       cmpl    $__PAGE_OFFSET, %esp
-       jb      ftrace_stub                     /* Paging not enabled yet? */
-
-       cmpl    $ftrace_stub, ftrace_trace_function
-       jnz     .Ltrace
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       cmpl    $ftrace_stub, ftrace_graph_return
-       jnz     ftrace_graph_caller
-
-       cmpl    $ftrace_graph_entry_stub, ftrace_graph_entry
-       jnz     ftrace_graph_caller
-#endif
-.globl ftrace_stub
-ftrace_stub:
-       ret
-
-       /* taken from glibc */
-.Ltrace:
-       pushl   %eax
-       pushl   %ecx
-       pushl   %edx
-       movl    0xc(%esp), %eax
-       movl    0x4(%ebp), %edx
-       subl    $MCOUNT_INSN_SIZE, %eax
-
-       movl    ftrace_trace_function, %ecx
-       CALL_NOSPEC %ecx
-
-       popl    %edx
-       popl    %ecx
-       popl    %eax
-       jmp     ftrace_stub
-END(function_hook)
-#endif /* CONFIG_DYNAMIC_FTRACE */
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 ENTRY(ftrace_graph_caller)
@@ -215,13 +159,8 @@ ENTRY(ftrace_graph_caller)
        pushl   %edx
        movl    3*4(%esp), %eax
        /* Even with frame pointers, fentry doesn't have one here */
-#ifdef CC_USING_FENTRY
        lea     4*4(%esp), %edx
        movl    $0, %ecx
-#else
-       lea     0x4(%ebp), %edx
-       movl    (%ebp), %ecx
-#endif
        subl    $MCOUNT_INSN_SIZE, %eax
        call    prepare_ftrace_return
        popl    %edx
@@ -234,11 +173,7 @@ END(ftrace_graph_caller)
 return_to_handler:
        pushl   %eax
        pushl   %edx
-#ifdef CC_USING_FENTRY
        movl    $0, %eax
-#else
-       movl    %ebp, %eax
-#endif
        call    ftrace_return_to_handler
        movl    %eax, %ecx
        popl    %edx
index 75f2b36..10eb276 100644 (file)
        .code64
        .section .entry.text, "ax"
 
-#ifdef CC_USING_FENTRY
 # define function_hook __fentry__
 EXPORT_SYMBOL(__fentry__)
-#else
-# define function_hook mcount
-EXPORT_SYMBOL(mcount)
-#endif
 
 #ifdef CONFIG_FRAME_POINTER
-# ifdef CC_USING_FENTRY
 /* Save parent and function stack frames (rip and rbp) */
 #  define MCOUNT_FRAME_SIZE    (8+16*2)
-# else
-/* Save just function stack frame (rip and rbp) */
-#  define MCOUNT_FRAME_SIZE    (8+16)
-# endif
 #else
 /* No need to save a stack frame */
 # define MCOUNT_FRAME_SIZE     0
@@ -75,17 +65,13 @@ EXPORT_SYMBOL(mcount)
         * fentry is called before the stack frame is set up, where as mcount
         * is called afterward.
         */
-#ifdef CC_USING_FENTRY
+
        /* Save the parent pointer (skip orig rbp and our return address) */
        pushq \added+8*2(%rsp)
        pushq %rbp
        movq %rsp, %rbp
        /* Save the return address (now skip orig rbp, rbp and parent) */
        pushq \added+8*3(%rsp)
-#else
-       /* Can't assume that rip is before this (unless added was zero) */
-       pushq \added+8(%rsp)
-#endif
        pushq %rbp
        movq %rsp, %rbp
 #endif /* CONFIG_FRAME_POINTER */
@@ -113,12 +99,7 @@ EXPORT_SYMBOL(mcount)
        movq %rdx, RBP(%rsp)
 
        /* Copy the parent address into %rsi (second parameter) */
-#ifdef CC_USING_FENTRY
        movq MCOUNT_REG_SIZE+8+\added(%rsp), %rsi
-#else
-       /* %rdx contains original %rbp */
-       movq 8(%rdx), %rsi
-#endif
 
         /* Move RIP to its proper location */
        movq MCOUNT_REG_SIZE+\added(%rsp), %rdi
@@ -303,15 +284,8 @@ ENTRY(ftrace_graph_caller)
        /* Saves rbp into %rdx and fills first parameter  */
        save_mcount_regs
 
-#ifdef CC_USING_FENTRY
        leaq MCOUNT_REG_SIZE+8(%rsp), %rsi
        movq $0, %rdx   /* No framepointers needed */
-#else
-       /* Save address of the return address of traced function */
-       leaq 8(%rdx), %rsi
-       /* ftrace does sanity checks against frame pointers */
-       movq (%rdx), %rdx
-#endif
        call    prepare_ftrace_return
 
        restore_mcount_regs
index cf52ee0..9e4fa24 100644 (file)
@@ -768,7 +768,7 @@ static struct kprobe kretprobe_kprobe = {
 /*
  * Called from kretprobe_trampoline
  */
-static __used void *trampoline_handler(struct pt_regs *regs)
+__used __visible void *trampoline_handler(struct pt_regs *regs)
 {
        struct kprobe_ctlblk *kcb;
        struct kretprobe_instance *ri = NULL;
index 3755d03..05b0989 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/x86_init.h>
 #include <asm/reboot.h>
 #include <asm/cache.h>
+#include <asm/nospec-branch.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/nmi.h>
@@ -551,6 +552,9 @@ nmi_restart:
                write_cr2(this_cpu_read(nmi_cr2));
        if (this_cpu_dec_return(nmi_state))
                goto nmi_restart;
+
+       if (user_mode(regs))
+               mds_user_clear_cpu_buffers();
 }
 NOKPROBE_SYMBOL(do_nmi);
 
index 15b5e98..356dfc5 100644 (file)
@@ -979,7 +979,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
                if (!(freq->flags & CPUFREQ_CONST_LOOPS))
                        mark_tsc_unstable("cpufreq changes");
 
-               set_cyc2ns_scale(tsc_khz, freq->cpu, rdtsc());
+               set_cyc2ns_scale(tsc_khz, freq->policy->cpu, rdtsc());
        }
 
        return 0;
index fd39516..bbbe611 100644 (file)
@@ -410,7 +410,8 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
        /* cpuid 7.0.edx*/
        const u32 kvm_cpuid_7_0_edx_x86_features =
                F(AVX512_4VNNIW) | F(AVX512_4FMAPS) | F(SPEC_CTRL) |
-               F(SPEC_CTRL_SSBD) | F(ARCH_CAPABILITIES) | F(INTEL_STIBP);
+               F(SPEC_CTRL_SSBD) | F(ARCH_CAPABILITIES) | F(INTEL_STIBP) |
+               F(MD_CLEAR);
 
        /* all calls to cpuid_count() should be made on the same cpu */
        get_cpu();
index 6bdca39..0871503 100644 (file)
@@ -140,7 +140,7 @@ static int FNAME(cmpxchg_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
        pt_element_t *table;
        struct page *page;
 
-       npages = get_user_pages_fast((unsigned long)ptep_user, 1, 1, &page);
+       npages = get_user_pages_fast((unsigned long)ptep_user, 1, FOLL_WRITE, &page);
        /* Check if the user is doing something meaningless. */
        if (unlikely(npages != 1))
                return -EFAULT;
index 406b558..6b92eaf 100644 (file)
@@ -1805,7 +1805,7 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr,
                return NULL;
 
        /* Pin the user virtual address. */
-       npinned = get_user_pages_fast(uaddr, npages, write ? FOLL_WRITE : 0, pages);
+       npinned = get_user_pages_fast(uaddr, npages, FOLL_WRITE, pages);
        if (npinned != npages) {
                pr_err("SEV: Failure locking %lu pages.\n", npages);
                goto err;
index 9663d41..e1fa935 100644 (file)
@@ -6431,8 +6431,11 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
         */
        x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0);
 
+       /* L1D Flush includes CPU buffer clear to mitigate MDS */
        if (static_branch_unlikely(&vmx_l1d_should_flush))
                vmx_l1d_flush(vcpu);
+       else if (static_branch_unlikely(&mds_user_clear))
+               mds_clear_cpu_buffers();
 
        if (vcpu->arch.cr2 != read_cr2())
                write_cr2(vcpu->arch.cr2);
@@ -6668,8 +6671,8 @@ free_partial_vcpu:
        return ERR_PTR(err);
 }
 
-#define L1TF_MSG_SMT "L1TF CPU bug present and SMT on, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html for details.\n"
-#define L1TF_MSG_L1D "L1TF CPU bug present and virtualization mitigation disabled, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html for details.\n"
+#define L1TF_MSG_SMT "L1TF CPU bug present and SMT on, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/l1tf.html for details.\n"
+#define L1TF_MSG_L1D "L1TF CPU bug present and virtualization mitigation disabled, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/l1tf.html for details.\n"
 
 static int vmx_vm_init(struct kvm *kvm)
 {
index d75bb97..b9591ab 100644 (file)
@@ -6698,10 +6698,8 @@ static void kvm_hyperv_tsc_notifier(void)
 }
 #endif
 
-static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
-                                    void *data)
+static void __kvmclock_cpufreq_notifier(struct cpufreq_freqs *freq, int cpu)
 {
-       struct cpufreq_freqs *freq = data;
        struct kvm *kvm;
        struct kvm_vcpu *vcpu;
        int i, send_ipi = 0;
@@ -6745,17 +6743,12 @@ static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long va
         *
         */
 
-       if (val == CPUFREQ_PRECHANGE && freq->old > freq->new)
-               return 0;
-       if (val == CPUFREQ_POSTCHANGE && freq->old < freq->new)
-               return 0;
-
-       smp_call_function_single(freq->cpu, tsc_khz_changed, freq, 1);
+       smp_call_function_single(cpu, tsc_khz_changed, freq, 1);
 
        spin_lock(&kvm_lock);
        list_for_each_entry(kvm, &vm_list, vm_list) {
                kvm_for_each_vcpu(i, vcpu, kvm) {
-                       if (vcpu->cpu != freq->cpu)
+                       if (vcpu->cpu != cpu)
                                continue;
                        kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
                        if (vcpu->cpu != smp_processor_id())
@@ -6777,8 +6770,24 @@ static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long va
                 * guest context is entered kvmclock will be updated,
                 * so the guest will not see stale values.
                 */
-               smp_call_function_single(freq->cpu, tsc_khz_changed, freq, 1);
+               smp_call_function_single(cpu, tsc_khz_changed, freq, 1);
        }
+}
+
+static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
+                                    void *data)
+{
+       struct cpufreq_freqs *freq = data;
+       int cpu;
+
+       if (val == CPUFREQ_PRECHANGE && freq->old > freq->new)
+               return 0;
+       if (val == CPUFREQ_POSTCHANGE && freq->old < freq->new)
+               return 0;
+
+       for_each_cpu(cpu, freq->policy->cpus)
+               __kvmclock_cpufreq_notifier(freq, cpu);
+
        return 0;
 }
 
index 92e4c4b..fab0953 100644 (file)
@@ -203,7 +203,7 @@ static __init int setup_hugepagesz(char *opt)
 }
 __setup("hugepagesz=", setup_hugepagesz);
 
-#if (defined(CONFIG_MEMORY_ISOLATION) && defined(CONFIG_COMPACTION)) || defined(CONFIG_CMA)
+#ifdef CONFIG_CONTIG_ALLOC
 static __init int gigantic_pages_init(void)
 {
        /* With compaction or CMA we can allocate gigantic pages at runtime */
index 85c94f9..075e568 100644 (file)
@@ -850,24 +850,25 @@ void __init mem_init(void)
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
-               bool want_memblock)
+int arch_add_memory(int nid, u64 start, u64 size,
+                       struct mhp_restrictions *restrictions)
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
 
-       return __add_pages(nid, start_pfn, nr_pages, altmap, want_memblock);
+       return __add_pages(nid, start_pfn, nr_pages, restrictions);
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-int arch_remove_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap)
+void arch_remove_memory(int nid, u64 start, u64 size,
+                       struct vmem_altmap *altmap)
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
        struct zone *zone;
 
        zone = page_zone(pfn_to_page(start_pfn));
-       return __remove_pages(zone, start_pfn, nr_pages, altmap);
+       __remove_pages(zone, start_pfn, nr_pages, altmap);
 }
 #endif
 #endif
index bccff68..62fc457 100644 (file)
 
 #include "ident_map.c"
 
+#define DEFINE_POPULATE(fname, type1, type2, init)             \
+static inline void fname##_init(struct mm_struct *mm,          \
+               type1##_t *arg1, type2##_t *arg2, bool init)    \
+{                                                              \
+       if (init)                                               \
+               fname##_safe(mm, arg1, arg2);                   \
+       else                                                    \
+               fname(mm, arg1, arg2);                          \
+}
+
+DEFINE_POPULATE(p4d_populate, p4d, pud, init)
+DEFINE_POPULATE(pgd_populate, pgd, p4d, init)
+DEFINE_POPULATE(pud_populate, pud, pmd, init)
+DEFINE_POPULATE(pmd_populate_kernel, pmd, pte, init)
+
+#define DEFINE_ENTRY(type1, type2, init)                       \
+static inline void set_##type1##_init(type1##_t *arg1,         \
+                       type2##_t arg2, bool init)              \
+{                                                              \
+       if (init)                                               \
+               set_##type1##_safe(arg1, arg2);                 \
+       else                                                    \
+               set_##type1(arg1, arg2);                        \
+}
+
+DEFINE_ENTRY(p4d, p4d, init)
+DEFINE_ENTRY(pud, pud, init)
+DEFINE_ENTRY(pmd, pmd, init)
+DEFINE_ENTRY(pte, pte, init)
+
+
 /*
  * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
  * physical space so we can cache the place of the first one and move
@@ -414,7 +445,7 @@ void __init cleanup_highmap(void)
  */
 static unsigned long __meminit
 phys_pte_init(pte_t *pte_page, unsigned long paddr, unsigned long paddr_end,
-             pgprot_t prot)
+             pgprot_t prot, bool init)
 {
        unsigned long pages = 0, paddr_next;
        unsigned long paddr_last = paddr_end;
@@ -432,7 +463,7 @@ phys_pte_init(pte_t *pte_page, unsigned long paddr, unsigned long paddr_end,
                                             E820_TYPE_RAM) &&
                            !e820__mapped_any(paddr & PAGE_MASK, paddr_next,
                                             E820_TYPE_RESERVED_KERN))
-                               set_pte_safe(pte, __pte(0));
+                               set_pte_init(pte, __pte(0), init);
                        continue;
                }
 
@@ -452,7 +483,7 @@ phys_pte_init(pte_t *pte_page, unsigned long paddr, unsigned long paddr_end,
                        pr_info("   pte=%p addr=%lx pte=%016lx\n", pte, paddr,
                                pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL).pte);
                pages++;
-               set_pte_safe(pte, pfn_pte(paddr >> PAGE_SHIFT, prot));
+               set_pte_init(pte, pfn_pte(paddr >> PAGE_SHIFT, prot), init);
                paddr_last = (paddr & PAGE_MASK) + PAGE_SIZE;
        }
 
@@ -468,7 +499,7 @@ phys_pte_init(pte_t *pte_page, unsigned long paddr, unsigned long paddr_end,
  */
 static unsigned long __meminit
 phys_pmd_init(pmd_t *pmd_page, unsigned long paddr, unsigned long paddr_end,
-             unsigned long page_size_mask, pgprot_t prot)
+             unsigned long page_size_mask, pgprot_t prot, bool init)
 {
        unsigned long pages = 0, paddr_next;
        unsigned long paddr_last = paddr_end;
@@ -487,7 +518,7 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long paddr, unsigned long paddr_end,
                                             E820_TYPE_RAM) &&
                            !e820__mapped_any(paddr & PMD_MASK, paddr_next,
                                             E820_TYPE_RESERVED_KERN))
-                               set_pmd_safe(pmd, __pmd(0));
+                               set_pmd_init(pmd, __pmd(0), init);
                        continue;
                }
 
@@ -496,7 +527,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long paddr, unsigned long paddr_end,
                                spin_lock(&init_mm.page_table_lock);
                                pte = (pte_t *)pmd_page_vaddr(*pmd);
                                paddr_last = phys_pte_init(pte, paddr,
-                                                          paddr_end, prot);
+                                                          paddr_end, prot,
+                                                          init);
                                spin_unlock(&init_mm.page_table_lock);
                                continue;
                        }
@@ -524,19 +556,20 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long paddr, unsigned long paddr_end,
                if (page_size_mask & (1<<PG_LEVEL_2M)) {
                        pages++;
                        spin_lock(&init_mm.page_table_lock);
-                       set_pte_safe((pte_t *)pmd,
-                               pfn_pte((paddr & PMD_MASK) >> PAGE_SHIFT,
-                                       __pgprot(pgprot_val(prot) | _PAGE_PSE)));
+                       set_pte_init((pte_t *)pmd,
+                                    pfn_pte((paddr & PMD_MASK) >> PAGE_SHIFT,
+                                            __pgprot(pgprot_val(prot) | _PAGE_PSE)),
+                                    init);
                        spin_unlock(&init_mm.page_table_lock);
                        paddr_last = paddr_next;
                        continue;
                }
 
                pte = alloc_low_page();
-               paddr_last = phys_pte_init(pte, paddr, paddr_end, new_prot);
+               paddr_last = phys_pte_init(pte, paddr, paddr_end, new_prot, init);
 
                spin_lock(&init_mm.page_table_lock);
-               pmd_populate_kernel_safe(&init_mm, pmd, pte);
+               pmd_populate_kernel_init(&init_mm, pmd, pte, init);
                spin_unlock(&init_mm.page_table_lock);
        }
        update_page_count(PG_LEVEL_2M, pages);
@@ -551,7 +584,7 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long paddr, unsigned long paddr_end,
  */
 static unsigned long __meminit
 phys_pud_init(pud_t *pud_page, unsigned long paddr, unsigned long paddr_end,
-             unsigned long page_size_mask)
+             unsigned long page_size_mask, bool init)
 {
        unsigned long pages = 0, paddr_next;
        unsigned long paddr_last = paddr_end;
@@ -573,7 +606,7 @@ phys_pud_init(pud_t *pud_page, unsigned long paddr, unsigned long paddr_end,
                                             E820_TYPE_RAM) &&
                            !e820__mapped_any(paddr & PUD_MASK, paddr_next,
                                             E820_TYPE_RESERVED_KERN))
-                               set_pud_safe(pud, __pud(0));
+                               set_pud_init(pud, __pud(0), init);
                        continue;
                }
 
@@ -583,7 +616,7 @@ phys_pud_init(pud_t *pud_page, unsigned long paddr, unsigned long paddr_end,
                                paddr_last = phys_pmd_init(pmd, paddr,
                                                           paddr_end,
                                                           page_size_mask,
-                                                          prot);
+                                                          prot, init);
                                continue;
                        }
                        /*
@@ -610,9 +643,10 @@ phys_pud_init(pud_t *pud_page, unsigned long paddr, unsigned long paddr_end,
                if (page_size_mask & (1<<PG_LEVEL_1G)) {
                        pages++;
                        spin_lock(&init_mm.page_table_lock);
-                       set_pte_safe((pte_t *)pud,
-                               pfn_pte((paddr & PUD_MASK) >> PAGE_SHIFT,
-                                       PAGE_KERNEL_LARGE));
+                       set_pte_init((pte_t *)pud,
+                                    pfn_pte((paddr & PUD_MASK) >> PAGE_SHIFT,
+                                            PAGE_KERNEL_LARGE),
+                                    init);
                        spin_unlock(&init_mm.page_table_lock);
                        paddr_last = paddr_next;
                        continue;
@@ -620,10 +654,10 @@ phys_pud_init(pud_t *pud_page, unsigned long paddr, unsigned long paddr_end,
 
                pmd = alloc_low_page();
                paddr_last = phys_pmd_init(pmd, paddr, paddr_end,
-                                          page_size_mask, prot);
+                                          page_size_mask, prot, init);
 
                spin_lock(&init_mm.page_table_lock);
-               pud_populate_safe(&init_mm, pud, pmd);
+               pud_populate_init(&init_mm, pud, pmd, init);
                spin_unlock(&init_mm.page_table_lock);
        }
 
@@ -634,14 +668,15 @@ phys_pud_init(pud_t *pud_page, unsigned long paddr, unsigned long paddr_end,
 
 static unsigned long __meminit
 phys_p4d_init(p4d_t *p4d_page, unsigned long paddr, unsigned long paddr_end,
-             unsigned long page_size_mask)
+             unsigned long page_size_mask, bool init)
 {
        unsigned long paddr_next, paddr_last = paddr_end;
        unsigned long vaddr = (unsigned long)__va(paddr);
        int i = p4d_index(vaddr);
 
        if (!pgtable_l5_enabled())
-               return phys_pud_init((pud_t *) p4d_page, paddr, paddr_end, page_size_mask);
+               return phys_pud_init((pud_t *) p4d_page, paddr, paddr_end,
+                                    page_size_mask, init);
 
        for (; i < PTRS_PER_P4D; i++, paddr = paddr_next) {
                p4d_t *p4d;
@@ -657,39 +692,34 @@ phys_p4d_init(p4d_t *p4d_page, unsigned long paddr, unsigned long paddr_end,
                                             E820_TYPE_RAM) &&
                            !e820__mapped_any(paddr & P4D_MASK, paddr_next,
                                             E820_TYPE_RESERVED_KERN))
-                               set_p4d_safe(p4d, __p4d(0));
+                               set_p4d_init(p4d, __p4d(0), init);
                        continue;
                }
 
                if (!p4d_none(*p4d)) {
                        pud = pud_offset(p4d, 0);
-                       paddr_last = phys_pud_init(pud, paddr,
-                                       paddr_end,
-                                       page_size_mask);
+                       paddr_last = phys_pud_init(pud, paddr, paddr_end,
+                                                  page_size_mask, init);
                        continue;
                }
 
                pud = alloc_low_page();
                paddr_last = phys_pud_init(pud, paddr, paddr_end,
-                                          page_size_mask);
+                                          page_size_mask, init);
 
                spin_lock(&init_mm.page_table_lock);
-               p4d_populate_safe(&init_mm, p4d, pud);
+               p4d_populate_init(&init_mm, p4d, pud, init);
                spin_unlock(&init_mm.page_table_lock);
        }
 
        return paddr_last;
 }
 
-/*
- * Create page table mapping for the physical memory for specific physical
- * addresses. The virtual and physical addresses have to be aligned on PMD level
- * down. It returns the last physical address mapped.
- */
-unsigned long __meminit
-kernel_physical_mapping_init(unsigned long paddr_start,
-                            unsigned long paddr_end,
-                            unsigned long page_size_mask)
+static unsigned long __meminit
+__kernel_physical_mapping_init(unsigned long paddr_start,
+                              unsigned long paddr_end,
+                              unsigned long page_size_mask,
+                              bool init)
 {
        bool pgd_changed = false;
        unsigned long vaddr, vaddr_start, vaddr_end, vaddr_next, paddr_last;
@@ -709,19 +739,22 @@ kernel_physical_mapping_init(unsigned long paddr_start,
                        p4d = (p4d_t *)pgd_page_vaddr(*pgd);
                        paddr_last = phys_p4d_init(p4d, __pa(vaddr),
                                                   __pa(vaddr_end),
-                                                  page_size_mask);
+                                                  page_size_mask,
+                                                  init);
                        continue;
                }
 
                p4d = alloc_low_page();
                paddr_last = phys_p4d_init(p4d, __pa(vaddr), __pa(vaddr_end),
-                                          page_size_mask);
+                                          page_size_mask, init);
 
                spin_lock(&init_mm.page_table_lock);
                if (pgtable_l5_enabled())
-                       pgd_populate_safe(&init_mm, pgd, p4d);
+                       pgd_populate_init(&init_mm, pgd, p4d, init);
                else
-                       p4d_populate_safe(&init_mm, p4d_offset(pgd, vaddr), (pud_t *) p4d);
+                       p4d_populate_init(&init_mm, p4d_offset(pgd, vaddr),
+                                         (pud_t *) p4d, init);
+
                spin_unlock(&init_mm.page_table_lock);
                pgd_changed = true;
        }
@@ -732,6 +765,37 @@ kernel_physical_mapping_init(unsigned long paddr_start,
        return paddr_last;
 }
 
+
+/*
+ * Create page table mapping for the physical memory for specific physical
+ * addresses. Note that it can only be used to populate non-present entries.
+ * The virtual and physical addresses have to be aligned on PMD level
+ * down. It returns the last physical address mapped.
+ */
+unsigned long __meminit
+kernel_physical_mapping_init(unsigned long paddr_start,
+                            unsigned long paddr_end,
+                            unsigned long page_size_mask)
+{
+       return __kernel_physical_mapping_init(paddr_start, paddr_end,
+                                             page_size_mask, true);
+}
+
+/*
+ * This function is similar to kernel_physical_mapping_init() above with the
+ * exception that it uses set_{pud,pmd}() instead of the set_{pud,pte}_safe()
+ * when updating the mapping. The caller is responsible to flush the TLBs after
+ * the function returns.
+ */
+unsigned long __meminit
+kernel_physical_mapping_change(unsigned long paddr_start,
+                              unsigned long paddr_end,
+                              unsigned long page_size_mask)
+{
+       return __kernel_physical_mapping_init(paddr_start, paddr_end,
+                                             page_size_mask, false);
+}
+
 #ifndef CONFIG_NUMA
 void __init initmem_init(void)
 {
@@ -777,11 +841,11 @@ static void update_end_of_memory_vars(u64 start, u64 size)
 }
 
 int add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
-               struct vmem_altmap *altmap, bool want_memblock)
+                               struct mhp_restrictions *restrictions)
 {
        int ret;
 
-       ret = __add_pages(nid, start_pfn, nr_pages, altmap, want_memblock);
+       ret = __add_pages(nid, start_pfn, nr_pages, restrictions);
        WARN_ON_ONCE(ret);
 
        /* update max_pfn, max_low_pfn and high_memory */
@@ -791,15 +855,15 @@ int add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
        return ret;
 }
 
-int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
-               bool want_memblock)
+int arch_add_memory(int nid, u64 start, u64 size,
+                       struct mhp_restrictions *restrictions)
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
 
        init_memory_mapping(start, start + size);
 
-       return add_pages(nid, start_pfn, nr_pages, altmap, want_memblock);
+       return add_pages(nid, start_pfn, nr_pages, restrictions);
 }
 
 #define PAGE_INUSE 0xFD
@@ -1141,24 +1205,20 @@ kernel_physical_mapping_remove(unsigned long start, unsigned long end)
        remove_pagetable(start, end, true, NULL);
 }
 
-int __ref arch_remove_memory(int nid, u64 start, u64 size,
-                               struct vmem_altmap *altmap)
+void __ref arch_remove_memory(int nid, u64 start, u64 size,
+                             struct vmem_altmap *altmap)
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
        struct page *page = pfn_to_page(start_pfn);
        struct zone *zone;
-       int ret;
 
        /* With altmap the first mapped page is offset from @start */
        if (altmap)
                page += vmem_altmap_offset(altmap);
        zone = page_zone(page);
-       ret = __remove_pages(zone, start_pfn, nr_pages, altmap);
-       WARN_ON_ONCE(ret);
+       __remove_pages(zone, start_pfn, nr_pages, altmap);
        kernel_physical_mapping_remove(start, start + size);
-
-       return ret;
 }
 #endif
 #endif /* CONFIG_MEMORY_HOTPLUG */
index 385afa2..51f50a7 100644 (file)
@@ -301,9 +301,13 @@ static int __init early_set_memory_enc_dec(unsigned long vaddr,
                else
                        split_page_size_mask = 1 << PG_LEVEL_2M;
 
-               kernel_physical_mapping_init(__pa(vaddr & pmask),
-                                            __pa((vaddr_end & pmask) + psize),
-                                            split_page_size_mask);
+               /*
+                * kernel_physical_mapping_change() does not flush the TLBs, so
+                * a TLB flush is required after we exit from the for loop.
+                */
+               kernel_physical_mapping_change(__pa(vaddr & pmask),
+                                              __pa((vaddr_end & pmask) + psize),
+                                              split_page_size_mask);
        }
 
        ret = 0;
index 319bde3..eeae142 100644 (file)
@@ -13,6 +13,9 @@ void early_ioremap_page_table_range_init(void);
 unsigned long kernel_physical_mapping_init(unsigned long start,
                                             unsigned long end,
                                             unsigned long page_size_mask);
+unsigned long kernel_physical_mapping_change(unsigned long start,
+                                            unsigned long end,
+                                            unsigned long page_size_mask);
 void zone_sizes_init(void);
 
 extern int after_bootmem;
index 52e5510..d3a73f9 100644 (file)
@@ -1119,6 +1119,8 @@ static const struct dmi_system_id pciirq_dmi_table[] __initconst = {
 
 void __init pcibios_irq_init(void)
 {
+       struct irq_routing_table *rtable = NULL;
+
        DBG(KERN_DEBUG "PCI: IRQ init\n");
 
        if (raw_pci_ops == NULL)
@@ -1129,8 +1131,10 @@ void __init pcibios_irq_init(void)
        pirq_table = pirq_find_routing_table();
 
 #ifdef CONFIG_PCI_BIOS
-       if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN))
+       if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN)) {
                pirq_table = pcibios_get_irq_routing_table();
+               rtable = pirq_table;
+       }
 #endif
        if (pirq_table) {
                pirq_peer_trick();
@@ -1145,8 +1149,10 @@ void __init pcibios_irq_init(void)
                 * If we're using the I/O APIC, avoid using the PCI IRQ
                 * routing table
                 */
-               if (io_apic_assign_pci_irqs)
+               if (io_apic_assign_pci_irqs) {
+                       kfree(rtable);
                        pirq_table = NULL;
+               }
        }
 
        x86_init.pci.fixup_irqs();
index ac9e7bf..0296c5b 100644 (file)
@@ -220,10 +220,26 @@ static u32 __init olpc_dt_get_board_revision(void)
        return be32_to_cpu(rev);
 }
 
+int olpc_dt_compatible_match(phandle node, const char *compat)
+{
+       char buf[64], *p;
+       int plen, len;
+
+       plen = olpc_dt_getproperty(node, "compatible", buf, sizeof(buf));
+       if (plen <= 0)
+               return 0;
+
+       len = strlen(compat);
+       for (p = buf; p < buf + plen; p += strlen(p) + 1) {
+               if (strcmp(p, compat) == 0)
+                       return 1;
+       }
+
+       return 0;
+}
+
 void __init olpc_dt_fixup(void)
 {
-       int r;
-       char buf[64];
        phandle node;
        u32 board_rev;
 
@@ -231,41 +247,66 @@ void __init olpc_dt_fixup(void)
        if (!node)
                return;
 
-       /*
-        * If the battery node has a compatible property, we are running a new
-        * enough firmware and don't have fixups to make.
-        */
-       r = olpc_dt_getproperty(node, "compatible", buf, sizeof(buf));
-       if (r > 0)
-               return;
-
-       pr_info("PROM DT: Old firmware detected, applying fixes\n");
-
-       /* Add olpc,xo1-battery compatible marker to battery node */
-       olpc_dt_interpret("\" /battery@0\" find-device"
-               " \" olpc,xo1-battery\" +compatible"
-               " device-end");
-
        board_rev = olpc_dt_get_board_revision();
        if (!board_rev)
                return;
 
        if (board_rev >= olpc_board_pre(0xd0)) {
-               /* XO-1.5: add dcon device */
-               olpc_dt_interpret("\" /pci/display@1\" find-device"
-                       " new-device"
-                       " \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
-                       " finish-device device-end");
+               /* XO-1.5 */
+
+               if (olpc_dt_compatible_match(node, "olpc,xo1.5-battery"))
+                       return;
+
+               /* Add olpc,xo1.5-battery compatible marker to battery node */
+               olpc_dt_interpret("\" /battery@0\" find-device");
+               olpc_dt_interpret("  \" olpc,xo1.5-battery\" +compatible");
+               olpc_dt_interpret("device-end");
+
+               if (olpc_dt_compatible_match(node, "olpc,xo1-battery")) {
+                       /*
+                        * If we have a olpc,xo1-battery compatible, then we're
+                        * running a new enough firmware that already has
+                        * the dcon node.
+                        */
+                       return;
+               }
+
+               /* Add dcon device */
+               olpc_dt_interpret("\" /pci/display@1\" find-device");
+               olpc_dt_interpret("  new-device");
+               olpc_dt_interpret("    \" dcon\" device-name");
+               olpc_dt_interpret("    \" olpc,xo1-dcon\" +compatible");
+               olpc_dt_interpret("  finish-device");
+               olpc_dt_interpret("device-end");
        } else {
-               /* XO-1: add dcon device, mark RTC as olpc,xo1-rtc */
-               olpc_dt_interpret("\" /pci/display@1,1\" find-device"
-                       " new-device"
-                       " \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
-                       " finish-device device-end"
-                       " \" /rtc\" find-device"
-                       " \" olpc,xo1-rtc\" +compatible"
-                       " device-end");
+               /* XO-1 */
+
+               if (olpc_dt_compatible_match(node, "olpc,xo1-battery")) {
+                       /*
+                        * If we have a olpc,xo1-battery compatible, then we're
+                        * running a new enough firmware that already has
+                        * the dcon and RTC nodes.
+                        */
+                       return;
+               }
+
+               /* Add dcon device, mark RTC as olpc,xo1-rtc */
+               olpc_dt_interpret("\" /pci/display@1,1\" find-device");
+               olpc_dt_interpret("  new-device");
+               olpc_dt_interpret("    \" dcon\" device-name");
+               olpc_dt_interpret("    \" olpc,xo1-dcon\" +compatible");
+               olpc_dt_interpret("  finish-device");
+               olpc_dt_interpret("device-end");
+
+               olpc_dt_interpret("\" /rtc\" find-device");
+               olpc_dt_interpret(" \" olpc,xo1-rtc\" +compatible");
+               olpc_dt_interpret("device-end");
        }
+
+       /* Add olpc,xo1-battery compatible marker to battery node */
+       olpc_dt_interpret("\" /battery@0\" find-device");
+       olpc_dt_interpret("  \" olpc,xo1-battery\" +compatible");
+       olpc_dt_interpret("device-end");
 }
 
 void __init olpc_dt_build_devicetree(void)
index 62f5c70..1861a2b 100644 (file)
@@ -44,8 +44,6 @@ void __init __weak mem_map_via_hcall(struct boot_params *ptr __maybe_unused)
 
 static void __init init_pvh_bootparams(bool xen_guest)
 {
-       memset(&pvh_bootparams, 0, sizeof(pvh_bootparams));
-
        if ((pvh_start_info.version > 0) && (pvh_start_info.memmap_entries)) {
                struct hvm_memmap_table_entry *ep;
                int i;
@@ -103,7 +101,7 @@ static void __init init_pvh_bootparams(bool xen_guest)
  * If we are trying to boot a Xen PVH guest, it is expected that the kernel
  * will have been configured to provide the required override for this routine.
  */
-void __init __weak xen_pvh_init(void)
+void __init __weak xen_pvh_init(struct boot_params *boot_params)
 {
        xen_raw_printk("Error: Missing xen PVH initialization\n");
        BUG();
@@ -112,7 +110,7 @@ void __init __weak xen_pvh_init(void)
 static void hypervisor_specific_init(bool xen_guest)
 {
        if (xen_guest)
-               xen_pvh_init();
+               xen_pvh_init(&pvh_bootparams);
 }
 
 /*
@@ -131,6 +129,8 @@ void __init xen_prepare_pvh(void)
                BUG();
        }
 
+       memset(&pvh_bootparams, 0, sizeof(pvh_bootparams));
+
        hypervisor_specific_init(xen_guest);
 
        init_pvh_bootparams(xen_guest);
index 1fbb629..0d3365c 100644 (file)
@@ -158,7 +158,7 @@ static enum efi_secureboot_mode xen_efi_get_secureboot(void)
        return efi_secureboot_mode_unknown;
 }
 
-void __init xen_efi_init(void)
+void __init xen_efi_init(struct boot_params *boot_params)
 {
        efi_system_table_t *efi_systab_xen;
 
@@ -167,12 +167,12 @@ void __init xen_efi_init(void)
        if (efi_systab_xen == NULL)
                return;
 
-       strncpy((char *)&boot_params.efi_info.efi_loader_signature, "Xen",
-                       sizeof(boot_params.efi_info.efi_loader_signature));
-       boot_params.efi_info.efi_systab = (__u32)__pa(efi_systab_xen);
-       boot_params.efi_info.efi_systab_hi = (__u32)(__pa(efi_systab_xen) >> 32);
+       strncpy((char *)&boot_params->efi_info.efi_loader_signature, "Xen",
+                       sizeof(boot_params->efi_info.efi_loader_signature));
+       boot_params->efi_info.efi_systab = (__u32)__pa(efi_systab_xen);
+       boot_params->efi_info.efi_systab_hi = (__u32)(__pa(efi_systab_xen) >> 32);
 
-       boot_params.secure_boot = xen_efi_get_secureboot();
+       boot_params->secure_boot = xen_efi_get_secureboot();
 
        set_bit(EFI_BOOT, &efi.flags);
        set_bit(EFI_PARAVIRT, &efi.flags);
index c54a493..4722ba2 100644 (file)
@@ -1403,7 +1403,7 @@ asmlinkage __visible void __init xen_start_kernel(void)
        /* We need this for printk timestamps */
        xen_setup_runstate_info(0);
 
-       xen_efi_init();
+       xen_efi_init(&boot_params);
 
        /* Start the world */
 #ifdef CONFIG_X86_32
index 35b7599..80a79db 100644 (file)
@@ -13,6 +13,8 @@
 
 #include <xen/interface/memory.h>
 
+#include "xen-ops.h"
+
 /*
  * PVH variables.
  *
  */
 bool xen_pvh __attribute__((section(".data"))) = 0;
 
-void __init xen_pvh_init(void)
+void __init xen_pvh_init(struct boot_params *boot_params)
 {
        u32 msr;
        u64 pfn;
 
        xen_pvh = 1;
+       xen_domain_type = XEN_HVM_DOMAIN;
        xen_start_flags = pvh_start_info.flags;
 
        msr = cpuid_ebx(xen_cpuid_base() + 2);
        pfn = __pa(hypercall_page);
        wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
+
+       xen_efi_init(boot_params);
 }
 
 void __init mem_map_via_hcall(struct boot_params *boot_params_p)
index 6e29794..befbdd8 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "xen-ops.h"
 
-/* Xen may fire a timer up to this many ns early */
+/* Minimum amount of time until next clock event fires */
 #define TIMER_SLOP     100000
 
 static u64 xen_sched_clock_offset __read_mostly;
@@ -212,7 +212,7 @@ static int xen_timerop_set_next_event(unsigned long delta,
        return 0;
 }
 
-static const struct clock_event_device xen_timerop_clockevent = {
+static struct clock_event_device xen_timerop_clockevent __ro_after_init = {
        .name                   = "xen",
        .features               = CLOCK_EVT_FEAT_ONESHOT,
 
@@ -273,7 +273,7 @@ static int xen_vcpuop_set_next_event(unsigned long delta,
        return ret;
 }
 
-static const struct clock_event_device xen_vcpuop_clockevent = {
+static struct clock_event_device xen_vcpuop_clockevent __ro_after_init = {
        .name = "xen",
        .features = CLOCK_EVT_FEAT_ONESHOT,
 
@@ -570,3 +570,17 @@ void __init xen_hvm_init_time_ops(void)
        x86_platform.set_wallclock = xen_set_wallclock;
 }
 #endif
+
+/* Kernel parameter to specify Xen timer slop */
+static int __init parse_xen_timer_slop(char *ptr)
+{
+       unsigned long slop = memparse(ptr, NULL);
+
+       xen_timerop_clockevent.min_delta_ns = slop;
+       xen_timerop_clockevent.min_delta_ticks = slop;
+       xen_vcpuop_clockevent.min_delta_ns = slop;
+       xen_vcpuop_clockevent.min_delta_ticks = slop;
+
+       return 0;
+}
+early_param("xen_timer_slop", parse_xen_timer_slop);
index 0e60bd9..2f111f4 100644 (file)
@@ -122,9 +122,9 @@ static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
 void __init xen_init_apic(void);
 
 #ifdef CONFIG_XEN_EFI
-extern void xen_efi_init(void);
+extern void xen_efi_init(struct boot_params *boot_params);
 #else
-static inline void __init xen_efi_init(void)
+static inline void __init xen_efi_init(struct boot_params *boot_params)
 {
 }
 #endif
index 9b5e852..1289068 100644 (file)
@@ -27,7 +27,7 @@ static inline unsigned long arch_local_irq_save(void)
 {
        unsigned long flags;
 #if XTENSA_FAKE_NMI
-#if defined(CONFIG_DEBUG_KERNEL) && (LOCKLEVEL | TOPLEVEL) >= XCHAL_DEBUGLEVEL
+#if defined(CONFIG_DEBUG_MISC) && (LOCKLEVEL | TOPLEVEL) >= XCHAL_DEBUGLEVEL
        unsigned long tmp;
 
        asm volatile("rsr       %0, ps\t\n"
diff --git a/arch/xtensa/include/asm/segment.h b/arch/xtensa/include/asm/segment.h
deleted file mode 100644 (file)
index 98964ad..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/segment.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SEGMENT_H
-#define _XTENSA_SEGMENT_H
-
-#include <linux/uaccess.h>
-
-#endif /* _XTENSA_SEGEMENT_H */
index 3699d6d..83b244c 100644 (file)
@@ -126,7 +126,7 @@ void secondary_start_kernel(void)
 
        init_mmu();
 
-#ifdef CONFIG_DEBUG_KERNEL
+#ifdef CONFIG_DEBUG_MISC
        if (boot_secondary_processors == 0) {
                pr_debug("%s: boot_secondary_processors:%d; Hanging cpu:%d\n",
                        __func__, boot_secondary_processors, cpu);
index d498610..b51746f 100644 (file)
@@ -216,11 +216,6 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 }
 #endif
 
-void free_initmem(void)
-{
-       free_initmem_default(-1);
-}
-
 static void __init parse_memmap_one(char *p)
 {
        char *oldp;
index 820e873..b150637 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/errno.h>
 #include <linux/reboot.h>
 #include <linux/kdev_t.h>
index 4253667..4db6208 100644 (file)
@@ -43,8 +43,7 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
        unsigned inline_vecs;
 
        if (!bs || !mempool_initialized(&bs->bio_integrity_pool)) {
-               bip = kmalloc(sizeof(struct bio_integrity_payload) +
-                             sizeof(struct bio_vec) * nr_vecs, gfp_mask);
+               bip = kmalloc(struct_size(bip, bip_inline_vecs, nr_vecs), gfp_mask);
                inline_vecs = nr_vecs;
        } else {
                bip = mempool_alloc(&bs->bio_integrity_pool, gfp_mask);
index ddf598a..c16f946 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/clkdev.h>
 #include <linux/acpi.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/pm.h>
 
 #include "internal.h"
index 8940054..78c2653 100644 (file)
@@ -428,8 +428,10 @@ static ssize_t acpi_device_adr_show(struct device *dev,
 {
        struct acpi_device *acpi_dev = to_acpi_device(dev);
 
-       return sprintf(buf, "0x%08x\n",
-                      (unsigned int)(acpi_dev->pnp.bus_address));
+       if (acpi_dev->pnp.bus_address > U32_MAX)
+               return sprintf(buf, "0x%016llx\n", acpi_dev->pnp.bus_address);
+       else
+               return sprintf(buf, "0x%08llx\n", acpi_dev->pnp.bus_address);
 }
 static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);
 
index a4e8432..b42be06 100644 (file)
@@ -52,6 +52,18 @@ struct mcfg_fixup {
 static struct mcfg_fixup mcfg_quirks[] = {
 /*     { OEM_ID, OEM_TABLE_ID, REV, SEGMENT, BUS_RANGE, ops, cfgres }, */
 
+#define AL_ECAM(table_id, rev, seg, ops) \
+       { "AMAZON", table_id, rev, seg, MCFG_BUS_ANY, ops }
+
+       AL_ECAM("GRAVITON", 0, 0, &al_pcie_ops),
+       AL_ECAM("GRAVITON", 0, 1, &al_pcie_ops),
+       AL_ECAM("GRAVITON", 0, 2, &al_pcie_ops),
+       AL_ECAM("GRAVITON", 0, 3, &al_pcie_ops),
+       AL_ECAM("GRAVITON", 0, 4, &al_pcie_ops),
+       AL_ECAM("GRAVITON", 0, 5, &al_pcie_ops),
+       AL_ECAM("GRAVITON", 0, 6, &al_pcie_ops),
+       AL_ECAM("GRAVITON", 0, 7, &al_pcie_ops),
+
 #define QCOM_ECAM32(seg) \
        { "QCOM  ", "QDF2432 ", 1, seg, MCFG_BUS_ANY, &pci_32b_ops }
 
index 707aafc..c36781a 100644 (file)
@@ -145,6 +145,7 @@ static struct pci_osc_bit_struct pci_osc_support_bit[] = {
        { OSC_PCI_CLOCK_PM_SUPPORT, "ClockPM" },
        { OSC_PCI_SEGMENT_GROUPS_SUPPORT, "Segments" },
        { OSC_PCI_MSI_SUPPORT, "MSI" },
+       { OSC_PCI_HPX_TYPE_3_SUPPORT, "HPX-Type3" },
 };
 
 static struct pci_osc_bit_struct pci_osc_control_bit[] = {
@@ -446,6 +447,7 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm,
         * PCI domains, so we indicate this in _OSC support capabilities.
         */
        support = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
+       support |= OSC_PCI_HPX_TYPE_3_SUPPORT;
        if (pci_ext_cfg_avail())
                support |= OSC_PCI_EXT_CONFIG_SUPPORT;
        if (pcie_aspm_support_enabled())
index 403c4ff..e52f123 100644 (file)
@@ -977,6 +977,8 @@ static int acpi_s2idle_prepare(void)
        if (acpi_sci_irq_valid())
                enable_irq_wake(acpi_sci_irq);
 
+       acpi_enable_wakeup_devices(ACPI_STATE_S0);
+
        /* Change the configuration of GPEs to avoid spurious wakeup. */
        acpi_enable_all_wakeup_gpes();
        acpi_os_wait_events_complete();
@@ -1027,6 +1029,8 @@ static void acpi_s2idle_restore(void)
 {
        acpi_enable_all_runtime_gpes();
 
+       acpi_disable_wakeup_devices(ACPI_STATE_S0);
+
        if (acpi_sci_irq_valid())
                disable_irq_wake(acpi_sci_irq);
 
index cc6d06c..db271b7 100644 (file)
@@ -44,7 +44,7 @@
 #include <linux/ktime.h>
 
 #include <linux/platform_data/dma-ep93xx.h>
-#include <mach/platform.h>
+#include <linux/soc/cirrus/ep93xx.h>
 
 #define DRV_NAME       "ep93xx-ide"
 #define DRV_VERSION    "1.0"
index 59b2317..3495e17 100644 (file)
@@ -909,7 +909,6 @@ static int sata_rcar_probe(struct platform_device *pdev)
 
        host = ata_host_alloc(dev, 1);
        if (!host) {
-               dev_err(dev, "ata_host_alloc failed\n");
                ret = -ENOMEM;
                goto err_pm_put;
        }
index 668139c..cc37511 100644 (file)
@@ -548,11 +548,18 @@ ssize_t __weak cpu_show_l1tf(struct device *dev,
        return sprintf(buf, "Not affected\n");
 }
 
+ssize_t __weak cpu_show_mds(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "Not affected\n");
+}
+
 static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
 static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
 static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
 static DEVICE_ATTR(spec_store_bypass, 0444, cpu_show_spec_store_bypass, NULL);
 static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL);
+static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL);
 
 static struct attribute *cpu_root_vulnerabilities_attrs[] = {
        &dev_attr_meltdown.attr,
@@ -560,6 +567,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
        &dev_attr_spectre_v2.attr,
        &dev_attr_spec_store_bypass.attr,
        &dev_attr_l1tf.attr,
+       &dev_attr_mds.attr,
        NULL
 };
 
index e49028a..f180427 100644 (file)
@@ -231,13 +231,14 @@ static bool pages_correctly_probed(unsigned long start_pfn)
  * OK to have direct references to sparsemem variables in here.
  */
 static int
-memory_block_action(unsigned long phys_index, unsigned long action, int online_type)
+memory_block_action(unsigned long start_section_nr, unsigned long action,
+                   int online_type)
 {
        unsigned long start_pfn;
        unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
        int ret;
 
-       start_pfn = section_nr_to_pfn(phys_index);
+       start_pfn = section_nr_to_pfn(start_section_nr);
 
        switch (action) {
        case MEM_ONLINE:
@@ -251,7 +252,7 @@ memory_block_action(unsigned long phys_index, unsigned long action, int online_t
                break;
        default:
                WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
-                    "%ld\n", __func__, phys_index, action, action);
+                    "%ld\n", __func__, start_section_nr, action, action);
                ret = -EINVAL;
        }
 
@@ -733,16 +734,18 @@ unregister_memory(struct memory_block *memory)
 {
        BUG_ON(memory->dev.bus != &memory_subsys);
 
-       /* drop the ref. we got in remove_memory_section() */
+       /* drop the ref. we got via find_memory_block() */
        put_device(&memory->dev);
        device_unregister(&memory->dev);
 }
 
-static int remove_memory_section(unsigned long node_id,
-                              struct mem_section *section, int phys_device)
+void unregister_memory_section(struct mem_section *section)
 {
        struct memory_block *mem;
 
+       if (WARN_ON_ONCE(!present_section(section)))
+               return;
+
        mutex_lock(&mem_sysfs_mutex);
 
        /*
@@ -763,15 +766,6 @@ static int remove_memory_section(unsigned long node_id,
 
 out_unlock:
        mutex_unlock(&mem_sysfs_mutex);
-       return 0;
-}
-
-int unregister_memory_section(struct mem_section *section)
-{
-       if (!present_section(section))
-               return -EINVAL;
-
-       return remove_memory_section(0, section, 0);
 }
 #endif /* CONFIG_MEMORY_HOTREMOVE */
 
index 7a6aa23..33c30c1 100644 (file)
@@ -128,6 +128,7 @@ static const struct genpd_lock_ops genpd_spin_ops = {
 #define genpd_is_always_on(genpd)      (genpd->flags & GENPD_FLAG_ALWAYS_ON)
 #define genpd_is_active_wakeup(genpd)  (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP)
 #define genpd_is_cpu_domain(genpd)     (genpd->flags & GENPD_FLAG_CPU_DOMAIN)
+#define genpd_is_rpm_always_on(genpd)  (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON)
 
 static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev,
                const struct generic_pm_domain *genpd)
@@ -515,7 +516,9 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
         * (1) The domain is configured as always on.
         * (2) When the domain has a subdomain being powered on.
         */
-       if (genpd_is_always_on(genpd) || atomic_read(&genpd->sd_count) > 0)
+       if (genpd_is_always_on(genpd) ||
+                       genpd_is_rpm_always_on(genpd) ||
+                       atomic_read(&genpd->sd_count) > 0)
                return -EBUSY;
 
        list_for_each_entry(pdd, &genpd->dev_list, list_node) {
@@ -1812,7 +1815,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
        }
 
        /* Always-on domains must be powered on at initialization. */
-       if (genpd_is_always_on(genpd) && !genpd_status_on(genpd))
+       if ((genpd_is_always_on(genpd) || genpd_is_rpm_always_on(genpd)) &&
+                       !genpd_status_on(genpd))
                return -EINVAL;
 
        if (genpd_is_cpu_domain(genpd) &&
index 17defbf..2da615b 100644 (file)
@@ -152,6 +152,12 @@ static void brd_free_pages(struct brd_device *brd)
 
                pos++;
 
+               /*
+                * It takes 3.4 seconds to remove 80GiB ramdisk.
+                * So, we need cond_resched to avoid stalling the CPU.
+                */
+               cond_resched();
+
                /*
                 * This assumes radix_tree_gang_lookup always returns as
                 * many pages as possible. If the radix-tree code changes,
index 2210c1b..e5009a3 100644 (file)
@@ -934,7 +934,7 @@ static struct rbd_client *rbd_get_client(struct ceph_options *ceph_opts)
        struct rbd_client *rbdc;
        int ret;
 
-       mutex_lock_nested(&client_mutex, SINGLE_DEPTH_NESTING);
+       mutex_lock(&client_mutex);
        rbdc = rbd_client_find(ceph_opts);
        if (rbdc) {
                ceph_destroy_options(ceph_opts);
@@ -1326,7 +1326,7 @@ static void rbd_obj_zero_range(struct rbd_obj_request *obj_req, u32 off,
                zero_bvecs(&obj_req->bvec_pos, off, bytes);
                break;
        default:
-               rbd_assert(0);
+               BUG();
        }
 }
 
@@ -1581,7 +1581,7 @@ static void rbd_obj_request_destroy(struct kref *kref)
                kfree(obj_request->bvec_pos.bvecs);
                break;
        default:
-               rbd_assert(0);
+               BUG();
        }
 
        kfree(obj_request->img_extents);
@@ -1781,7 +1781,7 @@ static void rbd_osd_req_setup_data(struct rbd_obj_request *obj_req, u32 which)
                                                    &obj_req->bvec_pos);
                break;
        default:
-               rbd_assert(0);
+               BUG();
        }
 }
 
@@ -2036,7 +2036,7 @@ static int __rbd_img_fill_request(struct rbd_img_request *img_req)
                        ret = rbd_obj_setup_zeroout(obj_req);
                        break;
                default:
-                       rbd_assert(0);
+                       BUG();
                }
                if (ret < 0)
                        return ret;
@@ -2383,7 +2383,7 @@ static int rbd_obj_read_from_parent(struct rbd_obj_request *obj_req)
                                                      &obj_req->bvec_pos);
                        break;
                default:
-                       rbd_assert(0);
+                       BUG();
                }
        } else {
                ret = rbd_img_fill_from_bvecs(child_img_req,
@@ -2515,7 +2515,7 @@ static int rbd_obj_issue_copyup_ops(struct rbd_obj_request *obj_req, u32 bytes)
                num_osd_ops += count_zeroout_ops(obj_req);
                break;
        default:
-               rbd_assert(0);
+               BUG();
        }
 
        obj_req->osd_req = rbd_osd_req_create(obj_req, num_osd_ops);
@@ -2542,7 +2542,7 @@ static int rbd_obj_issue_copyup_ops(struct rbd_obj_request *obj_req, u32 bytes)
                __rbd_obj_setup_zeroout(obj_req, which);
                break;
        default:
-               rbd_assert(0);
+               BUG();
        }
 
        ret = ceph_osdc_alloc_messages(obj_req->osd_req, GFP_NOIO);
@@ -3842,8 +3842,12 @@ static void rbd_queue_workfn(struct work_struct *work)
                goto err_rq;
        }
 
-       rbd_assert(op_type == OBJ_OP_READ ||
-                  rbd_dev->spec->snap_id == CEPH_NOSNAP);
+       if (op_type != OBJ_OP_READ && rbd_dev->spec->snap_id != CEPH_NOSNAP) {
+               rbd_warn(rbd_dev, "%s on read-only snapshot",
+                        obj_op_name(op_type));
+               result = -EIO;
+               goto err;
+       }
 
        /*
         * Quit early if the mapped snapshot no longer exists.  It's
index 084ae28..ac58142 100644 (file)
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
-#include <linux/pm_clock.h>
 #include <linux/pm_runtime.h>
 
+struct tegra_aconnect {
+       struct clk      *ape_clk;
+       struct clk      *apb2ape_clk;
+};
+
 static int tegra_aconnect_probe(struct platform_device *pdev)
 {
-       int ret;
+       struct tegra_aconnect *aconnect;
 
        if (!pdev->dev.of_node)
                return -EINVAL;
 
-       ret = pm_clk_create(&pdev->dev);
-       if (ret)
-               return ret;
+       aconnect = devm_kzalloc(&pdev->dev, sizeof(struct tegra_aconnect),
+                               GFP_KERNEL);
+       if (!aconnect)
+               return -ENOMEM;
 
-       ret = of_pm_clk_add_clk(&pdev->dev, "ape");
-       if (ret)
-               goto clk_destroy;
+       aconnect->ape_clk = devm_clk_get(&pdev->dev, "ape");
+       if (IS_ERR(aconnect->ape_clk)) {
+               dev_err(&pdev->dev, "Can't retrieve ape clock\n");
+               return PTR_ERR(aconnect->ape_clk);
+       }
 
-       ret = of_pm_clk_add_clk(&pdev->dev, "apb2ape");
-       if (ret)
-               goto clk_destroy;
+       aconnect->apb2ape_clk = devm_clk_get(&pdev->dev, "apb2ape");
+       if (IS_ERR(aconnect->apb2ape_clk)) {
+               dev_err(&pdev->dev, "Can't retrieve apb2ape clock\n");
+               return PTR_ERR(aconnect->apb2ape_clk);
+       }
 
+       dev_set_drvdata(&pdev->dev, aconnect);
        pm_runtime_enable(&pdev->dev);
 
        of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
@@ -41,35 +51,51 @@ static int tegra_aconnect_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "Tegra ACONNECT bus registered\n");
 
        return 0;
-
-clk_destroy:
-       pm_clk_destroy(&pdev->dev);
-
-       return ret;
 }
 
 static int tegra_aconnect_remove(struct platform_device *pdev)
 {
        pm_runtime_disable(&pdev->dev);
 
-       pm_clk_destroy(&pdev->dev);
-
        return 0;
 }
 
 static int tegra_aconnect_runtime_resume(struct device *dev)
 {
-       return pm_clk_resume(dev);
+       struct tegra_aconnect *aconnect = dev_get_drvdata(dev);
+       int ret;
+
+       ret = clk_prepare_enable(aconnect->ape_clk);
+       if (ret) {
+               dev_err(dev, "ape clk_enable failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = clk_prepare_enable(aconnect->apb2ape_clk);
+       if (ret) {
+               clk_disable_unprepare(aconnect->ape_clk);
+               dev_err(dev, "apb2ape clk_enable failed: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
 }
 
 static int tegra_aconnect_runtime_suspend(struct device *dev)
 {
-       return pm_clk_suspend(dev);
+       struct tegra_aconnect *aconnect = dev_get_drvdata(dev);
+
+       clk_disable_unprepare(aconnect->ape_clk);
+       clk_disable_unprepare(aconnect->apb2ape_clk);
+
+       return 0;
 }
 
 static const struct dev_pm_ops tegra_aconnect_pm_ops = {
        SET_RUNTIME_PM_OPS(tegra_aconnect_runtime_suspend,
                           tegra_aconnect_runtime_resume, NULL)
+       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+                                     pm_runtime_force_resume)
 };
 
 static const struct of_device_id tegra_aconnect_of_match[] = {
index d299ec7..308475e 100644 (file)
@@ -47,7 +47,10 @@ enum sysc_clocks {
        SYSC_MAX_CLOCKS,
 };
 
-static const char * const clock_names[SYSC_ICK + 1] = { "fck", "ick", };
+static const char * const clock_names[SYSC_MAX_CLOCKS] = {
+       "fck", "ick", "opt0", "opt1", "opt2", "opt3", "opt4",
+       "opt5", "opt6", "opt7",
+};
 
 #define SYSC_IDLEMODE_MASK             3
 #define SYSC_CLOCKACTIVITY_MASK                3
@@ -75,6 +78,7 @@ struct sysc {
        u32 module_size;
        void __iomem *module_va;
        int offsets[SYSC_MAX_REGS];
+       struct ti_sysc_module_data *mdata;
        struct clk **clocks;
        const char **clock_roles;
        int nr_clocks;
@@ -94,7 +98,7 @@ struct sysc {
 static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np,
                                  bool is_child);
 
-void sysc_write(struct sysc *ddata, int offset, u32 value)
+static void sysc_write(struct sysc *ddata, int offset, u32 value)
 {
        writel_relaxed(value, ddata->module_va + offset);
 }
@@ -128,6 +132,81 @@ static u32 sysc_read_revision(struct sysc *ddata)
        return sysc_read(ddata, offset);
 }
 
+static int sysc_add_named_clock_from_child(struct sysc *ddata,
+                                          const char *name,
+                                          const char *optfck_name)
+{
+       struct device_node *np = ddata->dev->of_node;
+       struct device_node *child;
+       struct clk_lookup *cl;
+       struct clk *clock;
+       const char *n;
+
+       if (name)
+               n = name;
+       else
+               n = optfck_name;
+
+       /* Does the clock alias already exist? */
+       clock = of_clk_get_by_name(np, n);
+       if (!IS_ERR(clock)) {
+               clk_put(clock);
+
+               return 0;
+       }
+
+       child = of_get_next_available_child(np, NULL);
+       if (!child)
+               return -ENODEV;
+
+       clock = devm_get_clk_from_child(ddata->dev, child, name);
+       if (IS_ERR(clock))
+               return PTR_ERR(clock);
+
+       /*
+        * Use clkdev_add() instead of clkdev_alloc() to avoid the MAX_DEV_ID
+        * limit for clk_get(). If cl ever needs to be freed, it should be done
+        * with clkdev_drop().
+        */
+       cl = kcalloc(1, sizeof(*cl), GFP_KERNEL);
+       if (!cl)
+               return -ENOMEM;
+
+       cl->con_id = n;
+       cl->dev_id = dev_name(ddata->dev);
+       cl->clk = clock;
+       clkdev_add(cl);
+
+       clk_put(clock);
+
+       return 0;
+}
+
+static int sysc_init_ext_opt_clock(struct sysc *ddata, const char *name)
+{
+       const char *optfck_name;
+       int error, index;
+
+       if (ddata->nr_clocks < SYSC_OPTFCK0)
+               index = SYSC_OPTFCK0;
+       else
+               index = ddata->nr_clocks;
+
+       if (name)
+               optfck_name = name;
+       else
+               optfck_name = clock_names[index];
+
+       error = sysc_add_named_clock_from_child(ddata, name, optfck_name);
+       if (error)
+               return error;
+
+       ddata->clock_roles[index] = optfck_name;
+       ddata->nr_clocks++;
+
+       return 0;
+}
+
 static int sysc_get_one_clock(struct sysc *ddata, const char *name)
 {
        int error, i, index = -ENODEV;
@@ -199,6 +278,12 @@ static int sysc_get_clocks(struct sysc *ddata)
        if (ddata->nr_clocks < 1)
                return 0;
 
+       if ((ddata->cfg.quirks & SYSC_QUIRK_EXT_OPT_CLOCK)) {
+               error = sysc_init_ext_opt_clock(ddata, NULL);
+               if (error)
+                       return error;
+       }
+
        if (ddata->nr_clocks > SYSC_MAX_CLOCKS) {
                dev_err(ddata->dev, "too many clocks for %pOF\n", np);
 
@@ -231,39 +316,125 @@ static int sysc_get_clocks(struct sysc *ddata)
        return 0;
 }
 
+static int sysc_enable_main_clocks(struct sysc *ddata)
+{
+       struct clk *clock;
+       int i, error;
+
+       if (!ddata->clocks)
+               return 0;
+
+       for (i = 0; i < SYSC_OPTFCK0; i++) {
+               clock = ddata->clocks[i];
+
+               /* Main clocks may not have ick */
+               if (IS_ERR_OR_NULL(clock))
+                       continue;
+
+               error = clk_enable(clock);
+               if (error)
+                       goto err_disable;
+       }
+
+       return 0;
+
+err_disable:
+       for (i--; i >= 0; i--) {
+               clock = ddata->clocks[i];
+
+               /* Main clocks may not have ick */
+               if (IS_ERR_OR_NULL(clock))
+                       continue;
+
+               clk_disable(clock);
+       }
+
+       return error;
+}
+
+static void sysc_disable_main_clocks(struct sysc *ddata)
+{
+       struct clk *clock;
+       int i;
+
+       if (!ddata->clocks)
+               return;
+
+       for (i = 0; i < SYSC_OPTFCK0; i++) {
+               clock = ddata->clocks[i];
+               if (IS_ERR_OR_NULL(clock))
+                       continue;
+
+               clk_disable(clock);
+       }
+}
+
+static int sysc_enable_opt_clocks(struct sysc *ddata)
+{
+       struct clk *clock;
+       int i, error;
+
+       if (!ddata->clocks)
+               return 0;
+
+       for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
+               clock = ddata->clocks[i];
+
+               /* Assume no holes for opt clocks */
+               if (IS_ERR_OR_NULL(clock))
+                       return 0;
+
+               error = clk_enable(clock);
+               if (error)
+                       goto err_disable;
+       }
+
+       return 0;
+
+err_disable:
+       for (i--; i >= 0; i--) {
+               clock = ddata->clocks[i];
+               if (IS_ERR_OR_NULL(clock))
+                       continue;
+
+               clk_disable(clock);
+       }
+
+       return error;
+}
+
+static void sysc_disable_opt_clocks(struct sysc *ddata)
+{
+       struct clk *clock;
+       int i;
+
+       if (!ddata->clocks)
+               return;
+
+       for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
+               clock = ddata->clocks[i];
+
+               /* Assume no holes for opt clocks */
+               if (IS_ERR_OR_NULL(clock))
+                       return;
+
+               clk_disable(clock);
+       }
+}
+
 /**
- * sysc_init_resets - reset module on init
+ * sysc_init_resets - init rstctrl reset line if configured
  * @ddata: device driver data
  *
- * A module can have both OCP softreset control and external rstctrl.
- * If more complicated rstctrl resets are needed, please handle these
- * directly from the child device driver and map only the module reset
- * for the parent interconnect target module device.
- *
- * Automatic reset of the module on init can be skipped with the
- * "ti,no-reset-on-init" device tree property.
+ * See sysc_rstctrl_reset_deassert().
  */
 static int sysc_init_resets(struct sysc *ddata)
 {
-       int error;
-
        ddata->rsts =
                devm_reset_control_array_get_optional_exclusive(ddata->dev);
        if (IS_ERR(ddata->rsts))
                return PTR_ERR(ddata->rsts);
 
-       if (ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
-               goto deassert;
-
-       error = reset_control_assert(ddata->rsts);
-       if (error)
-               return error;
-
-deassert:
-       error = reset_control_deassert(ddata->rsts);
-       if (error)
-               return error;
-
        return 0;
 }
 
@@ -622,91 +793,239 @@ static void sysc_show_registers(struct sysc *ddata)
                buf);
 }
 
-static int __maybe_unused sysc_runtime_suspend(struct device *dev)
+#define SYSC_IDLE_MASK (SYSC_NR_IDLEMODES - 1)
+
+static int sysc_enable_module(struct device *dev)
 {
-       struct ti_sysc_platform_data *pdata;
        struct sysc *ddata;
-       int error = 0, i;
+       const struct sysc_regbits *regbits;
+       u32 reg, idlemodes, best_mode;
 
        ddata = dev_get_drvdata(dev);
+       if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV)
+               return 0;
 
-       if (!ddata->enabled)
+       /*
+        * TODO: Need to prevent clockdomain autoidle?
+        * See clkdm_deny_idle() in arch/mach-omap2/omap_hwmod.c
+        */
+
+       regbits = ddata->cap->regbits;
+       reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
+
+       /* Set SIDLE mode */
+       idlemodes = ddata->cfg.sidlemodes;
+       if (!idlemodes || regbits->sidle_shift < 0)
+               goto set_midle;
+
+       best_mode = fls(ddata->cfg.sidlemodes) - 1;
+       if (best_mode > SYSC_IDLE_MASK) {
+               dev_err(dev, "%s: invalid sidlemode\n", __func__);
+               return -EINVAL;
+       }
+
+       reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift);
+       reg |= best_mode << regbits->sidle_shift;
+       sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
+
+set_midle:
+       /* Set MIDLE mode */
+       idlemodes = ddata->cfg.midlemodes;
+       if (!idlemodes || regbits->midle_shift < 0)
                return 0;
 
-       if (ddata->legacy_mode) {
-               pdata = dev_get_platdata(ddata->dev);
-               if (!pdata)
-                       return 0;
+       best_mode = fls(ddata->cfg.midlemodes) - 1;
+       if (best_mode > SYSC_IDLE_MASK) {
+               dev_err(dev, "%s: invalid midlemode\n", __func__);
+               return -EINVAL;
+       }
 
-               if (!pdata->idle_module)
-                       return -ENODEV;
+       reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift);
+       reg |= best_mode << regbits->midle_shift;
+       sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
 
-               error = pdata->idle_module(dev, &ddata->cookie);
-               if (error)
-                       dev_err(dev, "%s: could not idle: %i\n",
-                               __func__, error);
+       return 0;
+}
+
+static int sysc_best_idle_mode(u32 idlemodes, u32 *best_mode)
+{
+       if (idlemodes & BIT(SYSC_IDLE_SMART_WKUP))
+               *best_mode = SYSC_IDLE_SMART_WKUP;
+       else if (idlemodes & BIT(SYSC_IDLE_SMART))
+               *best_mode = SYSC_IDLE_SMART;
+       else if (idlemodes & SYSC_IDLE_FORCE)
+               *best_mode = SYSC_IDLE_FORCE;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static int sysc_disable_module(struct device *dev)
+{
+       struct sysc *ddata;
+       const struct sysc_regbits *regbits;
+       u32 reg, idlemodes, best_mode;
+       int ret;
 
-               goto idled;
+       ddata = dev_get_drvdata(dev);
+       if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV)
+               return 0;
+
+       /*
+        * TODO: Need to prevent clockdomain autoidle?
+        * See clkdm_deny_idle() in arch/mach-omap2/omap_hwmod.c
+        */
+
+       regbits = ddata->cap->regbits;
+       reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
+
+       /* Set MIDLE mode */
+       idlemodes = ddata->cfg.midlemodes;
+       if (!idlemodes || regbits->midle_shift < 0)
+               goto set_sidle;
+
+       ret = sysc_best_idle_mode(idlemodes, &best_mode);
+       if (ret) {
+               dev_err(dev, "%s: invalid midlemode\n", __func__);
+               return ret;
        }
 
-       for (i = 0; i < ddata->nr_clocks; i++) {
-               if (IS_ERR_OR_NULL(ddata->clocks[i]))
-                       continue;
+       reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift);
+       reg |= best_mode << regbits->midle_shift;
+       sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
 
-               if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
-                       break;
+set_sidle:
+       /* Set SIDLE mode */
+       idlemodes = ddata->cfg.sidlemodes;
+       if (!idlemodes || regbits->sidle_shift < 0)
+               return 0;
 
-               clk_disable(ddata->clocks[i]);
+       ret = sysc_best_idle_mode(idlemodes, &best_mode);
+       if (ret) {
+               dev_err(dev, "%s: invalid sidlemode\n", __func__);
+               return ret;
        }
 
-idled:
-       ddata->enabled = false;
+       reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift);
+       reg |= best_mode << regbits->sidle_shift;
+       sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
 
-       return error;
+       return 0;
 }
 
-static int __maybe_unused sysc_runtime_resume(struct device *dev)
+static int __maybe_unused sysc_runtime_suspend_legacy(struct device *dev,
+                                                     struct sysc *ddata)
 {
        struct ti_sysc_platform_data *pdata;
+       int error;
+
+       pdata = dev_get_platdata(ddata->dev);
+       if (!pdata)
+               return 0;
+
+       if (!pdata->idle_module)
+               return -ENODEV;
+
+       error = pdata->idle_module(dev, &ddata->cookie);
+       if (error)
+               dev_err(dev, "%s: could not idle: %i\n",
+                       __func__, error);
+
+       return 0;
+}
+
+static int __maybe_unused sysc_runtime_resume_legacy(struct device *dev,
+                                                    struct sysc *ddata)
+{
+       struct ti_sysc_platform_data *pdata;
+       int error;
+
+       pdata = dev_get_platdata(ddata->dev);
+       if (!pdata)
+               return 0;
+
+       if (!pdata->enable_module)
+               return -ENODEV;
+
+       error = pdata->enable_module(dev, &ddata->cookie);
+       if (error)
+               dev_err(dev, "%s: could not enable: %i\n",
+                       __func__, error);
+
+       return 0;
+}
+
+static int __maybe_unused sysc_runtime_suspend(struct device *dev)
+{
        struct sysc *ddata;
-       int error = 0, i;
+       int error = 0;
 
        ddata = dev_get_drvdata(dev);
 
-       if (ddata->enabled)
+       if (!ddata->enabled)
                return 0;
 
        if (ddata->legacy_mode) {
-               pdata = dev_get_platdata(ddata->dev);
-               if (!pdata)
-                       return 0;
+               error = sysc_runtime_suspend_legacy(dev, ddata);
+               if (error)
+                       return error;
+       } else {
+               error = sysc_disable_module(dev);
+               if (error)
+                       return error;
+       }
 
-               if (!pdata->enable_module)
-                       return -ENODEV;
+       sysc_disable_main_clocks(ddata);
 
-               error = pdata->enable_module(dev, &ddata->cookie);
-               if (error)
-                       dev_err(dev, "%s: could not enable: %i\n",
-                               __func__, error);
+       if (sysc_opt_clks_needed(ddata))
+               sysc_disable_opt_clocks(ddata);
 
-               goto awake;
-       }
+       ddata->enabled = false;
 
-       for (i = 0; i < ddata->nr_clocks; i++) {
-               if (IS_ERR_OR_NULL(ddata->clocks[i]))
-                       continue;
+       return error;
+}
 
-               if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
-                       break;
+static int __maybe_unused sysc_runtime_resume(struct device *dev)
+{
+       struct sysc *ddata;
+       int error = 0;
+
+       ddata = dev_get_drvdata(dev);
 
-               error = clk_enable(ddata->clocks[i]);
+       if (ddata->enabled)
+               return 0;
+
+       if (sysc_opt_clks_needed(ddata)) {
+               error = sysc_enable_opt_clocks(ddata);
                if (error)
                        return error;
        }
 
-awake:
+       error = sysc_enable_main_clocks(ddata);
+       if (error)
+               goto err_opt_clocks;
+
+       if (ddata->legacy_mode) {
+               error = sysc_runtime_resume_legacy(dev, ddata);
+               if (error)
+                       goto err_main_clocks;
+       } else {
+               error = sysc_enable_module(dev);
+               if (error)
+                       goto err_main_clocks;
+       }
+
        ddata->enabled = true;
 
+       return 0;
+
+err_main_clocks:
+       sysc_disable_main_clocks(ddata);
+err_opt_clocks:
+       if (sysc_opt_clks_needed(ddata))
+               sysc_disable_opt_clocks(ddata);
+
        return error;
 }
 
@@ -788,12 +1107,17 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
        SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff,
                   0),
        SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff,
-                  SYSC_QUIRK_LEGACY_IDLE),
+                  SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
        /* Uarts on omap4 and later */
        SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff,
-                  SYSC_QUIRK_LEGACY_IDLE),
+                  SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
        SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff,
-                  SYSC_QUIRK_LEGACY_IDLE),
+                  SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
+
+       /* Quirks that need to be set based on the module address */
+       SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -1, 0x50000800, 0xffffffff,
+                  SYSC_QUIRK_EXT_OPT_CLOCK | SYSC_QUIRK_NO_RESET_ON_INIT |
+                  SYSC_QUIRK_SWSUP_SIDLE),
 
 #ifdef DEBUG
        SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0),
@@ -805,6 +1129,7 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
                   0xffff00f0, 0),
        SYSC_QUIRK("dcan", 0, 0, -1, -1, 0xffffffff, 0xffffffff, 0),
        SYSC_QUIRK("dcan", 0, 0, -1, -1, 0x00001401, 0xffffffff, 0),
+       SYSC_QUIRK("dmic", 0, 0, 0x10, -1, 0x50010000, 0xffffffff, 0),
        SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0),
        SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0),
        SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0),
@@ -853,6 +1178,42 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
 #endif
 };
 
+/*
+ * Early quirks based on module base and register offsets only that are
+ * needed before the module revision can be read
+ */
+static void sysc_init_early_quirks(struct sysc *ddata)
+{
+       const struct sysc_revision_quirk *q;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(sysc_revision_quirks); i++) {
+               q = &sysc_revision_quirks[i];
+
+               if (!q->base)
+                       continue;
+
+               if (q->base != ddata->module_pa)
+                       continue;
+
+               if (q->rev_offset >= 0 &&
+                   q->rev_offset != ddata->offsets[SYSC_REVISION])
+                       continue;
+
+               if (q->sysc_offset >= 0 &&
+                   q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG])
+                       continue;
+
+               if (q->syss_offset >= 0 &&
+                   q->syss_offset != ddata->offsets[SYSC_SYSSTATUS])
+                       continue;
+
+               ddata->name = q->name;
+               ddata->cfg.quirks |= q->quirks;
+       }
+}
+
+/* Quirks that also consider the revision register value */
 static void sysc_init_revision_quirks(struct sysc *ddata)
 {
        const struct sysc_revision_quirk *q;
@@ -885,6 +1246,55 @@ static void sysc_init_revision_quirks(struct sysc *ddata)
        }
 }
 
+/*
+ * Note that pdata->init_module() typically does a reset first. After
+ * pdata->init_module() is done, PM runtime can be used for the interconnect
+ * target module.
+ */
+static int sysc_legacy_init(struct sysc *ddata)
+{
+       struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
+       int error;
+
+       if (!ddata->legacy_mode || !pdata || !pdata->init_module)
+               return 0;
+
+       error = pdata->init_module(ddata->dev, ddata->mdata, &ddata->cookie);
+       if (error == -EEXIST)
+               error = 0;
+
+       return error;
+}
+
+/**
+ * sysc_rstctrl_reset_deassert - deassert rstctrl reset
+ * @ddata: device driver data
+ * @reset: reset before deassert
+ *
+ * A module can have both OCP softreset control and external rstctrl.
+ * If more complicated rstctrl resets are needed, please handle these
+ * directly from the child device driver and map only the module reset
+ * for the parent interconnect target module device.
+ *
+ * Automatic reset of the module on init can be skipped with the
+ * "ti,no-reset-on-init" device tree property.
+ */
+static int sysc_rstctrl_reset_deassert(struct sysc *ddata, bool reset)
+{
+       int error;
+
+       if (!ddata->rsts)
+               return 0;
+
+       if (reset) {
+               error = reset_control_assert(ddata->rsts);
+               if (error)
+                       return error;
+       }
+
+       return reset_control_deassert(ddata->rsts);
+}
+
 static int sysc_reset(struct sysc *ddata)
 {
        int offset = ddata->offsets[SYSC_SYSCONFIG];
@@ -915,38 +1325,58 @@ static int sysc_reset(struct sysc *ddata)
                                  100, MAX_MODULE_SOFTRESET_WAIT);
 }
 
-/* At this point the module is configured enough to read the revision */
+/*
+ * At this point the module is configured enough to read the revision but
+ * module may not be completely configured yet to use PM runtime. Enable
+ * all clocks directly during init to configure the quirks needed for PM
+ * runtime based on the revision register.
+ */
 static int sysc_init_module(struct sysc *ddata)
 {
-       int error;
+       int error = 0;
+       bool manage_clocks = true;
+       bool reset = true;
 
-       if (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE_ON_INIT) {
-               ddata->revision = sysc_read_revision(ddata);
-               goto rev_quirks;
-       }
+       if (ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
+               reset = false;
 
-       error = pm_runtime_get_sync(ddata->dev);
-       if (error < 0) {
-               pm_runtime_put_noidle(ddata->dev);
+       error = sysc_rstctrl_reset_deassert(ddata, reset);
+       if (error)
+               return error;
 
-               return 0;
-       }
+       if (ddata->cfg.quirks &
+           (SYSC_QUIRK_NO_IDLE | SYSC_QUIRK_NO_IDLE_ON_INIT))
+               manage_clocks = false;
 
-       error = sysc_reset(ddata);
-       if (error) {
-               dev_err(ddata->dev, "Reset failed with %d\n", error);
-               pm_runtime_put_sync(ddata->dev);
+       if (manage_clocks) {
+               error = sysc_enable_opt_clocks(ddata);
+               if (error)
+                       return error;
 
-               return error;
+               error = sysc_enable_main_clocks(ddata);
+               if (error)
+                       goto err_opt_clocks;
        }
 
        ddata->revision = sysc_read_revision(ddata);
-       pm_runtime_put_sync(ddata->dev);
-
-rev_quirks:
        sysc_init_revision_quirks(ddata);
 
-       return 0;
+       error = sysc_legacy_init(ddata);
+       if (error)
+               goto err_main_clocks;
+
+       error = sysc_reset(ddata);
+       if (error)
+               dev_err(ddata->dev, "Reset failed with %d\n", error);
+
+err_main_clocks:
+       if (manage_clocks)
+               sysc_disable_main_clocks(ddata);
+err_opt_clocks:
+       if (manage_clocks)
+               sysc_disable_opt_clocks(ddata);
+
+       return error;
 }
 
 static int sysc_init_sysc_mask(struct sysc *ddata)
@@ -1208,7 +1638,7 @@ static int sysc_child_resume_noirq(struct device *dev)
 }
 #endif
 
-struct dev_pm_domain sysc_child_pm_domain = {
+static struct dev_pm_domain sysc_child_pm_domain = {
        .ops = {
                SET_RUNTIME_PM_OPS(sysc_child_runtime_suspend,
                                   sysc_child_runtime_resume,
@@ -1281,6 +1711,8 @@ static const struct sysc_dts_quirk sysc_dts_quirks[] = {
          .mask = SYSC_QUIRK_NO_IDLE_ON_INIT, },
        { .name = "ti,no-reset-on-init",
          .mask = SYSC_QUIRK_NO_RESET_ON_INIT, },
+       { .name = "ti,no-idle",
+         .mask = SYSC_QUIRK_NO_IDLE, },
 };
 
 static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np,
@@ -1331,6 +1763,9 @@ static void sysc_unprepare(struct sysc *ddata)
 {
        int i;
 
+       if (!ddata->clocks)
+               return;
+
        for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
                if (!IS_ERR_OR_NULL(ddata->clocks[i]))
                        clk_unprepare(ddata->clocks[i]);
@@ -1576,28 +2011,26 @@ static const struct sysc_capabilities sysc_dra7_mcan = {
 static int sysc_init_pdata(struct sysc *ddata)
 {
        struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
-       struct ti_sysc_module_data mdata;
-       int error = 0;
+       struct ti_sysc_module_data *mdata;
 
        if (!pdata || !ddata->legacy_mode)
                return 0;
 
-       mdata.name = ddata->legacy_mode;
-       mdata.module_pa = ddata->module_pa;
-       mdata.module_size = ddata->module_size;
-       mdata.offsets = ddata->offsets;
-       mdata.nr_offsets = SYSC_MAX_REGS;
-       mdata.cap = ddata->cap;
-       mdata.cfg = &ddata->cfg;
+       mdata = devm_kzalloc(ddata->dev, sizeof(*mdata), GFP_KERNEL);
+       if (!mdata)
+               return -ENOMEM;
 
-       if (!pdata->init_module)
-               return -ENODEV;
+       mdata->name = ddata->legacy_mode;
+       mdata->module_pa = ddata->module_pa;
+       mdata->module_size = ddata->module_size;
+       mdata->offsets = ddata->offsets;
+       mdata->nr_offsets = SYSC_MAX_REGS;
+       mdata->cap = ddata->cap;
+       mdata->cfg = &ddata->cfg;
 
-       error = pdata->init_module(ddata->dev, &mdata, &ddata->cookie);
-       if (error == -EEXIST)
-               error = 0;
+       ddata->mdata = mdata;
 
-       return error;
+       return 0;
 }
 
 static int sysc_init_match(struct sysc *ddata)
@@ -1651,10 +2084,6 @@ static int sysc_probe(struct platform_device *pdev)
        if (error)
                goto unprepare;
 
-       error = sysc_get_clocks(ddata);
-       if (error)
-               return error;
-
        error = sysc_map_and_check_registers(ddata);
        if (error)
                goto unprepare;
@@ -1675,15 +2104,21 @@ static int sysc_probe(struct platform_device *pdev)
        if (error)
                goto unprepare;
 
+       sysc_init_early_quirks(ddata);
+
+       error = sysc_get_clocks(ddata);
+       if (error)
+               return error;
+
        error = sysc_init_resets(ddata);
        if (error)
                return error;
 
-       pm_runtime_enable(ddata->dev);
        error = sysc_init_module(ddata);
        if (error)
                goto unprepare;
 
+       pm_runtime_enable(ddata->dev);
        error = pm_runtime_get_sync(ddata->dev);
        if (error < 0) {
                pm_runtime_put_noidle(ddata->dev);
index 02d3bcd..71c2e95 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/device.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/of.h>
index c68dada..aba787b 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/device.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
index 2a2c756..b6d07ca 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <dt-bindings/clock/bcm2835-aux.h>
index 9fcae93..770bb01 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/clk.h>
 #include <linux/debugfs.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
index eee64b9..cc3b1e1 100644 (file)
@@ -15,8 +15,9 @@
 #include "clk-kona.h"
 
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
 
 /*
  * "Policies" affect the frequencies of bus clocks provided by a
index 4d0be66..eb14a5b 100644 (file)
@@ -7,6 +7,7 @@
  */
 #include <linux/bitops.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
index 0b4b44a..bccdfa0 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 9b9db74..e9518d3 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index d1a97d9..51f2661 100644 (file)
@@ -10,8 +10,9 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/of_address.h>
+#include <linux/io.h>
 #include <linux/module.h>
+#include <linux/of_address.h>
 #include <linux/platform_device.h>
 
 static struct clk_hw *fixed_mmio_clk_setup(struct device_node *node)
index d81f1d2..b1e556f 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/slab.h>
index a47c2b6..97d1e8c 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
index 94470b4..e507aa9 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/export.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/slab.h>
index 0f71981..bf120be 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/clkdev.h>
 #include <linux/device.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/mfd/da8xx-cfgchip.h>
 #include <linux/mfd/syscon.h>
index d413ade..376be03 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 
index c7ae653..67c495b 100644 (file)
@@ -6,8 +6,9 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/err.h>
 #include <linux/device.h>
+#include <linux/io.h>
+#include <linux/err.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
 
index e8b2c43..89934be 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/mailbox_client.h>
 #include <linux/module.h>
 #include <linux/of.h>
index 574fac1..388bdb9 100644 (file)
@@ -3,9 +3,10 @@
  * Copyright 2018 NXP
  */
 
+#include <linux/clk-provider.h>
 #include <linux/errno.h>
+#include <linux/io.h>
 #include <linux/slab.h>
-#include <linux/clk-provider.h>
 
 #include "clk.h"
 
index 76b9eb1..fece503 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/slab.h>
 #include <linux/bitfield.h>
index e63188e..6e93284 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <dt-bindings/clock/imx21-clock.h>
index 0a0ab95..a375306 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <dt-bindings/clock/imx27-clock.h>
index fb567dc..a03bbed 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/slab.h>
 
index d7e62c3..8155b12 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/slab.h>
 
index 991bbe6..5d65f65 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/slab.h>
 #include <linux/bitfield.h>
index 510b685..b80af61 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/math64.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index b86edd3..25f7df0 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <dt-bindings/clock/jz4740-cgu.h>
 #include <asm/mach-jz4740/clock.h>
index bf46a0d..dfce740 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/bitops.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/syscore_ops.h>
 #include <dt-bindings/clock/jz4770-cgu.h>
index 6427be1..d03b7fc 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <dt-bindings/clock/jz4780-cgu.h>
 #include "cgu.h"
index 3466f73..22a165e 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include <loongson1.h>
 #include "clk.h"
index c3b3014..4680064 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/iopoll.h>
 #include <asm/mach-pic32/pic32.h>
 #include <asm/traps.h>
index 9f73477..e6c05df 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
index 1f1cff4..5fc6d48 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/mfd/syscon.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
index ee272d4..585a02e 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/clk.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
index 1fc84b0..818b175 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
index 5969f62..f2e171a 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index f5bc8bd..8b686da 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 7524d19..7f67c10 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/regmap.h>
 
index 42627bf..5326f77 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
+#include <linux/io.h>
 #include <linux/of.h>
 
 #include <dt-bindings/clock/pxa-clock.h>
index 2719c24..cfed11c 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/clk-provider.h>
 #include <linux/clk/renesas.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/of.h>
index 5967656..d8190f0 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/clk-provider.h>
 #include <linux/clk/renesas.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/of.h>
index 2913b41..da9fe3f 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/clk-provider.h>
 #include <linux/clk/renesas.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/math64.h>
 #include <linux/of.h>
index 3cda53a..fbc34be 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/clk-provider.h>
 #include <linux/clk/renesas.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index dc8ffc7..5f25a70 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/clk-provider.h>
 #include <linux/clk/renesas.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 97c7247..7d04218 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/math64.h>
 #include <linux/of.h>
index b241f9c..cc90b11 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/clk-provider.h>
 #include <linux/device.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
index 30df0dc..0201809 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
index 784b81e..ba9f00d 100644 (file)
@@ -3,8 +3,9 @@
  * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
  */
 
-#include <linux/slab.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/slab.h>
 #include "clk.h"
 
 #define div_mask(width)        ((1 << (width)) - 1)
index 601a77f..68d23be 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
index c300198..3bf919b 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
index 5970a50..8278a54 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
index 5ecf288..378420b 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <dt-bindings/clock/rk3188-cru-common.h>
index 7af4818..7176003 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
index 24baeb5..85907f3 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
index f12142d..9b03c1a 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
index 7c4d242..d239bbc 100644 (file)
@@ -13,6 +13,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
index 5a62814..2322d71 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
index 089cb17..6c051aa 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
index 0ea8e80..d5fac5a 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 #include <linux/reboot.h>
index a5fddeb..3f80bcd 100644 (file)
@@ -33,6 +33,7 @@
 */
 
 #include <linux/errno.h>
+#include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
index 9c95390..ce41f36 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
index 0e9a41a..facaad3 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
index 54066e6..d2a68a7 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 
index 8ae44b5..91db789 100644 (file)
@@ -4,6 +4,7 @@
 // Author: Marek Szyprowski <m.szyprowski@samsung.com>
 // Common Clock Framework support for Exynos5 power-domain dependent clocks
 
+#include <linux/io.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
index f14139b..c8265c4 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <dt-bindings/clock/exynos5250.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 
index 1c4c7a3..0c6782c 100644 (file)
@@ -13,7 +13,8 @@
 #include <linux/hrtimer.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
 #include "clk.h"
 #include "clk-pll.h"
 
index 82f8ae2..0117e40 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include "clk.h"
index dd11590..ce21b89 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/reboot.h>
index f38f0e2..b2ea4df 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/reboot.h>
index 1f6e47c..9ad546a 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/clkdev.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
 
index 0ec8bf7..6282ee2 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/clk/analogbits-wrpll-cln28hpc.h>
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_clk.h>
index eee2d48..54a464f 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (C) 2017, Intel Corporation
  */
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/slab.h>
 #include "stratix10-clk.h"
 #include "clk.h"
index 568f59b..5c50e72 100644 (file)
@@ -4,6 +4,7 @@
  */
 #include <linux/slab.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "stratix10-clk.h"
 #include "clk.h"
index c4d0b6f..4705eb5 100644 (file)
@@ -4,6 +4,7 @@
  */
 #include <linux/slab.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "stratix10-clk.h"
 #include "clk.h"
index c514d39..23497f0 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
index 129ebd2..2bbfb33 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 
 #include "ccu_common.h"
index be0deee..d3fc1f5 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 
index 3c32d77..9d3f989 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 
index fa2c2dd..813e9bf 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 
 #include "ccu_common.h"
index 609970c..b494c4f 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 
 #include "ccu_common.h"
index 4b5f8f4..a9c0c54 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 
 #include "ccu_common.h"
index c7bf814..25bcf3f 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 
 #include "ccu_common.h"
index 5f714b4..be5920e 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 
index e71e245..0f3df56 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 
 #include "ccu_common.h"
index a22d11a..f9625f7 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 
index eada0e2..ec64eb6 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 
 #include "ccu_common.h"
index 8936ef8..0e23583 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 
index dc9f0a3..e748b8a 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 
 #include "ccu_common.h"
index 302a18e..6d407a8 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "ccu_gate.h"
 #include "ccu_div.h"
index d1d168d..1842603 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/spinlock.h>
 
 #include "ccu_frac.h"
index cd069d5..9c81644 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "ccu_gate.h"
 
index f9869f7..b234106 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/clk/sunxi-ng.h>
+#include <linux/io.h>
 
 #include "ccu_common.h"
 
index 0357349..e17fb4c 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "ccu_gate.h"
 #include "ccu_mp.h"
index 12e0783..c2a6727 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "ccu_gate.h"
 #include "ccu_mult.h"
index 3126641..f9b409c 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 
 #include "ccu_gate.h"
 #include "ccu_mux.h"
index 2485bda..50c7e6b 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "ccu_gate.h"
 #include "ccu_nk.h"
index 841840e..aa5beaa 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "ccu_gate.h"
 #include "ccu_nkm.h"
index cbcdf66..53ec4fb 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "ccu_gate.h"
 #include "ccu_nkmp.h"
index 424d863..e154131 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "ccu_frac.h"
 #include "ccu_gate.h"
index 400c58a..0a4a6fd 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/spinlock.h>
 
 #include "ccu_phase.h"
index 3b3dc9b..e510467 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/spinlock.h>
 
 #include "ccu_sdm.h"
index e2819fa..9e6796a 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
index d8eab90..a709b6a 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
index d9ea22e..d119b45 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/reset-controller.h>
index 3437f73..e6d639d 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
index fc0278a..9159545 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
index a085c3b..8130467 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
index 9780fac..bb2dc83 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/reset-controller.h>
index f66267e..c879d7e 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
index b6d29d1..af8ca50 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
index d5c3180..5a7d4dd 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
index bee305b..bfbcd71 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
index 56db89b..0e924c9 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/of_address.h>
index 4d5e141..01255d8 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/of.h>
index f00d875..da264d0 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/reset.h>
index 892c290..f5b1c00 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/reset-controller.h>
index 917fc27..7d15e04 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/reset-controller.h>
index 93ecb53..b7f763f 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
index c57dfb0..956f221 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "clk.h"
 
index 473d418..a5cd3e3 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/types.h>
 
 #include "clk.h"
index ffaf17f..6f2862e 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/clk/tegra.h>
 #include <linux/reset-controller.h>
index 0c21098..fdfb900 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/math64.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
index ba17cc5..e0b8ed3 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/clk/ti.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/list.h>
index ed24f20..95e36ba 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/math64.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index c2b6bb8..4fa0cd9 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 
index 1917483..5970edb 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/platform_data/x86/clk-pmc-atom.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
index 8febd24..a11f93e 100644 (file)
@@ -739,8 +739,8 @@ static int zynqmp_clock_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
 
        eemi_ops = zynqmp_pm_get_eemi_ops();
-       if (!eemi_ops)
-               return -ENXIO;
+       if (IS_ERR(eemi_ops))
+               return PTR_ERR(eemi_ops);
 
        ret = zynqmp_clk_setup(dev->of_node);
 
index 4b3d143..4832148 100644 (file)
@@ -69,6 +69,13 @@ config FTTMR010_TIMER
          Enables support for the Faraday Technology timer block
          FTTMR010.
 
+config IXP4XX_TIMER
+       bool "Intel XScale IXP4xx timer driver" if COMPILE_TEST
+       depends on HAS_IOMEM
+       select CLKSRC_MMIO
+       help
+         Enables support for the Intel XScale IXP4xx SoC timer.
+
 config ROCKCHIP_TIMER
        bool "Rockchip timer driver" if COMPILE_TEST
        depends on ARM || ARM64
index be6e0fb..dba4eff 100644 (file)
@@ -20,6 +20,7 @@ obj-$(CONFIG_OMAP_DM_TIMER)   += timer-ti-dm.o
 obj-$(CONFIG_DW_APB_TIMER)     += dw_apb_timer.o
 obj-$(CONFIG_DW_APB_TIMER_OF)  += dw_apb_timer_of.o
 obj-$(CONFIG_FTTMR010_TIMER)   += timer-fttmr010.o
+obj-$(CONFIG_IXP4XX_TIMER)     += timer-ixp4xx.o
 obj-$(CONFIG_ROCKCHIP_TIMER)      += timer-rockchip.o
 obj-$(CONFIG_CLKSRC_NOMADIK_MTU)       += nomadik-mtu.o
 obj-$(CONFIG_CLKSRC_DBX500_PRCMU)      += clksrc-dbx500-prcmu.o
diff --git a/drivers/clocksource/timer-ixp4xx.c b/drivers/clocksource/timer-ixp4xx.c
new file mode 100644 (file)
index 0000000..5c2190b
--- /dev/null
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IXP4 timer driver
+ * Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
+ *
+ * Based on arch/arm/mach-ixp4xx/common.c
+ * Copyright 2002 (C) Intel Corporation
+ * Copyright 2003-2004 (C) MontaVista, Software, Inc.
+ * Copyright (C) Deepak Saxena <dsaxena@plexity.net>
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/sched_clock.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+/* Goes away with OF conversion */
+#include <linux/platform_data/timer-ixp4xx.h>
+
+/*
+ * Constants to make it easy to access Timer Control/Status registers
+ */
+#define IXP4XX_OSTS_OFFSET     0x00  /* Continuous Timestamp */
+#define IXP4XX_OST1_OFFSET     0x04  /* Timer 1 Timestamp */
+#define IXP4XX_OSRT1_OFFSET    0x08  /* Timer 1 Reload */
+#define IXP4XX_OST2_OFFSET     0x0C  /* Timer 2 Timestamp */
+#define IXP4XX_OSRT2_OFFSET    0x10  /* Timer 2 Reload */
+#define IXP4XX_OSWT_OFFSET     0x14  /* Watchdog Timer */
+#define IXP4XX_OSWE_OFFSET     0x18  /* Watchdog Enable */
+#define IXP4XX_OSWK_OFFSET     0x1C  /* Watchdog Key */
+#define IXP4XX_OSST_OFFSET     0x20  /* Timer Status */
+
+/*
+ * Timer register values and bit definitions
+ */
+#define IXP4XX_OST_ENABLE              0x00000001
+#define IXP4XX_OST_ONE_SHOT            0x00000002
+/* Low order bits of reload value ignored */
+#define IXP4XX_OST_RELOAD_MASK         0x00000003
+#define IXP4XX_OST_DISABLED            0x00000000
+#define IXP4XX_OSST_TIMER_1_PEND       0x00000001
+#define IXP4XX_OSST_TIMER_2_PEND       0x00000002
+#define IXP4XX_OSST_TIMER_TS_PEND      0x00000004
+#define IXP4XX_OSST_TIMER_WDOG_PEND    0x00000008
+#define IXP4XX_OSST_TIMER_WARM_RESET   0x00000010
+
+#define        IXP4XX_WDT_KEY                  0x0000482E
+#define        IXP4XX_WDT_RESET_ENABLE         0x00000001
+#define        IXP4XX_WDT_IRQ_ENABLE           0x00000002
+#define        IXP4XX_WDT_COUNT_ENABLE         0x00000004
+
+struct ixp4xx_timer {
+       void __iomem *base;
+       unsigned int tick_rate;
+       u32 latch;
+       struct clock_event_device clkevt;
+#ifdef CONFIG_ARM
+       struct delay_timer delay_timer;
+#endif
+};
+
+/*
+ * A local singleton used by sched_clock and delay timer reads, which are
+ * fast and stateless
+ */
+static struct ixp4xx_timer *local_ixp4xx_timer;
+
+static inline struct ixp4xx_timer *
+to_ixp4xx_timer(struct clock_event_device *evt)
+{
+       return container_of(evt, struct ixp4xx_timer, clkevt);
+}
+
+static u64 notrace ixp4xx_read_sched_clock(void)
+{
+       return __raw_readl(local_ixp4xx_timer->base + IXP4XX_OSTS_OFFSET);
+}
+
+static u64 ixp4xx_clocksource_read(struct clocksource *c)
+{
+       return __raw_readl(local_ixp4xx_timer->base + IXP4XX_OSTS_OFFSET);
+}
+
+static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
+{
+       struct ixp4xx_timer *tmr = dev_id;
+       struct clock_event_device *evt = &tmr->clkevt;
+
+       /* Clear Pending Interrupt */
+       __raw_writel(IXP4XX_OSST_TIMER_1_PEND,
+                    tmr->base + IXP4XX_OSST_OFFSET);
+
+       evt->event_handler(evt);
+
+       return IRQ_HANDLED;
+}
+
+static int ixp4xx_set_next_event(unsigned long cycles,
+                                struct clock_event_device *evt)
+{
+       struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
+       u32 val;
+
+       val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
+       /* Keep enable/oneshot bits */
+       val &= IXP4XX_OST_RELOAD_MASK;
+       __raw_writel((cycles & ~IXP4XX_OST_RELOAD_MASK) | val,
+                    tmr->base + IXP4XX_OSRT1_OFFSET);
+
+       return 0;
+}
+
+static int ixp4xx_shutdown(struct clock_event_device *evt)
+{
+       struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
+       u32 val;
+
+       val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
+       val &= ~IXP4XX_OST_ENABLE;
+       __raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET);
+
+       return 0;
+}
+
+static int ixp4xx_set_oneshot(struct clock_event_device *evt)
+{
+       struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
+
+       __raw_writel(IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT,
+                    tmr->base + IXP4XX_OSRT1_OFFSET);
+
+       return 0;
+}
+
+static int ixp4xx_set_periodic(struct clock_event_device *evt)
+{
+       struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
+       u32 val;
+
+       val = tmr->latch & ~IXP4XX_OST_RELOAD_MASK;
+       val |= IXP4XX_OST_ENABLE;
+       __raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET);
+
+       return 0;
+}
+
+static int ixp4xx_resume(struct clock_event_device *evt)
+{
+       struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
+       u32 val;
+
+       val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
+       val |= IXP4XX_OST_ENABLE;
+       __raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET);
+
+       return 0;
+}
+
+/*
+ * IXP4xx timer tick
+ * We use OS timer1 on the CPU for the timer tick and the timestamp
+ * counter as a source of real clock ticks to account for missed jiffies.
+ */
+static __init int ixp4xx_timer_register(void __iomem *base,
+                                       int timer_irq,
+                                       unsigned int timer_freq)
+{
+       struct ixp4xx_timer *tmr;
+       int ret;
+
+       tmr = kzalloc(sizeof(*tmr), GFP_KERNEL);
+       if (!tmr)
+               return -ENOMEM;
+       tmr->base = base;
+       tmr->tick_rate = timer_freq;
+
+       /*
+        * The timer register doesn't allow to specify the two least
+        * significant bits of the timeout value and assumes them being zero.
+        * So make sure the latch is the best value with the two least
+        * significant bits unset.
+        */
+       tmr->latch = DIV_ROUND_CLOSEST(timer_freq,
+                                      (IXP4XX_OST_RELOAD_MASK + 1) * HZ)
+               * (IXP4XX_OST_RELOAD_MASK + 1);
+
+       local_ixp4xx_timer = tmr;
+
+       /* Reset/disable counter */
+       __raw_writel(0, tmr->base + IXP4XX_OSRT1_OFFSET);
+
+       /* Clear any pending interrupt on timer 1 */
+       __raw_writel(IXP4XX_OSST_TIMER_1_PEND,
+                    tmr->base + IXP4XX_OSST_OFFSET);
+
+       /* Reset time-stamp counter */
+       __raw_writel(0, tmr->base + IXP4XX_OSTS_OFFSET);
+
+       clocksource_mmio_init(NULL, "OSTS", timer_freq, 200, 32,
+                             ixp4xx_clocksource_read);
+
+       tmr->clkevt.name = "ixp4xx timer1";
+       tmr->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+       tmr->clkevt.rating = 200;
+       tmr->clkevt.set_state_shutdown = ixp4xx_shutdown;
+       tmr->clkevt.set_state_periodic = ixp4xx_set_periodic;
+       tmr->clkevt.set_state_oneshot = ixp4xx_set_oneshot;
+       tmr->clkevt.tick_resume = ixp4xx_resume;
+       tmr->clkevt.set_next_event = ixp4xx_set_next_event;
+       tmr->clkevt.cpumask = cpumask_of(0);
+       tmr->clkevt.irq = timer_irq;
+       ret = request_irq(timer_irq, ixp4xx_timer_interrupt,
+                         IRQF_TIMER, "IXP4XX-TIMER1", tmr);
+       if (ret) {
+               pr_crit("no timer IRQ\n");
+               return -ENODEV;
+       }
+       clockevents_config_and_register(&tmr->clkevt, timer_freq,
+                                       0xf, 0xfffffffe);
+
+       sched_clock_register(ixp4xx_read_sched_clock, 32, timer_freq);
+
+       return 0;
+}
+
+/**
+ * ixp4xx_timer_setup() - Timer setup function to be called from boardfiles
+ * @timerbase: physical base of timer block
+ * @timer_irq: Linux IRQ number for the timer
+ * @timer_freq: Fixed frequency of the timer
+ */
+void __init ixp4xx_timer_setup(resource_size_t timerbase,
+                              int timer_irq,
+                              unsigned int timer_freq)
+{
+       void __iomem *base;
+
+       base = ioremap(timerbase, 0x100);
+       if (!base) {
+               pr_crit("IXP4xx: can't remap timer\n");
+               return;
+       }
+       ixp4xx_timer_register(base, timer_irq, timer_freq);
+}
+EXPORT_SYMBOL_GPL(ixp4xx_timer_setup);
+
+#ifdef CONFIG_OF
+static __init int ixp4xx_of_timer_init(struct device_node *np)
+{
+       void __iomem *base;
+       int irq;
+       int ret;
+
+       base = of_iomap(np, 0);
+       if (!base) {
+               pr_crit("IXP4xx: can't remap timer\n");
+               return -ENODEV;
+       }
+
+       irq = irq_of_parse_and_map(np, 0);
+       if (irq <= 0) {
+               pr_err("Can't parse IRQ\n");
+               ret = -EINVAL;
+               goto out_unmap;
+       }
+
+       /* TODO: get some fixed clocks into the device tree */
+       ret = ixp4xx_timer_register(base, irq, 66666000);
+       if (ret)
+               goto out_unmap;
+       return 0;
+
+out_unmap:
+       iounmap(base);
+       return ret;
+}
+TIMER_OF_DECLARE(ixp4xx, "intel,ixp4xx-timer", ixp4xx_of_timer_init);
+#endif
index db779b6..85ff958 100644 (file)
@@ -340,11 +340,14 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
                                      struct cpufreq_freqs *freqs,
                                      unsigned int state)
 {
+       int cpu;
+
        BUG_ON(irqs_disabled());
 
        if (cpufreq_disabled())
                return;
 
+       freqs->policy = policy;
        freqs->flags = cpufreq_driver->flags;
        pr_debug("notification %u of frequency transition to %u kHz\n",
                 state, freqs->new);
@@ -364,10 +367,8 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
                        }
                }
 
-               for_each_cpu(freqs->cpu, policy->cpus) {
-                       srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
-                                                CPUFREQ_PRECHANGE, freqs);
-               }
+               srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
+                                        CPUFREQ_PRECHANGE, freqs);
 
                adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
                break;
@@ -377,11 +378,11 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
                pr_debug("FREQ: %u - CPUs: %*pbl\n", freqs->new,
                         cpumask_pr_args(policy->cpus));
 
-               for_each_cpu(freqs->cpu, policy->cpus) {
-                       trace_cpu_frequency(freqs->new, freqs->cpu);
-                       srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
-                                                CPUFREQ_POSTCHANGE, freqs);
-               }
+               for_each_cpu(cpu, policy->cpus)
+                       trace_cpu_frequency(freqs->new, cpu);
+
+               srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
+                                        CPUFREQ_POSTCHANGE, freqs);
 
                cpufreq_stats_record_transition(policy, freqs->new);
                policy->cur = freqs->new;
@@ -618,50 +619,52 @@ static struct cpufreq_governor *find_governor(const char *str_governor)
        return NULL;
 }
 
+static int cpufreq_parse_policy(char *str_governor,
+                               struct cpufreq_policy *policy)
+{
+       if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
+               policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+               return 0;
+       }
+       if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
+               policy->policy = CPUFREQ_POLICY_POWERSAVE;
+               return 0;
+       }
+       return -EINVAL;
+}
+
 /**
- * cpufreq_parse_governor - parse a governor string
+ * cpufreq_parse_governor - parse a governor string only for !setpolicy
  */
 static int cpufreq_parse_governor(char *str_governor,
                                  struct cpufreq_policy *policy)
 {
-       if (cpufreq_driver->setpolicy) {
-               if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
-                       policy->policy = CPUFREQ_POLICY_PERFORMANCE;
-                       return 0;
-               }
+       struct cpufreq_governor *t;
 
-               if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
-                       policy->policy = CPUFREQ_POLICY_POWERSAVE;
-                       return 0;
-               }
-       } else {
-               struct cpufreq_governor *t;
+       mutex_lock(&cpufreq_governor_mutex);
 
-               mutex_lock(&cpufreq_governor_mutex);
+       t = find_governor(str_governor);
+       if (!t) {
+               int ret;
 
-               t = find_governor(str_governor);
-               if (!t) {
-                       int ret;
-
-                       mutex_unlock(&cpufreq_governor_mutex);
+               mutex_unlock(&cpufreq_governor_mutex);
 
-                       ret = request_module("cpufreq_%s", str_governor);
-                       if (ret)
-                               return -EINVAL;
+               ret = request_module("cpufreq_%s", str_governor);
+               if (ret)
+                       return -EINVAL;
 
-                       mutex_lock(&cpufreq_governor_mutex);
+               mutex_lock(&cpufreq_governor_mutex);
 
-                       t = find_governor(str_governor);
-               }
-               if (t && !try_module_get(t->owner))
-                       t = NULL;
+               t = find_governor(str_governor);
+       }
+       if (t && !try_module_get(t->owner))
+               t = NULL;
 
-               mutex_unlock(&cpufreq_governor_mutex);
+       mutex_unlock(&cpufreq_governor_mutex);
 
-               if (t) {
-                       policy->governor = t;
-                       return 0;
-               }
+       if (t) {
+               policy->governor = t;
+               return 0;
        }
 
        return -EINVAL;
@@ -783,8 +786,13 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
        if (ret != 1)
                return -EINVAL;
 
-       if (cpufreq_parse_governor(str_governor, &new_policy))
-               return -EINVAL;
+       if (cpufreq_driver->setpolicy) {
+               if (cpufreq_parse_policy(str_governor, &new_policy))
+                       return -EINVAL;
+       } else {
+               if (cpufreq_parse_governor(str_governor, &new_policy))
+                       return -EINVAL;
+       }
 
        ret = cpufreq_set_policy(policy, &new_policy);
 
@@ -1050,32 +1058,39 @@ __weak struct cpufreq_governor *cpufreq_default_governor(void)
 
 static int cpufreq_init_policy(struct cpufreq_policy *policy)
 {
-       struct cpufreq_governor *gov = NULL;
+       struct cpufreq_governor *gov = NULL, *def_gov = NULL;
        struct cpufreq_policy new_policy;
 
        memcpy(&new_policy, policy, sizeof(*policy));
 
-       /* Update governor of new_policy to the governor used before hotplug */
-       gov = find_governor(policy->last_governor);
-       if (gov) {
-               pr_debug("Restoring governor %s for cpu %d\n",
+       def_gov = cpufreq_default_governor();
+
+       if (has_target()) {
+               /*
+                * Update governor of new_policy to the governor used before
+                * hotplug
+                */
+               gov = find_governor(policy->last_governor);
+               if (gov) {
+                       pr_debug("Restoring governor %s for cpu %d\n",
                                policy->governor->name, policy->cpu);
+               } else {
+                       if (!def_gov)
+                               return -ENODATA;
+                       gov = def_gov;
+               }
+               new_policy.governor = gov;
        } else {
-               gov = cpufreq_default_governor();
-               if (!gov)
-                       return -ENODATA;
-       }
-
-       new_policy.governor = gov;
-
-       /* Use the default policy if there is no last_policy. */
-       if (cpufreq_driver->setpolicy) {
-               if (policy->last_policy)
+               /* Use the default policy if there is no last_policy. */
+               if (policy->last_policy) {
                        new_policy.policy = policy->last_policy;
-               else
-                       cpufreq_parse_governor(gov->name, &new_policy);
+               } else {
+                       if (!def_gov)
+                               return -ENODATA;
+                       cpufreq_parse_policy(def_gov->name, &new_policy);
+               }
        }
-       /* set default policy */
+
        return cpufreq_set_policy(policy, &new_policy);
 }
 
@@ -1133,6 +1148,11 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
                                   cpufreq_global_kobject, "policy%u", cpu);
        if (ret) {
                pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret);
+               /*
+                * The entire policy object will be freed below, but the extra
+                * memory allocated for the kobject name needs to be freed by
+                * releasing the kobject.
+                */
                kobject_put(&policy->kobj);
                goto err_free_real_cpus;
        }
index be89416..21c9ce8 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
index 3e23d4b..c0ece44 100644 (file)
@@ -89,6 +89,7 @@ struct caam_alg_entry {
        int class2_alg_type;
        bool rfc3686;
        bool geniv;
+       bool nodkp;
 };
 
 struct caam_aead_alg {
@@ -2052,6 +2053,7 @@ static struct caam_aead_alg driver_aeads[] = {
                },
                .caam = {
                        .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+                       .nodkp = true,
                },
        },
        {
@@ -2070,6 +2072,7 @@ static struct caam_aead_alg driver_aeads[] = {
                },
                .caam = {
                        .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+                       .nodkp = true,
                },
        },
        /* Galois Counter Mode */
@@ -2089,6 +2092,7 @@ static struct caam_aead_alg driver_aeads[] = {
                },
                .caam = {
                        .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+                       .nodkp = true,
                },
        },
        /* single-pass ipsec_esp descriptor */
@@ -3334,6 +3338,7 @@ static struct caam_aead_alg driver_aeads[] = {
                                           OP_ALG_AAI_AEAD,
                        .class2_alg_type = OP_ALG_ALGSEL_POLY1305 |
                                           OP_ALG_AAI_AEAD,
+                       .nodkp = true,
                },
        },
        {
@@ -3356,6 +3361,7 @@ static struct caam_aead_alg driver_aeads[] = {
                                           OP_ALG_AAI_AEAD,
                        .class2_alg_type = OP_ALG_ALGSEL_POLY1305 |
                                           OP_ALG_AAI_AEAD,
+                       .nodkp = true,
                },
        },
 };
@@ -3417,8 +3423,7 @@ static int caam_aead_init(struct crypto_aead *tfm)
                 container_of(alg, struct caam_aead_alg, aead);
        struct caam_ctx *ctx = crypto_aead_ctx(tfm);
 
-       return caam_init_common(ctx, &caam_alg->caam,
-                               alg->setkey == aead_setkey);
+       return caam_init_common(ctx, &caam_alg->caam, !caam_alg->caam.nodkp);
 }
 
 static void caam_exit_common(struct caam_ctx *ctx)
index 70af211..d290d6b 100644 (file)
@@ -36,6 +36,7 @@ struct caam_alg_entry {
        int class2_alg_type;
        bool rfc3686;
        bool geniv;
+       bool nodkp;
 };
 
 struct caam_aead_alg {
@@ -1523,6 +1524,7 @@ static struct caam_aead_alg driver_aeads[] = {
                },
                .caam = {
                        .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+                       .nodkp = true,
                },
        },
        {
@@ -1541,6 +1543,7 @@ static struct caam_aead_alg driver_aeads[] = {
                },
                .caam = {
                        .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+                       .nodkp = true,
                },
        },
        /* Galois Counter Mode */
@@ -1560,6 +1563,7 @@ static struct caam_aead_alg driver_aeads[] = {
                },
                .caam = {
                        .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+                       .nodkp = true,
                }
        },
        /* single-pass ipsec_esp descriptor */
@@ -2433,8 +2437,7 @@ static int caam_aead_init(struct crypto_aead *tfm)
                                                      aead);
        struct caam_ctx *ctx = crypto_aead_ctx(tfm);
 
-       return caam_init_common(ctx, &caam_alg->caam,
-                               alg->setkey == aead_setkey);
+       return caam_init_common(ctx, &caam_alg->caam, !caam_alg->caam.nodkp);
 }
 
 static void caam_exit_common(struct caam_ctx *ctx)
index 33a4df6..2b2980a 100644 (file)
@@ -42,6 +42,7 @@ struct caam_alg_entry {
        int class2_alg_type;
        bool rfc3686;
        bool geniv;
+       bool nodkp;
 };
 
 struct caam_aead_alg {
@@ -1480,7 +1481,7 @@ static int caam_cra_init_aead(struct crypto_aead *tfm)
 
        crypto_aead_set_reqsize(tfm, sizeof(struct caam_request));
        return caam_cra_init(crypto_aead_ctx(tfm), &caam_alg->caam,
-                            alg->setkey == aead_setkey);
+                            !caam_alg->caam.nodkp);
 }
 
 static void caam_exit_common(struct caam_ctx *ctx)
@@ -1641,6 +1642,7 @@ static struct caam_aead_alg driver_aeads[] = {
                },
                .caam = {
                        .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+                       .nodkp = true,
                },
        },
        {
@@ -1659,6 +1661,7 @@ static struct caam_aead_alg driver_aeads[] = {
                },
                .caam = {
                        .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+                       .nodkp = true,
                },
        },
        /* Galois Counter Mode */
@@ -1678,6 +1681,7 @@ static struct caam_aead_alg driver_aeads[] = {
                },
                .caam = {
                        .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+                       .nodkp = true,
                }
        },
        /* single-pass ipsec_esp descriptor */
@@ -2755,6 +2759,7 @@ static struct caam_aead_alg driver_aeads[] = {
                                           OP_ALG_AAI_AEAD,
                        .class2_alg_type = OP_ALG_ALGSEL_POLY1305 |
                                           OP_ALG_AAI_AEAD,
+                       .nodkp = true,
                },
        },
        {
@@ -2777,6 +2782,7 @@ static struct caam_aead_alg driver_aeads[] = {
                                           OP_ALG_AAI_AEAD,
                        .class2_alg_type = OP_ALG_ALGSEL_POLY1305 |
                                           OP_ALG_AAI_AEAD,
+                       .nodkp = true,
                },
        },
        {
index a4129a3..4da844e 100644 (file)
@@ -22,7 +22,7 @@ void caam_dump_sg(const char *level, const char *prefix_str, int prefix_type,
        size_t len;
        void *buf;
 
-       for (it = sg; it && tlen > 0 ; it = sg_next(sg)) {
+       for (it = sg; it && tlen > 0 ; it = sg_next(it)) {
                /*
                 * make sure the scatterlist's page
                 * has a valid virtual memory mapping
index 044a69b..1de2562 100644 (file)
@@ -213,7 +213,7 @@ static void caam_jr_dequeue(unsigned long devarg)
                mb();
 
                /* set done */
-               wr_reg32_relaxed(&jrp->rregs->outring_rmvd, 1);
+               wr_reg32(&jrp->rregs->outring_rmvd, 1);
 
                jrp->out_ring_read_index = (jrp->out_ring_read_index + 1) &
                                           (JOBR_DEPTH - 1);
index c1fa1ec..8591914 100644 (file)
@@ -96,14 +96,6 @@ cpu_to_caam(16)
 cpu_to_caam(32)
 cpu_to_caam(64)
 
-static inline void wr_reg32_relaxed(void __iomem *reg, u32 data)
-{
-       if (caam_little_end)
-               writel_relaxed(data, reg);
-       else
-               writel_relaxed(cpu_to_be32(data), reg);
-}
-
 static inline void wr_reg32(void __iomem *reg, u32 data)
 {
        if (caam_little_end)
index 8a76fce..177f572 100644 (file)
@@ -200,17 +200,10 @@ void chcr_verify_tag(struct aead_request *req, u8 *input, int *err)
 
 static int chcr_inc_wrcount(struct chcr_dev *dev)
 {
-       int err = 0;
-
-       spin_lock_bh(&dev->lock_chcr_dev);
        if (dev->state == CHCR_DETACH)
-               err = 1;
-       else
-               atomic_inc(&dev->inflight);
-
-       spin_unlock_bh(&dev->lock_chcr_dev);
-
-       return err;
+               return 1;
+       atomic_inc(&dev->inflight);
+       return 0;
 }
 
 static inline void chcr_dec_wrcount(struct chcr_dev *dev)
@@ -1101,8 +1094,8 @@ static int chcr_final_cipher_iv(struct ablkcipher_request *req,
        int ret = 0;
 
        if (subtype == CRYPTO_ALG_SUB_TYPE_CTR)
-               ctr_add_iv(iv, req->info, (reqctx->processed /
-                          AES_BLOCK_SIZE));
+               ctr_add_iv(iv, req->info, DIV_ROUND_UP(reqctx->processed,
+                                                      AES_BLOCK_SIZE));
        else if (subtype == CRYPTO_ALG_SUB_TYPE_XTS)
                ret = chcr_update_tweak(req, iv, 1);
        else if (subtype == CRYPTO_ALG_SUB_TYPE_CBC) {
index 239b933..029a735 100644 (file)
@@ -243,15 +243,11 @@ static void chcr_detach_device(struct uld_ctx *u_ctx)
 {
        struct chcr_dev *dev = &u_ctx->dev;
 
-       spin_lock_bh(&dev->lock_chcr_dev);
        if (dev->state == CHCR_DETACH) {
-               spin_unlock_bh(&dev->lock_chcr_dev);
                pr_debug("Detached Event received for already detach device\n");
                return;
        }
        dev->state = CHCR_DETACH;
-       spin_unlock_bh(&dev->lock_chcr_dev);
-
        if (atomic_read(&dev->inflight) != 0) {
                schedule_delayed_work(&dev->detach_work, WQ_DETACH_TM);
                wait_for_completion(&dev->detach_comp);
index 2f60049..f429aae 100644 (file)
@@ -575,7 +575,8 @@ inline void *chcr_crypto_wreq(struct sk_buff *skb,
        if (unlikely(credits < ETHTXQ_STOP_THRES)) {
                netif_tx_stop_queue(q->txq);
                q->q.stops++;
-               wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
+               if (!q->dbqt)
+                       wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
        }
        wr_mid |= FW_ULPTX_WR_DATA_F;
        wr->wreq.flowid_len16 = htonl(wr_mid);
index 9bbde2f..f5414b6 100644 (file)
@@ -30,8 +30,8 @@
 #include <crypto/authenc.h>
 #include <crypto/scatterwalk.h>
 
-#include <mach/npe.h>
-#include <mach/qmgr.h>
+#include <linux/soc/ixp4xx/npe.h>
+#include <linux/soc/ixp4xx/qmgr.h>
 
 #define MAX_KEYLEN 32
 
index 5ef624f..a59f338 100644 (file)
@@ -23,7 +23,6 @@ config DEV_DAX
 config DEV_DAX_PMEM
        tristate "PMEM DAX: direct access to persistent memory"
        depends on LIBNVDIMM && NVDIMM_DAX && DEV_DAX
-       depends on m # until we can kill DEV_DAX_PMEM_COMPAT
        default DEV_DAX
        help
          Support raw access to persistent memory.  Note that this
@@ -50,7 +49,7 @@ config DEV_DAX_KMEM
 
 config DEV_DAX_PMEM_COMPAT
        tristate "PMEM DAX: support the deprecated /sys/class/dax interface"
-       depends on DEV_DAX_PMEM
+       depends on m && DEV_DAX_PMEM=m
        default DEV_DAX_PMEM
        help
          Older versions of the libdaxctl library expect to find all
index e428468..996d68f 100644 (file)
@@ -184,8 +184,7 @@ static vm_fault_t __dev_dax_pmd_fault(struct dev_dax *dev_dax,
 
        *pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
 
-       return vmf_insert_pfn_pmd(vmf->vma, vmf->address, vmf->pmd, *pfn,
-                       vmf->flags & FAULT_FLAG_WRITE);
+       return vmf_insert_pfn_pmd(vmf, *pfn, vmf->flags & FAULT_FLAG_WRITE);
 }
 
 #ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
@@ -235,8 +234,7 @@ static vm_fault_t __dev_dax_pud_fault(struct dev_dax *dev_dax,
 
        *pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
 
-       return vmf_insert_pfn_pud(vmf->vma, vmf->address, vmf->pud, *pfn,
-                       vmf->flags & FAULT_FLAG_WRITE);
+       return vmf_insert_pfn_pud(vmf, *pfn, vmf->flags & FAULT_FLAG_WRITE);
 }
 #else
 static vm_fault_t __dev_dax_pud_fault(struct dev_dax *dev_dax,
index f71019c..f9f5178 100644 (file)
@@ -37,13 +37,13 @@ struct dev_dax *__dax_pmem_probe(struct device *dev, enum dev_dax_subsys subsys)
        devm_nsio_disable(dev, nsio);
 
        /* reserve the metadata area, device-dax will reserve the data */
-        pfn_sb = nd_pfn->pfn_sb;
+       pfn_sb = nd_pfn->pfn_sb;
        offset = le64_to_cpu(pfn_sb->dataoff);
        if (!devm_request_mem_region(dev, nsio->res.start, offset,
                                dev_name(&ndns->dev))) {
-                dev_warn(dev, "could not reserve metadata\n");
+               dev_warn(dev, "could not reserve metadata\n");
                return ERR_PTR(-EBUSY);
-        }
+       }
 
        rc = sscanf(dev_name(&ndns->dev), "namespace%d.%d", &region_id, &id);
        if (rc != 2)
index 3aa8733..9bf0604 100644 (file)
@@ -29,6 +29,7 @@
 
 EXPORT_TRACEPOINT_SYMBOL(dma_fence_emit);
 EXPORT_TRACEPOINT_SYMBOL(dma_fence_enable_signal);
+EXPORT_TRACEPOINT_SYMBOL(dma_fence_signaled);
 
 static DEFINE_SPINLOCK(dma_fence_stub_lock);
 static struct dma_fence dma_fence_stub;
index 47eb4d1..5e2e034 100644 (file)
@@ -263,8 +263,8 @@ config EDAC_PND2
          micro-server but may appear on others in the future.
 
 config EDAC_MPC85XX
-       tristate "Freescale MPC83xx / MPC85xx"
-       depends on FSL_SOC
+       bool "Freescale MPC83xx / MPC85xx"
+       depends on FSL_SOC && EDAC=y
        help
          Support for error detection and correction on the Freescale
          MPC8349, MPC8560, MPC8540, MPC8548, T4240
index 13594ff..64922c8 100644 (file)
@@ -679,22 +679,18 @@ static int del_mc_from_global_list(struct mem_ctl_info *mci)
 
 struct mem_ctl_info *edac_mc_find(int idx)
 {
-       struct mem_ctl_info *mci = NULL;
+       struct mem_ctl_info *mci;
        struct list_head *item;
 
        mutex_lock(&mem_ctls_mutex);
 
        list_for_each(item, &mc_devices) {
                mci = list_entry(item, struct mem_ctl_info, link);
-
-               if (mci->mc_idx >= idx) {
-                       if (mci->mc_idx == idx) {
-                               goto unlock;
-                       }
-                       break;
-               }
+               if (mci->mc_idx == idx)
+                       goto unlock;
        }
 
+       mci = NULL;
 unlock:
        mutex_unlock(&mem_ctls_mutex);
        return mci;
index 35e784c..5414eb1 100644 (file)
@@ -107,19 +107,8 @@ EXPORT_SYMBOL(fw_iso_buffer_init);
 int fw_iso_buffer_map_vma(struct fw_iso_buffer *buffer,
                          struct vm_area_struct *vma)
 {
-       unsigned long uaddr;
-       int i, err;
-
-       uaddr = vma->vm_start;
-       for (i = 0; i < buffer->page_count; i++) {
-               err = vm_insert_page(vma, uaddr, buffer->pages[i]);
-               if (err)
-                       return err;
-
-               uaddr += PAGE_SIZE;
-       }
-
-       return 0;
+       return vm_map_pages_zero(vma, buffer->pages,
+                                       buffer->page_count);
 }
 
 void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer,
index 7b655f6..11fda9e 100644 (file)
@@ -253,6 +253,22 @@ config TI_SCI_PROTOCOL
          This protocol library is used by client drivers to use the features
          provided by the system controller.
 
+config TRUSTED_FOUNDATIONS
+       bool "Trusted Foundations secure monitor support"
+       depends on ARM
+       help
+         Some devices (including most early Tegra-based consumer devices on
+         the market) are booted with the Trusted Foundations secure monitor
+         active, requiring some core operations to be performed by the secure
+         monitor instead of the kernel.
+
+         This option allows the kernel to invoke the secure monitor whenever
+         required on devices using Trusted Foundations. See the functions and
+         comments in linux/firmware/trusted_foundations.h or the device tree
+         bindings for "tlm,trusted-foundations" for details on how to use it.
+
+         Choose N if you don't know what this is about.
+
 config HAVE_ARM_SMCCC
        bool
 
index 9a3909a..3fa0b34 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_QCOM_SCM_64)     += qcom_scm-64.o
 obj-$(CONFIG_QCOM_SCM_32)      += qcom_scm-32.o
 CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
 obj-$(CONFIG_TI_SCI_PROTOCOL)  += ti_sci.o
+obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o
 
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)        += arm_scmi/
 obj-y                          += psci/
index 8f952f2..b5bc4c7 100644 (file)
@@ -654,9 +654,7 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
 
 static int scmi_mailbox_check(struct device_node *np)
 {
-       struct of_phandle_args arg;
-
-       return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, &arg);
+       return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, NULL);
 }
 
 static int scmi_mbox_free_channel(int id, void *p, void *data)
@@ -798,7 +796,9 @@ static int scmi_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       desc = of_match_device(scmi_of_match, dev)->data;
+       desc = of_device_get_match_data(dev);
+       if (!desc)
+               return -EINVAL;
 
        info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
        if (!info)
index 1b2e15b..802c4ad 100644 (file)
@@ -1,3 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_IMX_SCU)          += imx-scu.o misc.o
+obj-$(CONFIG_IMX_SCU)          += imx-scu.o misc.o imx-scu-irq.o
 obj-$(CONFIG_IMX_SCU_PD)       += scu-pd.o
diff --git a/drivers/firmware/imx/imx-scu-irq.c b/drivers/firmware/imx/imx-scu-irq.c
new file mode 100644 (file)
index 0000000..043833a
--- /dev/null
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ *
+ * Implementation of the SCU IRQ functions using MU.
+ *
+ */
+
+#include <dt-bindings/firmware/imx/rsrc.h>
+#include <linux/firmware/imx/ipc.h>
+#include <linux/mailbox_client.h>
+
+#define IMX_SC_IRQ_FUNC_ENABLE 1
+#define IMX_SC_IRQ_FUNC_STATUS 2
+#define IMX_SC_IRQ_NUM_GROUP   4
+
+static u32 mu_resource_id;
+
+struct imx_sc_msg_irq_get_status {
+       struct imx_sc_rpc_msg hdr;
+       union {
+               struct {
+                       u16 resource;
+                       u8 group;
+                       u8 reserved;
+               } __packed req;
+               struct {
+                       u32 status;
+               } resp;
+       } data;
+};
+
+struct imx_sc_msg_irq_enable {
+       struct imx_sc_rpc_msg hdr;
+       u32 mask;
+       u16 resource;
+       u8 group;
+       u8 enable;
+} __packed;
+
+static struct imx_sc_ipc *imx_sc_irq_ipc_handle;
+static struct work_struct imx_sc_irq_work;
+static ATOMIC_NOTIFIER_HEAD(imx_scu_irq_notifier_chain);
+
+int imx_scu_irq_register_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_register(
+               &imx_scu_irq_notifier_chain, nb);
+}
+EXPORT_SYMBOL(imx_scu_irq_register_notifier);
+
+int imx_scu_irq_unregister_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_unregister(
+               &imx_scu_irq_notifier_chain, nb);
+}
+EXPORT_SYMBOL(imx_scu_irq_unregister_notifier);
+
+static int imx_scu_irq_notifier_call_chain(unsigned long status, u8 *group)
+{
+       return atomic_notifier_call_chain(&imx_scu_irq_notifier_chain,
+               status, (void *)group);
+}
+
+static void imx_scu_irq_work_handler(struct work_struct *work)
+{
+       struct imx_sc_msg_irq_get_status msg;
+       struct imx_sc_rpc_msg *hdr = &msg.hdr;
+       u32 irq_status;
+       int ret;
+       u8 i;
+
+       for (i = 0; i < IMX_SC_IRQ_NUM_GROUP; i++) {
+               hdr->ver = IMX_SC_RPC_VERSION;
+               hdr->svc = IMX_SC_RPC_SVC_IRQ;
+               hdr->func = IMX_SC_IRQ_FUNC_STATUS;
+               hdr->size = 2;
+
+               msg.data.req.resource = mu_resource_id;
+               msg.data.req.group = i;
+
+               ret = imx_scu_call_rpc(imx_sc_irq_ipc_handle, &msg, true);
+               if (ret) {
+                       pr_err("get irq group %d status failed, ret %d\n",
+                              i, ret);
+                       return;
+               }
+
+               irq_status = msg.data.resp.status;
+               if (!irq_status)
+                       continue;
+
+               imx_scu_irq_notifier_call_chain(irq_status, &i);
+       }
+}
+
+int imx_scu_irq_group_enable(u8 group, u32 mask, u8 enable)
+{
+       struct imx_sc_msg_irq_enable msg;
+       struct imx_sc_rpc_msg *hdr = &msg.hdr;
+       int ret;
+
+       hdr->ver = IMX_SC_RPC_VERSION;
+       hdr->svc = IMX_SC_RPC_SVC_IRQ;
+       hdr->func = IMX_SC_IRQ_FUNC_ENABLE;
+       hdr->size = 3;
+
+       msg.resource = mu_resource_id;
+       msg.group = group;
+       msg.mask = mask;
+       msg.enable = enable;
+
+       ret = imx_scu_call_rpc(imx_sc_irq_ipc_handle, &msg, true);
+       if (ret)
+               pr_err("enable irq failed, group %d, mask %d, ret %d\n",
+                       group, mask, ret);
+
+       return ret;
+}
+EXPORT_SYMBOL(imx_scu_irq_group_enable);
+
+static void imx_scu_irq_callback(struct mbox_client *c, void *msg)
+{
+       schedule_work(&imx_sc_irq_work);
+}
+
+int imx_scu_enable_general_irq_channel(struct device *dev)
+{
+       struct of_phandle_args spec;
+       struct mbox_client *cl;
+       struct mbox_chan *ch;
+       int ret = 0, i = 0;
+
+       ret = imx_scu_get_handle(&imx_sc_irq_ipc_handle);
+       if (ret)
+               return ret;
+
+       cl = devm_kzalloc(dev, sizeof(*cl), GFP_KERNEL);
+       if (!cl)
+               return -ENOMEM;
+
+       cl->dev = dev;
+       cl->rx_callback = imx_scu_irq_callback;
+
+       /* SCU general IRQ uses general interrupt channel 3 */
+       ch = mbox_request_channel_byname(cl, "gip3");
+       if (IS_ERR(ch)) {
+               ret = PTR_ERR(ch);
+               dev_err(dev, "failed to request mbox chan gip3, ret %d\n", ret);
+               devm_kfree(dev, cl);
+               return ret;
+       }
+
+       INIT_WORK(&imx_sc_irq_work, imx_scu_irq_work_handler);
+
+       if (!of_parse_phandle_with_args(dev->of_node, "mboxes",
+                                      "#mbox-cells", 0, &spec))
+               i = of_alias_get_id(spec.np, "mu");
+
+       /* use mu1 as general mu irq channel if failed */
+       if (i < 0)
+               i = 1;
+
+       mu_resource_id = IMX_SC_R_MU_0A + i;
+
+       return ret;
+}
+EXPORT_SYMBOL(imx_scu_enable_general_irq_channel);
index 2bb1a19..04a24a8 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/err.h>
 #include <linux/firmware/imx/types.h>
 #include <linux/firmware/imx/ipc.h>
+#include <linux/firmware/imx/sci.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
@@ -246,6 +247,11 @@ static int imx_scu_probe(struct platform_device *pdev)
 
        imx_sc_ipc_handle = sc_ipc;
 
+       ret = imx_scu_enable_general_irq_channel(dev);
+       if (ret)
+               dev_warn(dev,
+                       "failed to enable general irq channel: %d\n", ret);
+
        dev_info(dev, "NXP i.MX SCU Initialized\n");
 
        return devm_of_platform_populate(dev);
index 39a94c7..480cec6 100644 (file)
@@ -74,7 +74,10 @@ struct imx_sc_pd_range {
        char *name;
        u32 rsrc;
        u8 num;
+
+       /* add domain index */
        bool postfix;
+       u8 start_from;
 };
 
 struct imx_sc_pd_soc {
@@ -84,71 +87,75 @@ struct imx_sc_pd_soc {
 
 static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
        /* LSIO SS */
-       { "lsio-pwm", IMX_SC_R_PWM_0, 8, 1 },
-       { "lsio-gpio", IMX_SC_R_GPIO_0, 8, 1 },
-       { "lsio-gpt", IMX_SC_R_GPT_0, 5, 1 },
-       { "lsio-kpp", IMX_SC_R_KPP, 1, 0 },
-       { "lsio-fspi", IMX_SC_R_FSPI_0, 2, 1 },
-       { "lsio-mu", IMX_SC_R_MU_0A, 14, 1 },
+       { "pwm", IMX_SC_R_PWM_0, 8, true, 0 },
+       { "gpio", IMX_SC_R_GPIO_0, 8, true, 0 },
+       { "gpt", IMX_SC_R_GPT_0, 5, true, 0 },
+       { "kpp", IMX_SC_R_KPP, 1, false, 0 },
+       { "fspi", IMX_SC_R_FSPI_0, 2, true, 0 },
+       { "mu", IMX_SC_R_MU_0A, 14, true, 0 },
 
        /* CONN SS */
-       { "con-usb", IMX_SC_R_USB_0, 2, 1 },
-       { "con-usb0phy", IMX_SC_R_USB_0_PHY, 1, 0 },
-       { "con-usb2", IMX_SC_R_USB_2, 1, 0 },
-       { "con-usb2phy", IMX_SC_R_USB_2_PHY, 1, 0 },
-       { "con-sdhc", IMX_SC_R_SDHC_0, 3, 1 },
-       { "con-enet", IMX_SC_R_ENET_0, 2, 1 },
-       { "con-nand", IMX_SC_R_NAND, 1, 0 },
-       { "con-mlb", IMX_SC_R_MLB_0, 1, 1 },
-
-       /* Audio DMA SS */
-       { "adma-audio-pll0", IMX_SC_R_AUDIO_PLL_0, 1, 0 },
-       { "adma-audio-pll1", IMX_SC_R_AUDIO_PLL_1, 1, 0 },
-       { "adma-audio-clk-0", IMX_SC_R_AUDIO_CLK_0, 1, 0 },
-       { "adma-dma0-ch", IMX_SC_R_DMA_0_CH0, 16, 1 },
-       { "adma-dma1-ch", IMX_SC_R_DMA_1_CH0, 16, 1 },
-       { "adma-dma2-ch", IMX_SC_R_DMA_2_CH0, 5, 1 },
-       { "adma-asrc0", IMX_SC_R_ASRC_0, 1, 0 },
-       { "adma-asrc1", IMX_SC_R_ASRC_1, 1, 0 },
-       { "adma-esai0", IMX_SC_R_ESAI_0, 1, 0 },
-       { "adma-spdif0", IMX_SC_R_SPDIF_0, 1, 0 },
-       { "adma-sai", IMX_SC_R_SAI_0, 3, 1 },
-       { "adma-amix", IMX_SC_R_AMIX, 1, 0 },
-       { "adma-mqs0", IMX_SC_R_MQS_0, 1, 0 },
-       { "adma-dsp", IMX_SC_R_DSP, 1, 0 },
-       { "adma-dsp-ram", IMX_SC_R_DSP_RAM, 1, 0 },
-       { "adma-can", IMX_SC_R_CAN_0, 3, 1 },
-       { "adma-ftm", IMX_SC_R_FTM_0, 2, 1 },
-       { "adma-lpi2c", IMX_SC_R_I2C_0, 4, 1 },
-       { "adma-adc", IMX_SC_R_ADC_0, 1, 1 },
-       { "adma-lcd", IMX_SC_R_LCD_0, 1, 1 },
-       { "adma-lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, 1 },
-       { "adma-lpuart", IMX_SC_R_UART_0, 4, 1 },
-       { "adma-lpspi", IMX_SC_R_SPI_0, 4, 1 },
-
-       /* VPU SS  */
-       { "vpu", IMX_SC_R_VPU, 1, 0 },
-       { "vpu-pid", IMX_SC_R_VPU_PID0, 8, 1 },
-       { "vpu-dec0", IMX_SC_R_VPU_DEC_0, 1, 0 },
-       { "vpu-enc0", IMX_SC_R_VPU_ENC_0, 1, 0 },
+       { "usb", IMX_SC_R_USB_0, 2, true, 0 },
+       { "usb0phy", IMX_SC_R_USB_0_PHY, 1, false, 0 },
+       { "usb2", IMX_SC_R_USB_2, 1, false, 0 },
+       { "usb2phy", IMX_SC_R_USB_2_PHY, 1, false, 0 },
+       { "sdhc", IMX_SC_R_SDHC_0, 3, true, 0 },
+       { "enet", IMX_SC_R_ENET_0, 2, true, 0 },
+       { "nand", IMX_SC_R_NAND, 1, false, 0 },
+       { "mlb", IMX_SC_R_MLB_0, 1, true, 0 },
+
+       /* AUDIO SS */
+       { "audio-pll0", IMX_SC_R_AUDIO_PLL_0, 1, false, 0 },
+       { "audio-pll1", IMX_SC_R_AUDIO_PLL_1, 1, false, 0 },
+       { "audio-clk-0", IMX_SC_R_AUDIO_CLK_0, 1, false, 0 },
+       { "dma0-ch", IMX_SC_R_DMA_0_CH0, 16, true, 0 },
+       { "dma1-ch", IMX_SC_R_DMA_1_CH0, 16, true, 0 },
+       { "dma2-ch", IMX_SC_R_DMA_2_CH0, 5, true, 0 },
+       { "asrc0", IMX_SC_R_ASRC_0, 1, false, 0 },
+       { "asrc1", IMX_SC_R_ASRC_1, 1, false, 0 },
+       { "esai0", IMX_SC_R_ESAI_0, 1, false, 0 },
+       { "spdif0", IMX_SC_R_SPDIF_0, 1, false, 0 },
+       { "sai", IMX_SC_R_SAI_0, 3, true, 0 },
+       { "amix", IMX_SC_R_AMIX, 1, false, 0 },
+       { "mqs0", IMX_SC_R_MQS_0, 1, false, 0 },
+       { "dsp", IMX_SC_R_DSP, 1, false, 0 },
+       { "dsp-ram", IMX_SC_R_DSP_RAM, 1, false, 0 },
+
+       /* DMA SS */
+       { "can", IMX_SC_R_CAN_0, 3, true, 0 },
+       { "ftm", IMX_SC_R_FTM_0, 2, true, 0 },
+       { "lpi2c", IMX_SC_R_I2C_0, 4, true, 0 },
+       { "adc", IMX_SC_R_ADC_0, 1, true, 0 },
+       { "lcd", IMX_SC_R_LCD_0, 1, true, 0 },
+       { "lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, true, 0 },
+       { "lpuart", IMX_SC_R_UART_0, 4, true, 0 },
+       { "lpspi", IMX_SC_R_SPI_0, 4, true, 0 },
+
+       /* VPU SS */
+       { "vpu", IMX_SC_R_VPU, 1, false, 0 },
+       { "vpu-pid", IMX_SC_R_VPU_PID0, 8, true, 0 },
+       { "vpu-dec0", IMX_SC_R_VPU_DEC_0, 1, false, 0 },
+       { "vpu-enc0", IMX_SC_R_VPU_ENC_0, 1, false, 0 },
 
        /* GPU SS */
-       { "gpu0-pid", IMX_SC_R_GPU_0_PID0, 4, 1 },
+       { "gpu0-pid", IMX_SC_R_GPU_0_PID0, 4, true, 0 },
 
        /* HSIO SS */
-       { "hsio-pcie-b", IMX_SC_R_PCIE_B, 1, 0 },
-       { "hsio-serdes-1", IMX_SC_R_SERDES_1, 1, 0 },
-       { "hsio-gpio", IMX_SC_R_HSIO_GPIO, 1, 0 },
+       { "pcie-b", IMX_SC_R_PCIE_B, 1, false, 0 },
+       { "serdes-1", IMX_SC_R_SERDES_1, 1, false, 0 },
+       { "hsio-gpio", IMX_SC_R_HSIO_GPIO, 1, false, 0 },
+
+       /* MIPI SS */
+       { "mipi0", IMX_SC_R_MIPI_0, 1, false, 0 },
+       { "mipi0-pwm0", IMX_SC_R_MIPI_0_PWM_0, 1, false, 0 },
+       { "mipi0-i2c", IMX_SC_R_MIPI_0_I2C_0, 2, true, 0 },
 
-       /* MIPI/LVDS SS */
-       { "mipi0", IMX_SC_R_MIPI_0, 1, 0 },
-       { "mipi0-pwm0", IMX_SC_R_MIPI_0_PWM_0, 1, 0 },
-       { "mipi0-i2c", IMX_SC_R_MIPI_0_I2C_0, 2, 1 },
-       { "lvds0", IMX_SC_R_LVDS_0, 1, 0 },
+       /* LVDS SS */
+       { "lvds0", IMX_SC_R_LVDS_0, 1, false, 0 },
 
        /* DC SS */
-       { "dc0", IMX_SC_R_DC_0, 1, 0 },
-       { "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, 1 },
+       { "dc0", IMX_SC_R_DC_0, 1, false, 0 },
+       { "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, true, 0 },
 };
 
 static const struct imx_sc_pd_soc imx8qxp_scu_pd = {
@@ -236,7 +243,7 @@ imx_scu_add_pm_domain(struct device *dev, int idx,
 
        if (pd_ranges->postfix)
                snprintf(sc_pd->name, sizeof(sc_pd->name),
-                        "%s%i", pd_ranges->name, idx);
+                        "%s%i", pd_ranges->name, pd_ranges->start_from + idx);
        else
                snprintf(sc_pd->name, sizeof(sc_pd->name),
                         "%s", pd_ranges->name);
diff --git a/drivers/firmware/trusted_foundations.c b/drivers/firmware/trusted_foundations.c
new file mode 100644 (file)
index 0000000..fd49993
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Trusted Foundations support for ARM CPUs
+ *
+ * Copyright (c) 2013, NVIDIA 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of.h>
+
+#include <linux/firmware/trusted_foundations.h>
+
+#include <asm/firmware.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/outercache.h>
+
+#define TF_CACHE_MAINT         0xfffff100
+
+#define TF_CACHE_ENABLE                1
+#define TF_CACHE_DISABLE       2
+
+#define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200
+
+#define TF_CPU_PM              0xfffffffc
+#define TF_CPU_PM_S3           0xffffffe3
+#define TF_CPU_PM_S2           0xffffffe6
+#define TF_CPU_PM_S2_NO_MC_CLK 0xffffffe5
+#define TF_CPU_PM_S1           0xffffffe4
+#define TF_CPU_PM_S1_NOFLUSH_L2        0xffffffe7
+
+static unsigned long cpu_boot_addr;
+
+static void tf_generic_smc(u32 type, u32 arg1, u32 arg2)
+{
+       register u32 r0 asm("r0") = type;
+       register u32 r1 asm("r1") = arg1;
+       register u32 r2 asm("r2") = arg2;
+
+       asm volatile(
+               ".arch_extension        sec\n\t"
+               "stmfd  sp!, {r4 - r11}\n\t"
+               __asmeq("%0", "r0")
+               __asmeq("%1", "r1")
+               __asmeq("%2", "r2")
+               "mov    r3, #0\n\t"
+               "mov    r4, #0\n\t"
+               "smc    #0\n\t"
+               "ldmfd  sp!, {r4 - r11}\n\t"
+               :
+               : "r" (r0), "r" (r1), "r" (r2)
+               : "memory", "r3", "r12", "lr");
+}
+
+static int tf_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
+{
+       cpu_boot_addr = boot_addr;
+       tf_generic_smc(TF_SET_CPU_BOOT_ADDR_SMC, cpu_boot_addr, 0);
+
+       return 0;
+}
+
+static int tf_prepare_idle(unsigned long mode)
+{
+       switch (mode) {
+       case TF_PM_MODE_LP0:
+               tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S3, cpu_boot_addr);
+               break;
+
+       case TF_PM_MODE_LP1:
+               tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S2, cpu_boot_addr);
+               break;
+
+       case TF_PM_MODE_LP1_NO_MC_CLK:
+               tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S2_NO_MC_CLK,
+                              cpu_boot_addr);
+               break;
+
+       case TF_PM_MODE_LP2:
+               tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1, cpu_boot_addr);
+               break;
+
+       case TF_PM_MODE_LP2_NOFLUSH_L2:
+               tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1_NOFLUSH_L2,
+                              cpu_boot_addr);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_CACHE_L2X0
+static void tf_cache_write_sec(unsigned long val, unsigned int reg)
+{
+       u32 l2x0_way_mask = 0xff;
+
+       switch (reg) {
+       case L2X0_CTRL:
+               if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_ASSOCIATIVITY_16)
+                       l2x0_way_mask = 0xffff;
+
+               if (val == L2X0_CTRL_EN)
+                       tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_ENABLE,
+                                      l2x0_saved_regs.aux_ctrl);
+               else
+                       tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_DISABLE,
+                                      l2x0_way_mask);
+               break;
+
+       default:
+               break;
+       }
+}
+
+static int tf_init_cache(void)
+{
+       outer_cache.write_sec = tf_cache_write_sec;
+
+       return 0;
+}
+#endif /* CONFIG_CACHE_L2X0 */
+
+static const struct firmware_ops trusted_foundations_ops = {
+       .set_cpu_boot_addr = tf_set_cpu_boot_addr,
+       .prepare_idle = tf_prepare_idle,
+#ifdef CONFIG_CACHE_L2X0
+       .l2x0_init = tf_init_cache,
+#endif
+};
+
+void register_trusted_foundations(struct trusted_foundations_platform_data *pd)
+{
+       /*
+        * we are not using version information for now since currently
+        * supported SMCs are compatible with all TF releases
+        */
+       register_firmware_ops(&trusted_foundations_ops);
+}
+
+void of_register_trusted_foundations(void)
+{
+       struct device_node *node;
+       struct trusted_foundations_platform_data pdata;
+       int err;
+
+       node = of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations");
+       if (!node)
+               return;
+
+       err = of_property_read_u32(node, "tlm,version-major",
+                                  &pdata.version_major);
+       if (err != 0)
+               panic("Trusted Foundation: missing version-major property\n");
+       err = of_property_read_u32(node, "tlm,version-minor",
+                                  &pdata.version_minor);
+       if (err != 0)
+               panic("Trusted Foundation: missing version-minor property\n");
+       register_trusted_foundations(&pdata);
+}
+
+bool trusted_foundations_registered(void)
+{
+       return firmware_ops == &trusted_foundations_ops;
+}
index 2771df6..c6d0724 100644 (file)
@@ -90,9 +90,6 @@ static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret)
        int ret;
        struct zynqmp_pm_query_data qdata = {0};
 
-       if (!eemi_ops)
-               return -ENXIO;
-
        switch (pm_id) {
        case PM_GET_API_VERSION:
                ret = eemi_ops->get_api_version(&pm_api_version);
@@ -163,21 +160,14 @@ static ssize_t zynqmp_pm_debugfs_api_write(struct file *file,
 
        strcpy(debugfs_buf, "");
 
-       if (*off != 0 || len == 0)
+       if (*off != 0 || len <= 1 || len > PAGE_SIZE - 1)
                return -EINVAL;
 
-       kern_buff = kzalloc(len, GFP_KERNEL);
-       if (!kern_buff)
-               return -ENOMEM;
-
+       kern_buff = memdup_user_nul(ptr, len);
+       if (IS_ERR(kern_buff))
+               return PTR_ERR(kern_buff);
        tmp_buff = kern_buff;
 
-       ret = strncpy_from_user(kern_buff, ptr, len);
-       if (ret < 0) {
-               ret = -EFAULT;
-               goto err;
-       }
-
        /* Read the API name from a user request */
        pm_api_req = strsep(&kern_buff, " ");
 
index 98f9361..fd3d837 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/firmware/xlnx-zynqmp.h>
 #include "zynqmp-debug.h"
 
+static const struct zynqmp_eemi_ops *eemi_ops_tbl;
+
 static const struct mfd_cell firmware_devs[] = {
        {
                .name = "zynqmp_power_controller",
@@ -537,6 +539,49 @@ static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,
        return ret;
 }
 
+/**
+ * zynqmp_pm_fpga_load - Perform the fpga load
+ * @address:   Address to write to
+ * @size:      pl bitstream size
+ * @flags:     Bitstream type
+ *     -XILINX_ZYNQMP_PM_FPGA_FULL:  FPGA full reconfiguration
+ *     -XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
+ *
+ * This function provides access to pmufw. To transfer
+ * the required bitstream into PL.
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_fpga_load(const u64 address, const u32 size,
+                              const u32 flags)
+{
+       return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
+                                  upper_32_bits(address), size, flags, NULL);
+}
+
+/**
+ * zynqmp_pm_fpga_get_status - Read value from PCAP status register
+ * @value: Value to read
+ *
+ * This function provides access to the pmufw to get the PCAP
+ * status
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_fpga_get_status(u32 *value)
+{
+       u32 ret_payload[PAYLOAD_ARG_CNT];
+       int ret;
+
+       if (!value)
+               return -EINVAL;
+
+       ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
+       *value = ret_payload[1];
+
+       return ret;
+}
+
 /**
  * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
  *                            master has initialized its own power management
@@ -640,6 +685,8 @@ static const struct zynqmp_eemi_ops eemi_ops = {
        .request_node = zynqmp_pm_request_node,
        .release_node = zynqmp_pm_release_node,
        .set_requirement = zynqmp_pm_set_requirement,
+       .fpga_load = zynqmp_pm_fpga_load,
+       .fpga_get_status = zynqmp_pm_fpga_get_status,
 };
 
 /**
@@ -649,7 +696,11 @@ static const struct zynqmp_eemi_ops eemi_ops = {
  */
 const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void)
 {
-       return &eemi_ops;
+       if (eemi_ops_tbl)
+               return eemi_ops_tbl;
+       else
+               return ERR_PTR(-EPROBE_DEFER);
+
 }
 EXPORT_SYMBOL_GPL(zynqmp_pm_get_eemi_ops);
 
@@ -694,6 +745,9 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
        pr_info("%s Trustzone version v%d.%d\n", __func__,
                pm_tz_version >> 16, pm_tz_version & 0xFFFF);
 
+       /* Assign eemi_ops_table */
+       eemi_ops_tbl = &eemi_ops;
+
        zynqmp_pm_api_debugfs_init();
 
        ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
index c20445b..d892f3e 100644 (file)
@@ -204,4 +204,13 @@ config FPGA_DFL_PCI
 
          To compile this as a module, choose M here.
 
+config FPGA_MGR_ZYNQMP_FPGA
+       tristate "Xilinx ZynqMP FPGA"
+       depends on ARCH_ZYNQMP || COMPILE_TEST
+       help
+         FPGA manager driver support for Xilinx ZynqMP FPGAs.
+         This driver uses the processor configuration port(PCAP)
+         to configure the programmable logic(PL) through PS
+         on ZynqMP SoC.
+
 endif # FPGA
index c0dd4c8..312b937 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_FPGA_MGR_STRATIX10_SOC)  += stratix10-soc.o
 obj-$(CONFIG_FPGA_MGR_TS73XX)          += ts73xx-fpga.o
 obj-$(CONFIG_FPGA_MGR_XILINX_SPI)      += xilinx-spi.o
 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)       += zynq-fpga.o
+obj-$(CONFIG_FPGA_MGR_ZYNQMP_FPGA)     += zynqmp-fpga.o
 obj-$(CONFIG_ALTERA_PR_IP_CORE)         += altera-pr-ip-core.o
 obj-$(CONFIG_ALTERA_PR_IP_CORE_PLAT)    += altera-pr-ip-core-plat.o
 
index e18a786..c438722 100644 (file)
@@ -102,7 +102,7 @@ static int afu_dma_pin_pages(struct dfl_feature_platform_data *pdata,
                goto unlock_vm;
        }
 
-       pinned = get_user_pages_fast(region->user_addr, npages, 1,
+       pinned = get_user_pages_fast(region->user_addr, npages, FOLL_WRITE,
                                     region->pages);
        if (pinned < 0) {
                ret = pinned;
diff --git a/drivers/fpga/zynqmp-fpga.c b/drivers/fpga/zynqmp-fpga.c
new file mode 100644 (file)
index 0000000..f7cbaad
--- /dev/null
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Xilinx, Inc.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/string.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+
+/* Constant Definitions */
+#define IXR_FPGA_DONE_MASK     BIT(3)
+
+/**
+ * struct zynqmp_fpga_priv - Private data structure
+ * @dev:       Device data structure
+ * @flags:     flags which is used to identify the bitfile type
+ */
+struct zynqmp_fpga_priv {
+       struct device *dev;
+       u32 flags;
+};
+
+static int zynqmp_fpga_ops_write_init(struct fpga_manager *mgr,
+                                     struct fpga_image_info *info,
+                                     const char *buf, size_t size)
+{
+       struct zynqmp_fpga_priv *priv;
+
+       priv = mgr->priv;
+       priv->flags = info->flags;
+
+       return 0;
+}
+
+static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
+                                const char *buf, size_t size)
+{
+       const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+       struct zynqmp_fpga_priv *priv;
+       dma_addr_t dma_addr;
+       u32 eemi_flags = 0;
+       char *kbuf;
+       int ret;
+
+       if (!eemi_ops || !eemi_ops->fpga_load)
+               return -ENXIO;
+
+       priv = mgr->priv;
+
+       kbuf = dma_alloc_coherent(priv->dev, size, &dma_addr, GFP_KERNEL);
+       if (!kbuf)
+               return -ENOMEM;
+
+       memcpy(kbuf, buf, size);
+
+       wmb(); /* ensure all writes are done before initiate FW call */
+
+       if (priv->flags & FPGA_MGR_PARTIAL_RECONFIG)
+               eemi_flags |= XILINX_ZYNQMP_PM_FPGA_PARTIAL;
+
+       ret = eemi_ops->fpga_load(dma_addr, size, eemi_flags);
+
+       dma_free_coherent(priv->dev, size, kbuf, dma_addr);
+
+       return ret;
+}
+
+static int zynqmp_fpga_ops_write_complete(struct fpga_manager *mgr,
+                                         struct fpga_image_info *info)
+{
+       return 0;
+}
+
+static enum fpga_mgr_states zynqmp_fpga_ops_state(struct fpga_manager *mgr)
+{
+       const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+       u32 status;
+
+       if (!eemi_ops || !eemi_ops->fpga_get_status)
+               return FPGA_MGR_STATE_UNKNOWN;
+
+       eemi_ops->fpga_get_status(&status);
+       if (status & IXR_FPGA_DONE_MASK)
+               return FPGA_MGR_STATE_OPERATING;
+
+       return FPGA_MGR_STATE_UNKNOWN;
+}
+
+static const struct fpga_manager_ops zynqmp_fpga_ops = {
+       .state = zynqmp_fpga_ops_state,
+       .write_init = zynqmp_fpga_ops_write_init,
+       .write = zynqmp_fpga_ops_write,
+       .write_complete = zynqmp_fpga_ops_write_complete,
+};
+
+static int zynqmp_fpga_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct zynqmp_fpga_priv *priv;
+       struct fpga_manager *mgr;
+       int ret;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->dev = dev;
+
+       mgr = devm_fpga_mgr_create(dev, "Xilinx ZynqMP FPGA Manager",
+                                  &zynqmp_fpga_ops, priv);
+       if (!mgr)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, mgr);
+
+       ret = fpga_mgr_register(mgr);
+       if (ret) {
+               dev_err(dev, "unable to register FPGA manager");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int zynqmp_fpga_remove(struct platform_device *pdev)
+{
+       struct fpga_manager *mgr = platform_get_drvdata(pdev);
+
+       fpga_mgr_unregister(mgr);
+
+       return 0;
+}
+
+static const struct of_device_id zynqmp_fpga_of_match[] = {
+       { .compatible = "xlnx,zynqmp-pcap-fpga", },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, zynqmp_fpga_of_match);
+
+static struct platform_driver zynqmp_fpga_driver = {
+       .probe = zynqmp_fpga_probe,
+       .remove = zynqmp_fpga_remove,
+       .driver = {
+               .name = "zynqmp_fpga_manager",
+               .of_match_table = of_match_ptr(zynqmp_fpga_of_match),
+       },
+};
+
+module_platform_driver(zynqmp_fpga_driver);
+
+MODULE_AUTHOR("Nava kishore Manne <navam@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx ZynqMp FPGA Manager");
+MODULE_LICENSE("GPL");
index 9370276..8023d03 100644 (file)
@@ -286,6 +286,19 @@ config GPIO_IOP
 
          If unsure, say N.
 
+config GPIO_IXP4XX
+       bool "Intel IXP4xx GPIO"
+       depends on ARM # For <asm/mach-types.h>
+       depends on ARCH_IXP4XX
+       select GPIO_GENERIC
+       select IRQ_DOMAIN
+       select IRQ_DOMAIN_HIERARCHY
+       help
+         Say yes here to support the GPIO functionality of a number of Intel
+         IXP4xx series of chips.
+
+         If unsure, say N.
+
 config GPIO_LOONGSON
        bool "Loongson-2/3 GPIO support"
        depends on CPU_LOONGSON2 || CPU_LOONGSON3
@@ -1097,6 +1110,13 @@ config GPIO_MAX77620
          driver also provides interrupt support for each of the gpios.
          Say yes here to enable the max77620 to be used as gpio controller.
 
+config GPIO_MAX77650
+       tristate "Maxim MAX77650/77651 GPIO support"
+       depends on MFD_MAX77650
+       help
+         GPIO driver for MAX77650/77651 PMIC from Maxim Semiconductor.
+         These chips have a single pin that can be configured as GPIO.
+
 config GPIO_MSIC
        bool "Intel MSIC mixed signal gpio support"
        depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC
index db8d854..6700eee 100644 (file)
@@ -61,6 +61,7 @@ obj-$(CONFIG_GPIO_HLWD)               += gpio-hlwd.o
 obj-$(CONFIG_HTC_EGPIO)                += gpio-htc-egpio.o
 obj-$(CONFIG_GPIO_ICH)         += gpio-ich.o
 obj-$(CONFIG_GPIO_IOP)         += gpio-iop.o
+obj-$(CONFIG_GPIO_IXP4XX)      += gpio-ixp4xx.o
 obj-$(CONFIG_GPIO_IT87)                += gpio-it87.o
 obj-$(CONFIG_GPIO_JANZ_TTL)    += gpio-janz-ttl.o
 obj-$(CONFIG_GPIO_KEMPLD)      += gpio-kempld.o
@@ -80,6 +81,7 @@ obj-$(CONFIG_GPIO_MAX7300)    += gpio-max7300.o
 obj-$(CONFIG_GPIO_MAX7301)     += gpio-max7301.o
 obj-$(CONFIG_GPIO_MAX732X)     += gpio-max732x.o
 obj-$(CONFIG_GPIO_MAX77620)    += gpio-max77620.o
+obj-$(CONFIG_GPIO_MAX77650)    += gpio-max77650.o
 obj-$(CONFIG_GPIO_MB86S7X)     += gpio-mb86s7x.o
 obj-$(CONFIG_GPIO_MENZ127)     += gpio-menz127.o
 obj-$(CONFIG_GPIO_MERRIFIELD)  += gpio-merrifield.o
diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c
new file mode 100644 (file)
index 0000000..4b1cf7e
--- /dev/null
@@ -0,0 +1,474 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// IXP4 GPIO driver
+// Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
+//
+// based on previous work and know-how from:
+// Deepak Saxena <dsaxena@plexity.net>
+
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+/* Include that go away with DT transition */
+#include <linux/irqchip/irq-ixp4xx.h>
+
+#include <asm/mach-types.h>
+
+#define IXP4XX_REG_GPOUT       0x00
+#define IXP4XX_REG_GPOE                0x04
+#define IXP4XX_REG_GPIN                0x08
+#define IXP4XX_REG_GPIS                0x0C
+#define IXP4XX_REG_GPIT1       0x10
+#define IXP4XX_REG_GPIT2       0x14
+#define IXP4XX_REG_GPCLK       0x18
+#define IXP4XX_REG_GPDBSEL     0x1C
+
+/*
+ * The hardware uses 3 bits to indicate interrupt "style".
+ * we clear and set these three bits accordingly. The lower 24
+ * bits in two registers (GPIT1 and GPIT2) are used to set up
+ * the style for 8 lines each for a total of 16 GPIO lines.
+ */
+#define IXP4XX_GPIO_STYLE_ACTIVE_HIGH  0x0
+#define IXP4XX_GPIO_STYLE_ACTIVE_LOW   0x1
+#define IXP4XX_GPIO_STYLE_RISING_EDGE  0x2
+#define IXP4XX_GPIO_STYLE_FALLING_EDGE 0x3
+#define IXP4XX_GPIO_STYLE_TRANSITIONAL 0x4
+#define IXP4XX_GPIO_STYLE_MASK         GENMASK(2, 0)
+#define IXP4XX_GPIO_STYLE_SIZE         3
+
+/**
+ * struct ixp4xx_gpio - IXP4 GPIO state container
+ * @dev: containing device for this instance
+ * @fwnode: the fwnode for this GPIO chip
+ * @gc: gpiochip for this instance
+ * @domain: irqdomain for this chip instance
+ * @base: remapped I/O-memory base
+ * @irq_edge: Each bit represents an IRQ: 1: edge-triggered,
+ * 0: level triggered
+ */
+struct ixp4xx_gpio {
+       struct device *dev;
+       struct fwnode_handle *fwnode;
+       struct gpio_chip gc;
+       struct irq_domain *domain;
+       void __iomem *base;
+       unsigned long long irq_edge;
+};
+
+/**
+ * struct ixp4xx_gpio_map - IXP4 GPIO to parent IRQ map
+ * @gpio_offset: offset of the IXP4 GPIO line
+ * @parent_hwirq: hwirq on the parent IRQ controller
+ */
+struct ixp4xx_gpio_map {
+       int gpio_offset;
+       int parent_hwirq;
+};
+
+/* GPIO lines 0..12 have corresponding IRQs, GPIOs 13..15 have no IRQs */
+const struct ixp4xx_gpio_map ixp4xx_gpiomap[] = {
+       { .gpio_offset = 0, .parent_hwirq = 6 },
+       { .gpio_offset = 1, .parent_hwirq = 7 },
+       { .gpio_offset = 2, .parent_hwirq = 19 },
+       { .gpio_offset = 3, .parent_hwirq = 20 },
+       { .gpio_offset = 4, .parent_hwirq = 21 },
+       { .gpio_offset = 5, .parent_hwirq = 22 },
+       { .gpio_offset = 6, .parent_hwirq = 23 },
+       { .gpio_offset = 7, .parent_hwirq = 24 },
+       { .gpio_offset = 8, .parent_hwirq = 25 },
+       { .gpio_offset = 9, .parent_hwirq = 26 },
+       { .gpio_offset = 10, .parent_hwirq = 27 },
+       { .gpio_offset = 11, .parent_hwirq = 28 },
+       { .gpio_offset = 12, .parent_hwirq = 29 },
+};
+
+static void ixp4xx_gpio_irq_ack(struct irq_data *d)
+{
+       struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
+
+       __raw_writel(BIT(d->hwirq), g->base + IXP4XX_REG_GPIS);
+}
+
+static void ixp4xx_gpio_irq_unmask(struct irq_data *d)
+{
+       struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
+
+       /* ACK when unmasking if not edge-triggered */
+       if (!(g->irq_edge & BIT(d->hwirq)))
+               ixp4xx_gpio_irq_ack(d);
+
+       irq_chip_unmask_parent(d);
+}
+
+static int ixp4xx_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
+       int line = d->hwirq;
+       unsigned long flags;
+       u32 int_style;
+       u32 int_reg;
+       u32 val;
+
+       switch (type) {
+       case IRQ_TYPE_EDGE_BOTH:
+               irq_set_handler_locked(d, handle_edge_irq);
+               int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
+               g->irq_edge |= BIT(d->hwirq);
+               break;
+       case IRQ_TYPE_EDGE_RISING:
+               irq_set_handler_locked(d, handle_edge_irq);
+               int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
+               g->irq_edge |= BIT(d->hwirq);
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               irq_set_handler_locked(d, handle_edge_irq);
+               int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
+               g->irq_edge |= BIT(d->hwirq);
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:
+               irq_set_handler_locked(d, handle_level_irq);
+               int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
+               g->irq_edge &= ~BIT(d->hwirq);
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               irq_set_handler_locked(d, handle_level_irq);
+               int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
+               g->irq_edge &= ~BIT(d->hwirq);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (line >= 8) {
+               /* pins 8-15 */
+               line -= 8;
+               int_reg = IXP4XX_REG_GPIT2;
+       } else {
+               /* pins 0-7 */
+               int_reg = IXP4XX_REG_GPIT1;
+       }
+
+       spin_lock_irqsave(&g->gc.bgpio_lock, flags);
+
+       /* Clear the style for the appropriate pin */
+       val = __raw_readl(g->base + int_reg);
+       val &= ~(IXP4XX_GPIO_STYLE_MASK << (line * IXP4XX_GPIO_STYLE_SIZE));
+       __raw_writel(val, g->base + int_reg);
+
+       __raw_writel(BIT(line), g->base + IXP4XX_REG_GPIS);
+
+       /* Set the new style */
+       val = __raw_readl(g->base + int_reg);
+       val |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
+       __raw_writel(val, g->base + int_reg);
+
+       /* Force-configure this line as an input */
+       val = __raw_readl(g->base + IXP4XX_REG_GPOE);
+       val |= BIT(d->hwirq);
+       __raw_writel(val, g->base + IXP4XX_REG_GPOE);
+
+       spin_unlock_irqrestore(&g->gc.bgpio_lock, flags);
+
+       /* This parent only accept level high (asserted) */
+       return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
+}
+
+static struct irq_chip ixp4xx_gpio_irqchip = {
+       .name = "IXP4GPIO",
+       .irq_ack = ixp4xx_gpio_irq_ack,
+       .irq_mask = irq_chip_mask_parent,
+       .irq_unmask = ixp4xx_gpio_irq_unmask,
+       .irq_set_type = ixp4xx_gpio_irq_set_type,
+};
+
+static int ixp4xx_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
+{
+       struct ixp4xx_gpio *g = gpiochip_get_data(gc);
+       struct irq_fwspec fwspec;
+
+       fwspec.fwnode = g->fwnode;
+       fwspec.param_count = 2;
+       fwspec.param[0] = offset;
+       fwspec.param[1] = IRQ_TYPE_NONE;
+
+       return irq_create_fwspec_mapping(&fwspec);
+}
+
+static int ixp4xx_gpio_irq_domain_translate(struct irq_domain *domain,
+                                           struct irq_fwspec *fwspec,
+                                           unsigned long *hwirq,
+                                           unsigned int *type)
+{
+
+       /* We support standard DT translation */
+       if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) {
+               *hwirq = fwspec->param[0];
+               *type = fwspec->param[1];
+               return 0;
+       }
+
+       /* This goes away when we transition to DT */
+       if (is_fwnode_irqchip(fwspec->fwnode)) {
+               if (fwspec->param_count != 2)
+                       return -EINVAL;
+               *hwirq = fwspec->param[0];
+               *type = fwspec->param[1];
+               WARN_ON(*type == IRQ_TYPE_NONE);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int ixp4xx_gpio_irq_domain_alloc(struct irq_domain *d,
+                                       unsigned int irq, unsigned int nr_irqs,
+                                       void *data)
+{
+       struct ixp4xx_gpio *g = d->host_data;
+       irq_hw_number_t hwirq;
+       unsigned int type = IRQ_TYPE_NONE;
+       struct irq_fwspec *fwspec = data;
+       int ret;
+       int i;
+
+       ret = ixp4xx_gpio_irq_domain_translate(d, fwspec, &hwirq, &type);
+       if (ret)
+               return ret;
+
+       dev_dbg(g->dev, "allocate IRQ %d..%d, hwirq %lu..%lu\n",
+               irq, irq + nr_irqs - 1,
+               hwirq, hwirq + nr_irqs - 1);
+
+       for (i = 0; i < nr_irqs; i++) {
+               struct irq_fwspec parent_fwspec;
+               const struct ixp4xx_gpio_map *map;
+               int j;
+
+               /* Not all lines support IRQs */
+               for (j = 0; j < ARRAY_SIZE(ixp4xx_gpiomap); j++) {
+                       map = &ixp4xx_gpiomap[j];
+                       if (map->gpio_offset == hwirq)
+                               break;
+               }
+               if (j == ARRAY_SIZE(ixp4xx_gpiomap)) {
+                       dev_err(g->dev, "can't look up hwirq %lu\n", hwirq);
+                       return -EINVAL;
+               }
+               dev_dbg(g->dev, "found parent hwirq %u\n", map->parent_hwirq);
+
+               /*
+                * We set handle_bad_irq because the .set_type() should
+                * always be invoked and set the right type of handler.
+                */
+               irq_domain_set_info(d,
+                                   irq + i,
+                                   hwirq + i,
+                                   &ixp4xx_gpio_irqchip,
+                                   g,
+                                   handle_bad_irq,
+                                   NULL, NULL);
+               irq_set_probe(irq + i);
+
+               /*
+                * Create a IRQ fwspec to send up to the parent irqdomain:
+                * specify the hwirq we address on the parent and tie it
+                * all together up the chain.
+                */
+               parent_fwspec.fwnode = d->parent->fwnode;
+               parent_fwspec.param_count = 2;
+               parent_fwspec.param[0] = map->parent_hwirq;
+               /* This parent only handles asserted level IRQs */
+               parent_fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
+               dev_dbg(g->dev, "alloc_irqs_parent for %d parent hwirq %d\n",
+                       irq + i, map->parent_hwirq);
+               ret = irq_domain_alloc_irqs_parent(d, irq + i, 1,
+                                                  &parent_fwspec);
+               if (ret)
+                       dev_err(g->dev,
+                               "failed to allocate parent hwirq %d for hwirq %lu\n",
+                               map->parent_hwirq, hwirq);
+       }
+
+       return 0;
+}
+
+static const struct irq_domain_ops ixp4xx_gpio_irqdomain_ops = {
+       .translate = ixp4xx_gpio_irq_domain_translate,
+       .alloc = ixp4xx_gpio_irq_domain_alloc,
+       .free = irq_domain_free_irqs_common,
+};
+
+static int ixp4xx_gpio_probe(struct platform_device *pdev)
+{
+       unsigned long flags;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct irq_domain *parent;
+       struct resource *res;
+       struct ixp4xx_gpio *g;
+       int ret;
+       int i;
+
+       g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
+       if (!g)
+               return -ENOMEM;
+       g->dev = dev;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       g->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(g->base)) {
+               dev_err(dev, "ioremap error\n");
+               return PTR_ERR(g->base);
+       }
+
+       /*
+        * Make sure GPIO 14 and 15 are NOT used as clocks but GPIO on
+        * specific machines.
+        */
+       if (machine_is_dsmg600() || machine_is_nas100d())
+               __raw_writel(0x0, g->base + IXP4XX_REG_GPCLK);
+
+       /*
+        * This is a very special big-endian ARM issue: when the IXP4xx is
+        * run in big endian mode, all registers in the machine are switched
+        * around to the CPU-native endianness. As you see mostly in the
+        * driver we use __raw_readl()/__raw_writel() to access the registers
+        * in the appropriate order. With the GPIO library we need to specify
+        * byte order explicitly, so this flag needs to be set when compiling
+        * for big endian.
+        */
+#if defined(CONFIG_CPU_BIG_ENDIAN)
+       flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
+#else
+       flags = 0;
+#endif
+
+       /* Populate and register gpio chip */
+       ret = bgpio_init(&g->gc, dev, 4,
+                        g->base + IXP4XX_REG_GPIN,
+                        g->base + IXP4XX_REG_GPOUT,
+                        NULL,
+                        NULL,
+                        g->base + IXP4XX_REG_GPOE,
+                        flags);
+       if (ret) {
+               dev_err(dev, "unable to init generic GPIO\n");
+               return ret;
+       }
+       g->gc.to_irq = ixp4xx_gpio_to_irq;
+       g->gc.ngpio = 16;
+       g->gc.label = "IXP4XX_GPIO_CHIP";
+       /*
+        * TODO: when we have migrated to device tree and all GPIOs
+        * are fetched using phandles, set this to -1 to get rid of
+        * the fixed gpiochip base.
+        */
+       g->gc.base = 0;
+       g->gc.parent = &pdev->dev;
+       g->gc.owner = THIS_MODULE;
+
+       ret = devm_gpiochip_add_data(dev, &g->gc, g);
+       if (ret) {
+               dev_err(dev, "failed to add SoC gpiochip\n");
+               return ret;
+       }
+
+       /*
+        * When we convert to device tree we will simply look up the
+        * parent irqdomain using irq_find_host(parent) as parent comes
+        * from IRQCHIP_DECLARE(), then use of_node_to_fwnode() to get
+        * the fwnode. For now we need this boardfile style code.
+        */
+       if (np) {
+               struct device_node *irq_parent;
+
+               irq_parent = of_irq_find_parent(np);
+               if (!irq_parent) {
+                       dev_err(dev, "no IRQ parent node\n");
+                       return -ENODEV;
+               }
+               parent = irq_find_host(irq_parent);
+               if (!parent) {
+                       dev_err(dev, "no IRQ parent domain\n");
+                       return -ENODEV;
+               }
+               g->fwnode = of_node_to_fwnode(np);
+       } else {
+               parent = ixp4xx_get_irq_domain();
+               g->fwnode = irq_domain_alloc_fwnode(g->base);
+               if (!g->fwnode) {
+                       dev_err(dev, "no domain base\n");
+                       return -ENODEV;
+               }
+       }
+       g->domain = irq_domain_create_hierarchy(parent,
+                                               IRQ_DOMAIN_FLAG_HIERARCHY,
+                                               ARRAY_SIZE(ixp4xx_gpiomap),
+                                               g->fwnode,
+                                               &ixp4xx_gpio_irqdomain_ops,
+                                               g);
+       if (!g->domain) {
+               irq_domain_free_fwnode(g->fwnode);
+               dev_err(dev, "no hierarchical irq domain\n");
+               return ret;
+       }
+
+       /*
+        * After adding OF support, this is no longer needed: irqs
+        * will be allocated for the respective fwnodes.
+        */
+       if (!np) {
+               for (i = 0; i < ARRAY_SIZE(ixp4xx_gpiomap); i++) {
+                       const struct ixp4xx_gpio_map *map = &ixp4xx_gpiomap[i];
+                       struct irq_fwspec fwspec;
+
+                       fwspec.fwnode = g->fwnode;
+                       /* This is the hwirq for the GPIO line side of things */
+                       fwspec.param[0] = map->gpio_offset;
+                       fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+                       fwspec.param_count = 2;
+                       ret = __irq_domain_alloc_irqs(g->domain,
+                                                     -1, /* just pick something */
+                                                     1,
+                                                     NUMA_NO_NODE,
+                                                     &fwspec,
+                                                     false,
+                                                     NULL);
+                       if (ret < 0) {
+                               irq_domain_free_fwnode(g->fwnode);
+                               dev_err(dev,
+                                       "can not allocate irq for GPIO line %d parent hwirq %d in hierarchy domain: %d\n",
+                                       map->gpio_offset, map->parent_hwirq,
+                                       ret);
+                               return ret;
+                       }
+               }
+       }
+
+       platform_set_drvdata(pdev, g);
+       dev_info(dev, "IXP4 GPIO @%p registered\n", g->base);
+
+       return 0;
+}
+
+static const struct of_device_id ixp4xx_gpio_of_match[] = {
+       {
+               .compatible = "intel,ixp4xx-gpio",
+       },
+       {},
+};
+
+
+static struct platform_driver ixp4xx_gpio_driver = {
+       .driver = {
+               .name           = "ixp4xx-gpio",
+               .of_match_table = of_match_ptr(ixp4xx_gpio_of_match),
+       },
+       .probe = ixp4xx_gpio_probe,
+};
+builtin_platform_driver(ixp4xx_gpio_driver);
diff --git a/drivers/gpio/gpio-max77650.c b/drivers/gpio/gpio-max77650.c
new file mode 100644 (file)
index 0000000..3f03f4e
--- /dev/null
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// GPIO driver for MAXIM 77650/77651 charger/power-supply.
+
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/mfd/max77650.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define MAX77650_GPIO_DIR_MASK         BIT(0)
+#define MAX77650_GPIO_INVAL_MASK       BIT(1)
+#define MAX77650_GPIO_DRV_MASK         BIT(2)
+#define MAX77650_GPIO_OUTVAL_MASK      BIT(3)
+#define MAX77650_GPIO_DEBOUNCE_MASK    BIT(4)
+
+#define MAX77650_GPIO_DIR_OUT          0x00
+#define MAX77650_GPIO_DIR_IN           BIT(0)
+#define MAX77650_GPIO_OUT_LOW          0x00
+#define MAX77650_GPIO_OUT_HIGH         BIT(3)
+#define MAX77650_GPIO_DRV_OPEN_DRAIN   0x00
+#define MAX77650_GPIO_DRV_PUSH_PULL    BIT(2)
+#define MAX77650_GPIO_DEBOUNCE         BIT(4)
+
+#define MAX77650_GPIO_DIR_BITS(_reg) \
+               ((_reg) & MAX77650_GPIO_DIR_MASK)
+#define MAX77650_GPIO_INVAL_BITS(_reg) \
+               (((_reg) & MAX77650_GPIO_INVAL_MASK) >> 1)
+
+struct max77650_gpio_chip {
+       struct regmap *map;
+       struct gpio_chip gc;
+       int irq;
+};
+
+static int max77650_gpio_direction_input(struct gpio_chip *gc,
+                                        unsigned int offset)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+
+       return regmap_update_bits(chip->map,
+                                 MAX77650_REG_CNFG_GPIO,
+                                 MAX77650_GPIO_DIR_MASK,
+                                 MAX77650_GPIO_DIR_IN);
+}
+
+static int max77650_gpio_direction_output(struct gpio_chip *gc,
+                                         unsigned int offset, int value)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+       int mask, regval;
+
+       mask = MAX77650_GPIO_DIR_MASK | MAX77650_GPIO_OUTVAL_MASK;
+       regval = value ? MAX77650_GPIO_OUT_HIGH : MAX77650_GPIO_OUT_LOW;
+       regval |= MAX77650_GPIO_DIR_OUT;
+
+       return regmap_update_bits(chip->map,
+                                 MAX77650_REG_CNFG_GPIO, mask, regval);
+}
+
+static void max77650_gpio_set_value(struct gpio_chip *gc,
+                                   unsigned int offset, int value)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+       int rv, regval;
+
+       regval = value ? MAX77650_GPIO_OUT_HIGH : MAX77650_GPIO_OUT_LOW;
+
+       rv = regmap_update_bits(chip->map, MAX77650_REG_CNFG_GPIO,
+                               MAX77650_GPIO_OUTVAL_MASK, regval);
+       if (rv)
+               dev_err(gc->parent, "cannot set GPIO value: %d\n", rv);
+}
+
+static int max77650_gpio_get_value(struct gpio_chip *gc,
+                                  unsigned int offset)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+       unsigned int val;
+       int rv;
+
+       rv = regmap_read(chip->map, MAX77650_REG_CNFG_GPIO, &val);
+       if (rv)
+               return rv;
+
+       return MAX77650_GPIO_INVAL_BITS(val);
+}
+
+static int max77650_gpio_get_direction(struct gpio_chip *gc,
+                                      unsigned int offset)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+       unsigned int val;
+       int rv;
+
+       rv = regmap_read(chip->map, MAX77650_REG_CNFG_GPIO, &val);
+       if (rv)
+               return rv;
+
+       return MAX77650_GPIO_DIR_BITS(val);
+}
+
+static int max77650_gpio_set_config(struct gpio_chip *gc,
+                                   unsigned int offset, unsigned long cfg)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+
+       switch (pinconf_to_config_param(cfg)) {
+       case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+               return regmap_update_bits(chip->map,
+                                         MAX77650_REG_CNFG_GPIO,
+                                         MAX77650_GPIO_DRV_MASK,
+                                         MAX77650_GPIO_DRV_OPEN_DRAIN);
+       case PIN_CONFIG_DRIVE_PUSH_PULL:
+               return regmap_update_bits(chip->map,
+                                         MAX77650_REG_CNFG_GPIO,
+                                         MAX77650_GPIO_DRV_MASK,
+                                         MAX77650_GPIO_DRV_PUSH_PULL);
+       case PIN_CONFIG_INPUT_DEBOUNCE:
+               return regmap_update_bits(chip->map,
+                                         MAX77650_REG_CNFG_GPIO,
+                                         MAX77650_GPIO_DEBOUNCE_MASK,
+                                         MAX77650_GPIO_DEBOUNCE);
+       default:
+               return -ENOTSUPP;
+       }
+}
+
+static int max77650_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
+{
+       struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
+
+       return chip->irq;
+}
+
+static int max77650_gpio_probe(struct platform_device *pdev)
+{
+       struct max77650_gpio_chip *chip;
+       struct device *dev, *parent;
+       struct i2c_client *i2c;
+
+       dev = &pdev->dev;
+       parent = dev->parent;
+       i2c = to_i2c_client(parent);
+
+       chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       chip->map = dev_get_regmap(parent, NULL);
+       if (!chip->map)
+               return -ENODEV;
+
+       chip->irq = platform_get_irq_byname(pdev, "GPI");
+       if (chip->irq < 0)
+               return chip->irq;
+
+       chip->gc.base = -1;
+       chip->gc.ngpio = 1;
+       chip->gc.label = i2c->name;
+       chip->gc.parent = dev;
+       chip->gc.owner = THIS_MODULE;
+       chip->gc.can_sleep = true;
+
+       chip->gc.direction_input = max77650_gpio_direction_input;
+       chip->gc.direction_output = max77650_gpio_direction_output;
+       chip->gc.set = max77650_gpio_set_value;
+       chip->gc.get = max77650_gpio_get_value;
+       chip->gc.get_direction = max77650_gpio_get_direction;
+       chip->gc.set_config = max77650_gpio_set_config;
+       chip->gc.to_irq = max77650_gpio_to_irq;
+
+       return devm_gpiochip_add_data(dev, &chip->gc, chip);
+}
+
+static struct platform_driver max77650_gpio_driver = {
+       .driver = {
+               .name = "max77650-gpio",
+       },
+       .probe = max77650_gpio_probe,
+};
+module_platform_driver(max77650_gpio_driver);
+
+MODULE_DESCRIPTION("MAXIM 77650/77651 GPIO driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL v2");
index 2267e84..e360a4a 100644 (file)
@@ -200,7 +200,6 @@ config DRM_RADEON
        select POWER_SUPPLY
        select HWMON
        select BACKLIGHT_CLASS_DEVICE
-       select BACKLIGHT_LCD_SUPPORT
        select INTERVAL_TREE
        help
          Choose this option if you have an ATI Radeon graphics card.  There
@@ -221,7 +220,6 @@ config DRM_AMDGPU
        select POWER_SUPPLY
        select HWMON
        select BACKLIGHT_CLASS_DEVICE
-       select BACKLIGHT_LCD_SUPPORT
        select INTERVAL_TREE
        select CHASH
        help
index 4376b17..56f8ca2 100644 (file)
@@ -464,8 +464,7 @@ static int amdgpu_atif_handler(struct amdgpu_device *adev,
                        }
                }
                if (req.pending & ATIF_DGPU_DISPLAY_EVENT) {
-                       if ((adev->flags & AMD_IS_PX) &&
-                           amdgpu_atpx_dgpu_req_power_for_displays()) {
+                       if (adev->flags & AMD_IS_PX) {
                                pm_runtime_get_sync(adev->ddev->dev);
                                /* Just fire off a uevent and let userspace tell us what to do */
                                drm_helper_hpd_irq_event(adev->ddev);
index 3e6823f..58ed401 100644 (file)
@@ -256,14 +256,14 @@ static int amdgpu_mn_invalidate_range_start_gfx(struct mmu_notifier *mn,
        /* TODO we should be able to split locking for interval tree and
         * amdgpu_mn_invalidate_node
         */
-       if (amdgpu_mn_read_lock(amn, range->blockable))
+       if (amdgpu_mn_read_lock(amn, mmu_notifier_range_blockable(range)))
                return -EAGAIN;
 
        it = interval_tree_iter_first(&amn->objects, range->start, end);
        while (it) {
                struct amdgpu_mn_node *node;
 
-               if (!range->blockable) {
+               if (!mmu_notifier_range_blockable(range)) {
                        amdgpu_mn_read_unlock(amn);
                        return -EAGAIN;
                }
@@ -299,7 +299,7 @@ static int amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn,
        /* notification is exclusive, but interval is inclusive */
        end = range->end - 1;
 
-       if (amdgpu_mn_read_lock(amn, range->blockable))
+       if (amdgpu_mn_read_lock(amn, mmu_notifier_range_blockable(range)))
                return -EAGAIN;
 
        it = interval_tree_iter_first(&amn->objects, range->start, end);
@@ -307,7 +307,7 @@ static int amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn,
                struct amdgpu_mn_node *node;
                struct amdgpu_bo *bo;
 
-               if (!range->blockable) {
+               if (!mmu_notifier_range_blockable(range)) {
                        amdgpu_mn_read_unlock(amn);
                        return -EAGAIN;
                }
index 95144e4..34471db 100644 (file)
@@ -342,6 +342,16 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
        if (current_level == level)
                return count;
 
+       /* profile_exit setting is valid only when current mode is in profile mode */
+       if (!(current_level & (AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
+           AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
+           AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
+           AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)) &&
+           (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) {
+               pr_err("Currently not in any profile mode!\n");
+               return -EINVAL;
+       }
+
        if (is_support_sw_smu(adev)) {
                mutex_lock(&adev->pm.mutex);
                if (adev->pm.dpm.thermal_active) {
index 905cce1..05897b0 100644 (file)
@@ -38,18 +38,10 @@ static void psp_set_funcs(struct amdgpu_device *adev);
 static int psp_early_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       struct psp_context *psp = &adev->psp;
 
        psp_set_funcs(adev);
 
-       return 0;
-}
-
-static int psp_sw_init(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct psp_context *psp = &adev->psp;
-       int ret;
-
        switch (adev->asic_type) {
        case CHIP_VEGA10:
        case CHIP_VEGA12:
@@ -67,6 +59,15 @@ static int psp_sw_init(void *handle)
 
        psp->adev = adev;
 
+       return 0;
+}
+
+static int psp_sw_init(void *handle)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       struct psp_context *psp = &adev->psp;
+       int ret;
+
        ret = psp_init_microcode(psp);
        if (ret) {
                DRM_ERROR("Failed to load psp firmware!\n");
index a07c858..4f10f5a 100644 (file)
@@ -2756,6 +2756,37 @@ error_free_sched_entity:
        return r;
 }
 
+/**
+ * amdgpu_vm_check_clean_reserved - check if a VM is clean
+ *
+ * @adev: amdgpu_device pointer
+ * @vm: the VM to check
+ *
+ * check all entries of the root PD, if any subsequent PDs are allocated,
+ * it means there are page table creating and filling, and is no a clean
+ * VM
+ *
+ * Returns:
+ *     0 if this VM is clean
+ */
+static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev,
+       struct amdgpu_vm *vm)
+{
+       enum amdgpu_vm_level root = adev->vm_manager.root_level;
+       unsigned int entries = amdgpu_vm_num_entries(adev, root);
+       unsigned int i = 0;
+
+       if (!(vm->root.entries))
+               return 0;
+
+       for (i = 0; i < entries; i++) {
+               if (vm->root.entries[i].base.bo)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 /**
  * amdgpu_vm_make_compute - Turn a GFX VM into a compute VM
  *
@@ -2786,10 +2817,9 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, uns
                return r;
 
        /* Sanity checks */
-       if (!RB_EMPTY_ROOT(&vm->va.rb_root) || vm->root.entries) {
-               r = -EINVAL;
+       r = amdgpu_vm_check_clean_reserved(adev, vm);
+       if (r)
                goto unreserve_bo;
-       }
 
        if (pasid) {
                unsigned long flags;
index 8dbad49..2471e7c 100644 (file)
@@ -372,6 +372,9 @@ static int xgpu_ai_mailbox_rcv_irq(struct amdgpu_device *adev,
                if (amdgpu_sriov_runtime(adev))
                        schedule_work(&adev->virt.flr_work);
                break;
+               case IDH_QUERY_ALIVE:
+                       xgpu_ai_mailbox_send_ack(adev);
+                       break;
                /* READY_TO_ACCESS_GPU is fetched by kernel polling, IRQ can ignore
                 * it byfar since that polling thread will handle it,
                 * other msg like flr complete is not handled here.
index 39d151b..077e91a 100644 (file)
@@ -49,6 +49,7 @@ enum idh_event {
        IDH_FLR_NOTIFICATION_CMPL,
        IDH_SUCCESS,
        IDH_FAIL,
+       IDH_QUERY_ALIVE,
        IDH_EVENT_MAX
 };
 
index dc461df..2191d3d 100644 (file)
@@ -787,10 +787,13 @@ static int uvd_v7_0_sriov_start(struct amdgpu_device *adev)
                                                           0xFFFFFFFF, 0x00000004);
                        /* mc resume*/
                        if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
-                               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
-                                                           lower_32_bits(adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].mc_addr));
-                               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
-                                                           upper_32_bits(adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].mc_addr));
+                               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, i,
+                                                       mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
+                                                       adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].tmr_mc_addr_lo);
+                               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, i,
+                                                       mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
+                                                       adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].tmr_mc_addr_hi);
+                               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0), 0);
                                offset = 0;
                        } else {
                                MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
@@ -798,10 +801,11 @@ static int uvd_v7_0_sriov_start(struct amdgpu_device *adev)
                                MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
                                                            upper_32_bits(adev->uvd.inst[i].gpu_addr));
                                offset = size;
+                               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0),
+                                                       AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
+
                        }
 
-                       MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_OFFSET0),
-                                                   AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
                        MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_SIZE0), size);
 
                        MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, i, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW),
index f3f5938..c0ec279 100644 (file)
@@ -244,13 +244,18 @@ static int vce_v4_0_sriov_start(struct amdgpu_device *adev)
                MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_SWAP_CNTL1), 0);
                MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VM_CTRL), 0);
 
+               offset = AMDGPU_VCE_FIRMWARE_OFFSET;
                if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+                       uint32_t low = adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].tmr_mc_addr_lo;
+                       uint32_t hi = adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].tmr_mc_addr_hi;
+                       uint64_t tmr_mc_addr = (uint64_t)(hi) << 32 | low;
+
                        MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0,
-                                               mmVCE_LMI_VCPU_CACHE_40BIT_BAR0),
-                                               adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 8);
+                                               mmVCE_LMI_VCPU_CACHE_40BIT_BAR0), tmr_mc_addr >> 8);
                        MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0,
                                                mmVCE_LMI_VCPU_CACHE_64BIT_BAR0),
-                                               (adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 40) & 0xff);
+                                               (tmr_mc_addr >> 40) & 0xff);
+                       MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET0), 0);
                } else {
                        MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0,
                                                mmVCE_LMI_VCPU_CACHE_40BIT_BAR0),
@@ -258,6 +263,9 @@ static int vce_v4_0_sriov_start(struct amdgpu_device *adev)
                        MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0,
                                                mmVCE_LMI_VCPU_CACHE_64BIT_BAR0),
                                                (adev->vce.gpu_addr >> 40) & 0xff);
+                       MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET0),
+                                               offset & ~0x0f000000);
+
                }
                MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0,
                                                mmVCE_LMI_VCPU_CACHE_40BIT_BAR1),
@@ -272,10 +280,7 @@ static int vce_v4_0_sriov_start(struct amdgpu_device *adev)
                                                mmVCE_LMI_VCPU_CACHE_64BIT_BAR2),
                                                (adev->vce.gpu_addr >> 40) & 0xff);
 
-               offset = AMDGPU_VCE_FIRMWARE_OFFSET;
                size = VCE_V4_0_FW_SIZE;
-               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET0),
-                                       offset & ~0x0f000000);
                MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_SIZE0), size);
 
                offset = (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) ? offset + size : 0;
index 1b2f69a..8d89ab7 100644 (file)
@@ -31,7 +31,7 @@
 #include "soc15_common.h"
 #include "vega10_ih.h"
 
-
+#define MAX_REARM_RETRY 10
 
 static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev);
 
@@ -381,6 +381,38 @@ static void vega10_ih_decode_iv(struct amdgpu_device *adev,
        ih->rptr += 32;
 }
 
+/**
+ * vega10_ih_irq_rearm - rearm IRQ if lost
+ *
+ * @adev: amdgpu_device pointer
+ *
+ */
+static void vega10_ih_irq_rearm(struct amdgpu_device *adev,
+                              struct amdgpu_ih_ring *ih)
+{
+       uint32_t reg_rptr = 0;
+       uint32_t v = 0;
+       uint32_t i = 0;
+
+       if (ih == &adev->irq.ih)
+               reg_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR);
+       else if (ih == &adev->irq.ih1)
+               reg_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR_RING1);
+       else if (ih == &adev->irq.ih2)
+               reg_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR_RING2);
+       else
+               return;
+
+       /* Rearm IRQ / re-wwrite doorbell if doorbell write is lost */
+       for (i = 0; i < MAX_REARM_RETRY; i++) {
+               v = RREG32_NO_KIQ(reg_rptr);
+               if ((v < ih->ring_size) && (v != ih->rptr))
+                       WDOORBELL32(ih->doorbell_index, ih->rptr);
+               else
+                       break;
+       }
+}
+
 /**
  * vega10_ih_set_rptr - set the IH ring buffer rptr
  *
@@ -395,6 +427,9 @@ static void vega10_ih_set_rptr(struct amdgpu_device *adev,
                /* XXX check if swapping is necessary on BE */
                *ih->rptr_cpu = ih->rptr;
                WDOORBELL32(ih->doorbell_index, ih->rptr);
+
+               if (amdgpu_sriov_vf(adev))
+                       vega10_ih_irq_rearm(adev, ih);
        } else if (ih == &adev->irq.ih) {
                WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, ih->rptr);
        } else if (ih == &adev->irq.ih1) {
index 2cb09e0..769dbc7 100644 (file)
@@ -1272,8 +1272,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
 
        dev->node_props.vendor_id = gpu->pdev->vendor;
        dev->node_props.device_id = gpu->pdev->device;
-       dev->node_props.location_id = PCI_DEVID(gpu->pdev->bus->number,
-               gpu->pdev->devfn);
+       dev->node_props.location_id = pci_dev_id(gpu->pdev);
        dev->node_props.max_engine_clk_fcompute =
                amdgpu_amdkfd_get_max_engine_clock_in_mhz(dev->gpu->kgd);
        dev->node_props.max_engine_clk_ccompute =
index 1854506..995f9df 100644 (file)
@@ -5242,7 +5242,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                                    struct drm_crtc *pcrtc,
                                    bool wait_for_vblank)
 {
-       uint32_t i, r;
+       uint32_t i;
        uint64_t timestamp_ns;
        struct drm_plane *plane;
        struct drm_plane_state *old_plane_state, *new_plane_state;
@@ -5253,6 +5253,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
        struct dm_crtc_state *dm_old_crtc_state =
                        to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc));
        int planes_count = 0, vpos, hpos;
+       long r;
        unsigned long flags;
        struct amdgpu_bo *abo;
        uint64_t tiling_flags;
index 8840f39..3dff999 100644 (file)
@@ -76,7 +76,6 @@ config DRM_PARADE_PS8622
        depends on OF
        select DRM_PANEL
        select DRM_KMS_HELPER
-       select BACKLIGHT_LCD_SUPPORT
        select BACKLIGHT_CLASS_DEVICE
        ---help---
          Parade eDP-LVDS bridge chip driver.
index ec2ca71..c532e9c 100644 (file)
@@ -748,11 +748,11 @@ static void adv7511_mode_set(struct adv7511 *adv7511,
                        vsync_polarity = 1;
        }
 
-       if (mode->vrefresh <= 24000)
+       if (drm_mode_vrefresh(mode) <= 24)
                low_refresh_rate = ADV7511_LOW_REFRESH_RATE_24HZ;
-       else if (mode->vrefresh <= 25000)
+       else if (drm_mode_vrefresh(mode) <= 25)
                low_refresh_rate = ADV7511_LOW_REFRESH_RATE_25HZ;
-       else if (mode->vrefresh <= 30000)
+       else if (drm_mode_vrefresh(mode) <= 30)
                low_refresh_rate = ADV7511_LOW_REFRESH_RATE_30HZ;
        else
                low_refresh_rate = ADV7511_LOW_REFRESH_RATE_NONE;
index 14a72c4..dc82588 100644 (file)
@@ -2,7 +2,6 @@ config DRM_FSL_DCU
        tristate "DRM Support for Freescale DCU"
        depends on DRM && OF && ARM && COMMON_CLK
        select BACKLIGHT_CLASS_DEVICE
-       select BACKLIGHT_LCD_SUPPORT
        select DRM_KMS_HELPER
        select DRM_KMS_CMA_HELPER
        select DRM_PANEL
index 148be8e..3d5f1cb 100644 (file)
@@ -15,7 +15,6 @@ config DRM_I915
        select IRQ_WORK
        # i915 depends on ACPI_VIDEO when ACPI is enabled
        # but for select to work, need to select ACPI_VIDEO's dependencies, ick
-       select BACKLIGHT_LCD_SUPPORT if ACPI
        select BACKLIGHT_CLASS_DEVICE if ACPI
        select INPUT if ACPI
        select ACPI_VIDEO if ACPI
index 2ec89bc..8a9606f 100644 (file)
@@ -196,9 +196,9 @@ DEFINE_SIMPLE_ATTRIBUTE(vgpu_scan_nonprivbb_fops,
 int intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu)
 {
        struct dentry *ent;
-       char name[10] = "";
+       char name[16] = "";
 
-       sprintf(name, "vgpu%d", vgpu->id);
+       snprintf(name, 16, "vgpu%d", vgpu->id);
        vgpu->debugfs = debugfs_create_dir(name, vgpu->gvt->debugfs_root);
        if (!vgpu->debugfs)
                return -ENOMEM;
index 4e1e425..41c8ebc 100644 (file)
@@ -45,6 +45,7 @@ static int vgpu_gem_get_pages(
        int i, ret;
        gen8_pte_t __iomem *gtt_entries;
        struct intel_vgpu_fb_info *fb_info;
+       u32 page_num;
 
        fb_info = (struct intel_vgpu_fb_info *)obj->gvt_info;
        if (WARN_ON(!fb_info))
@@ -54,14 +55,15 @@ static int vgpu_gem_get_pages(
        if (unlikely(!st))
                return -ENOMEM;
 
-       ret = sg_alloc_table(st, fb_info->size, GFP_KERNEL);
+       page_num = obj->base.size >> PAGE_SHIFT;
+       ret = sg_alloc_table(st, page_num, GFP_KERNEL);
        if (ret) {
                kfree(st);
                return ret;
        }
        gtt_entries = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
                (fb_info->start >> PAGE_SHIFT);
-       for_each_sg(st->sgl, sg, fb_info->size, i) {
+       for_each_sg(st->sgl, sg, page_num, i) {
                sg->offset = 0;
                sg->length = PAGE_SIZE;
                sg_dma_address(sg) =
@@ -158,7 +160,7 @@ static struct drm_i915_gem_object *vgpu_create_gem(struct drm_device *dev,
                return NULL;
 
        drm_gem_private_object_init(dev, &obj->base,
-               info->size << PAGE_SHIFT);
+               roundup(info->size, PAGE_SIZE));
        i915_gem_object_init(obj, &intel_vgpu_gem_ops);
 
        obj->read_domains = I915_GEM_DOMAIN_GTT;
@@ -206,11 +208,12 @@ static int vgpu_get_plane_info(struct drm_device *dev,
                struct intel_vgpu_fb_info *info,
                int plane_id)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_vgpu_primary_plane_format p;
        struct intel_vgpu_cursor_plane_format c;
        int ret, tile_height = 1;
 
+       memset(info, 0, sizeof(*info));
+
        if (plane_id == DRM_PLANE_TYPE_PRIMARY) {
                ret = intel_vgpu_decode_primary_plane(vgpu, &p);
                if (ret)
@@ -267,8 +270,7 @@ static int vgpu_get_plane_info(struct drm_device *dev,
                return -EINVAL;
        }
 
-       info->size = (info->stride * roundup(info->height, tile_height)
-                     + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       info->size = info->stride * roundup(info->height, tile_height);
        if (info->size == 0) {
                gvt_vgpu_err("fb size is zero\n");
                return -EINVAL;
@@ -278,11 +280,6 @@ static int vgpu_get_plane_info(struct drm_device *dev,
                gvt_vgpu_err("Not aligned fb address:0x%llx\n", info->start);
                return -EFAULT;
        }
-       if (((info->start >> PAGE_SHIFT) + info->size) >
-               ggtt_total_entries(&dev_priv->ggtt)) {
-               gvt_vgpu_err("Invalid GTT offset or size\n");
-               return -EFAULT;
-       }
 
        if (!intel_gvt_ggtt_validate_range(vgpu, info->start, info->size)) {
                gvt_vgpu_err("invalid gma addr\n");
index c2f7d20..08c74e6 100644 (file)
@@ -811,7 +811,7 @@ static int reclaim_one_ppgtt_mm(struct intel_gvt *gvt);
 
 /* Allocate shadow page table without guest page. */
 static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
-               struct intel_vgpu *vgpu, intel_gvt_gtt_type_t type)
+               struct intel_vgpu *vgpu, enum intel_gvt_gtt_type type)
 {
        struct device *kdev = &vgpu->gvt->dev_priv->drm.pdev->dev;
        struct intel_vgpu_ppgtt_spt *spt = NULL;
@@ -861,7 +861,7 @@ err_free_spt:
 
 /* Allocate shadow page table associated with specific gfn. */
 static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt_gfn(
-               struct intel_vgpu *vgpu, intel_gvt_gtt_type_t type,
+               struct intel_vgpu *vgpu, enum intel_gvt_gtt_type type,
                unsigned long gfn, bool guest_pde_ips)
 {
        struct intel_vgpu_ppgtt_spt *spt;
@@ -936,7 +936,7 @@ static int ppgtt_invalidate_spt_by_shadow_entry(struct intel_vgpu *vgpu,
 {
        struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
        struct intel_vgpu_ppgtt_spt *s;
-       intel_gvt_gtt_type_t cur_pt_type;
+       enum intel_gvt_gtt_type cur_pt_type;
 
        GEM_BUG_ON(!gtt_type_is_pt(get_next_pt_type(e->type)));
 
@@ -1076,6 +1076,9 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_spt_by_guest_entry(
        } else {
                int type = get_next_pt_type(we->type);
 
+               if (!gtt_type_is_pt(type))
+                       goto err;
+
                spt = ppgtt_alloc_spt_gfn(vgpu, type, ops->get_pfn(we), ips);
                if (IS_ERR(spt)) {
                        ret = PTR_ERR(spt);
@@ -1855,7 +1858,7 @@ static void vgpu_free_mm(struct intel_vgpu_mm *mm)
  * Zero on success, negative error code in pointer if failed.
  */
 struct intel_vgpu_mm *intel_vgpu_create_ppgtt_mm(struct intel_vgpu *vgpu,
-               intel_gvt_gtt_type_t root_entry_type, u64 pdps[])
+               enum intel_gvt_gtt_type root_entry_type, u64 pdps[])
 {
        struct intel_gvt *gvt = vgpu->gvt;
        struct intel_vgpu_mm *mm;
@@ -2309,7 +2312,7 @@ int intel_vgpu_emulate_ggtt_mmio_write(struct intel_vgpu *vgpu,
 }
 
 static int alloc_scratch_pages(struct intel_vgpu *vgpu,
-               intel_gvt_gtt_type_t type)
+               enum intel_gvt_gtt_type type)
 {
        struct intel_vgpu_gtt *gtt = &vgpu->gtt;
        struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
@@ -2594,7 +2597,7 @@ struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu,
  * Zero on success, negative error code if failed.
  */
 struct intel_vgpu_mm *intel_vgpu_get_ppgtt_mm(struct intel_vgpu *vgpu,
-               intel_gvt_gtt_type_t root_entry_type, u64 pdps[])
+               enum intel_gvt_gtt_type root_entry_type, u64 pdps[])
 {
        struct intel_vgpu_mm *mm;
 
index 32c573a..42d0394 100644 (file)
@@ -95,8 +95,8 @@ struct intel_gvt_gtt {
        unsigned long scratch_mfn;
 };
 
-typedef enum {
-       GTT_TYPE_INVALID = -1,
+enum intel_gvt_gtt_type {
+       GTT_TYPE_INVALID = 0,
 
        GTT_TYPE_GGTT_PTE,
 
@@ -124,7 +124,7 @@ typedef enum {
        GTT_TYPE_PPGTT_PML4_PT,
 
        GTT_TYPE_MAX,
-} intel_gvt_gtt_type_t;
+};
 
 enum intel_gvt_mm_type {
        INTEL_GVT_MM_GGTT,
@@ -148,7 +148,7 @@ struct intel_vgpu_mm {
 
        union {
                struct {
-                       intel_gvt_gtt_type_t root_entry_type;
+                       enum intel_gvt_gtt_type root_entry_type;
                        /*
                         * The 4 PDPs in ring context. For 48bit addressing,
                         * only PDP0 is valid and point to PML4. For 32it
@@ -169,7 +169,7 @@ struct intel_vgpu_mm {
 };
 
 struct intel_vgpu_mm *intel_vgpu_create_ppgtt_mm(struct intel_vgpu *vgpu,
-               intel_gvt_gtt_type_t root_entry_type, u64 pdps[]);
+               enum intel_gvt_gtt_type root_entry_type, u64 pdps[]);
 
 static inline void intel_vgpu_mm_get(struct intel_vgpu_mm *mm)
 {
@@ -233,7 +233,7 @@ struct intel_vgpu_ppgtt_spt {
        struct intel_vgpu *vgpu;
 
        struct {
-               intel_gvt_gtt_type_t type;
+               enum intel_gvt_gtt_type type;
                bool pde_ips; /* for 64KB PTEs */
                void *vaddr;
                struct page *page;
@@ -241,7 +241,7 @@ struct intel_vgpu_ppgtt_spt {
        } shadow_page;
 
        struct {
-               intel_gvt_gtt_type_t type;
+               enum intel_gvt_gtt_type type;
                bool pde_ips; /* for 64KB PTEs */
                unsigned long gfn;
                unsigned long write_cnt;
@@ -267,7 +267,7 @@ struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu,
                u64 pdps[]);
 
 struct intel_vgpu_mm *intel_vgpu_get_ppgtt_mm(struct intel_vgpu *vgpu,
-               intel_gvt_gtt_type_t root_entry_type, u64 pdps[]);
+               enum intel_gvt_gtt_type root_entry_type, u64 pdps[]);
 
 int intel_vgpu_put_ppgtt_mm(struct intel_vgpu *vgpu, u64 pdps[]);
 
index 18f01ee..90673fc 100644 (file)
@@ -1206,7 +1206,7 @@ static int pvinfo_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
 
 static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification)
 {
-       intel_gvt_gtt_type_t root_entry_type = GTT_TYPE_PPGTT_ROOT_L4_ENTRY;
+       enum intel_gvt_gtt_type root_entry_type = GTT_TYPE_PPGTT_ROOT_L4_ENTRY;
        struct intel_vgpu_mm *mm;
        u64 *pdps;
 
@@ -3303,7 +3303,7 @@ void intel_gvt_clean_mmio_info(struct intel_gvt *gvt)
 /* Special MMIO blocks. */
 static struct gvt_mmio_block mmio_blocks[] = {
        {D_SKL_PLUS, _MMIO(CSR_MMIO_START_RANGE), 0x3000, NULL, NULL},
-       {D_ALL, MCHBAR_MIRROR_REG_BASE, 0x4000, NULL, NULL},
+       {D_ALL, _MMIO(MCHBAR_MIRROR_BASE_SNB), 0x40000, NULL, NULL},
        {D_ALL, _MMIO(VGT_PVINFO_PAGE), VGT_PVINFO_SIZE,
                pvinfo_mmio_read, pvinfo_mmio_write},
        {D_ALL, LGC_PALETTE(PIPE_A, 0), 1024, NULL, NULL},
index e7e14c8..edf6d64 100644 (file)
@@ -132,6 +132,7 @@ static struct engine_mmio gen9_engine_mmio_list[] __cacheline_aligned = {
 
        {RCS0, GEN9_GAMT_ECO_REG_RW_IA, 0x0, false}, /* 0x4ab0 */
        {RCS0, GEN9_CSFE_CHICKEN1_RCS, 0xffff, false}, /* 0x20d4 */
+       {RCS0, _MMIO(0x20D8), 0xffff, true}, /* 0x20d8 */
 
        {RCS0, GEN8_GARBCNTL, 0x0, false}, /* 0xb004 */
        {RCS0, GEN7_FF_THREAD_MODE, 0x0, false}, /* 0x20a0 */
index 3de5b64..33aaa14 100644 (file)
 #define RING_GFX_MODE(base)    _MMIO((base) + 0x29c)
 #define VF_GUARDBAND           _MMIO(0x83a4)
 
-/* define the effective range of MCHBAR register on Sandybridge+ */
-#define MCHBAR_MIRROR_REG_BASE _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x4000)
-
 #endif
index 8998fa5..7c99bbc 100644 (file)
@@ -1343,7 +1343,7 @@ static int prepare_mm(struct intel_vgpu_workload *workload)
        struct execlist_ctx_descriptor_format *desc = &workload->ctx_desc;
        struct intel_vgpu_mm *mm;
        struct intel_vgpu *vgpu = workload->vgpu;
-       intel_gvt_gtt_type_t root_entry_type;
+       enum intel_gvt_gtt_type root_entry_type;
        u64 pdps[GVT_RING_CTX_NR_PDPS];
 
        switch (desc->addressing_mode) {
index 215bf3f..8079ea3 100644 (file)
@@ -122,7 +122,7 @@ userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
        while (it) {
                struct drm_i915_gem_object *obj;
 
-               if (!range->blockable) {
+               if (!mmu_notifier_range_blockable(range)) {
                        ret = -EAGAIN;
                        break;
                }
index b836721..f6c78c0 100644 (file)
@@ -425,6 +425,26 @@ void __i915_request_submit(struct i915_request *request)
        if (i915_gem_context_is_banned(request->gem_context))
                i915_request_skip(request, -EIO);
 
+       /*
+        * Are we using semaphores when the gpu is already saturated?
+        *
+        * Using semaphores incurs a cost in having the GPU poll a
+        * memory location, busywaiting for it to change. The continual
+        * memory reads can have a noticeable impact on the rest of the
+        * system with the extra bus traffic, stalling the cpu as it too
+        * tries to access memory across the bus (perf stat -e bus-cycles).
+        *
+        * If we installed a semaphore on this request and we only submit
+        * the request after the signaler completed, that indicates the
+        * system is overloaded and using semaphores at this time only
+        * increases the amount of work we are doing. If so, we disable
+        * further use of semaphores until we are idle again, whence we
+        * optimistically try again.
+        */
+       if (request->sched.semaphores &&
+           i915_sw_fence_signaled(&request->semaphore))
+               request->hw_context->saturated |= request->sched.semaphores;
+
        /* We may be recursing from the signal callback of another i915 fence */
        spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING);
 
@@ -432,6 +452,7 @@ void __i915_request_submit(struct i915_request *request)
        set_bit(I915_FENCE_FLAG_ACTIVE, &request->fence.flags);
 
        if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags) &&
+           !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &request->fence.flags) &&
            !i915_request_enable_breadcrumb(request))
                intel_engine_queue_breadcrumbs(engine);
 
@@ -798,6 +819,39 @@ err_unreserve:
        return ERR_PTR(ret);
 }
 
+static int
+i915_request_await_start(struct i915_request *rq, struct i915_request *signal)
+{
+       if (list_is_first(&signal->ring_link, &signal->ring->request_list))
+               return 0;
+
+       signal = list_prev_entry(signal, ring_link);
+       if (i915_timeline_sync_is_later(rq->timeline, &signal->fence))
+               return 0;
+
+       return i915_sw_fence_await_dma_fence(&rq->submit,
+                                            &signal->fence, 0,
+                                            I915_FENCE_GFP);
+}
+
+static intel_engine_mask_t
+already_busywaiting(struct i915_request *rq)
+{
+       /*
+        * Polling a semaphore causes bus traffic, delaying other users of
+        * both the GPU and CPU. We want to limit the impact on others,
+        * while taking advantage of early submission to reduce GPU
+        * latency. Therefore we restrict ourselves to not using more
+        * than one semaphore from each source, and not using a semaphore
+        * if we have detected the engine is saturated (i.e. would not be
+        * submitted early and cause bus traffic reading an already passed
+        * semaphore).
+        *
+        * See the are-we-too-late? check in __i915_request_submit().
+        */
+       return rq->sched.semaphores | rq->hw_context->saturated;
+}
+
 static int
 emit_semaphore_wait(struct i915_request *to,
                    struct i915_request *from,
@@ -811,11 +865,15 @@ emit_semaphore_wait(struct i915_request *to,
        GEM_BUG_ON(INTEL_GEN(to->i915) < 8);
 
        /* Just emit the first semaphore we see as request space is limited. */
-       if (to->sched.semaphores & from->engine->mask)
+       if (already_busywaiting(to) & from->engine->mask)
                return i915_sw_fence_await_dma_fence(&to->submit,
                                                     &from->fence, 0,
                                                     I915_FENCE_GFP);
 
+       err = i915_request_await_start(to, from);
+       if (err < 0)
+               return err;
+
        err = i915_sw_fence_await_dma_fence(&to->semaphore,
                                            &from->fence, 0,
                                            I915_FENCE_GFP);
index 3cbffd4..832cb6b 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <linux/kthread.h>
+#include <trace/events/dma_fence.h>
 #include <uapi/linux/sched/types.h>
 
 #include "i915_drv.h"
@@ -80,9 +81,39 @@ static inline bool __request_completed(const struct i915_request *rq)
        return i915_seqno_passed(__hwsp_seqno(rq), rq->fence.seqno);
 }
 
+static bool
+__dma_fence_signal(struct dma_fence *fence)
+{
+       return !test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags);
+}
+
+static void
+__dma_fence_signal__timestamp(struct dma_fence *fence, ktime_t timestamp)
+{
+       fence->timestamp = timestamp;
+       set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
+       trace_dma_fence_signaled(fence);
+}
+
+static void
+__dma_fence_signal__notify(struct dma_fence *fence)
+{
+       struct dma_fence_cb *cur, *tmp;
+
+       lockdep_assert_held(fence->lock);
+       lockdep_assert_irqs_disabled();
+
+       list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
+               INIT_LIST_HEAD(&cur->node);
+               cur->func(fence, cur);
+       }
+       INIT_LIST_HEAD(&fence->cb_list);
+}
+
 void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine)
 {
        struct intel_breadcrumbs *b = &engine->breadcrumbs;
+       const ktime_t timestamp = ktime_get();
        struct intel_context *ce, *cn;
        struct list_head *pos, *next;
        LIST_HEAD(signal);
@@ -104,6 +135,10 @@ void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine)
 
                        GEM_BUG_ON(!test_bit(I915_FENCE_FLAG_SIGNAL,
                                             &rq->fence.flags));
+                       clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags);
+
+                       if (!__dma_fence_signal(&rq->fence))
+                               continue;
 
                        /*
                         * Queue for execution after dropping the signaling
@@ -111,14 +146,6 @@ void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine)
                         * more signalers to the same context or engine.
                         */
                        i915_request_get(rq);
-
-                       /*
-                        * We may race with direct invocation of
-                        * dma_fence_signal(), e.g. i915_request_retire(),
-                        * so we need to acquire our reference to the request
-                        * before we cancel the breadcrumb.
-                        */
-                       clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags);
                        list_add_tail(&rq->signal_link, &signal);
                }
 
@@ -141,7 +168,12 @@ void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine)
                struct i915_request *rq =
                        list_entry(pos, typeof(*rq), signal_link);
 
-               dma_fence_signal(&rq->fence);
+               __dma_fence_signal__timestamp(&rq->fence, timestamp);
+
+               spin_lock(&rq->lock);
+               __dma_fence_signal__notify(&rq->fence);
+               spin_unlock(&rq->lock);
+
                i915_request_put(rq);
        }
 }
@@ -243,19 +275,17 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine)
 
 bool i915_request_enable_breadcrumb(struct i915_request *rq)
 {
-       struct intel_breadcrumbs *b = &rq->engine->breadcrumbs;
-
-       GEM_BUG_ON(test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags));
+       lockdep_assert_held(&rq->lock);
+       lockdep_assert_irqs_disabled();
 
-       if (!test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags))
-               return true;
-
-       spin_lock(&b->irq_lock);
-       if (test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags) &&
-           !__request_completed(rq)) {
+       if (test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags)) {
+               struct intel_breadcrumbs *b = &rq->engine->breadcrumbs;
                struct intel_context *ce = rq->hw_context;
                struct list_head *pos;
 
+               spin_lock(&b->irq_lock);
+               GEM_BUG_ON(test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags));
+
                __intel_breadcrumbs_arm_irq(b);
 
                /*
@@ -284,8 +314,8 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq)
                        list_move_tail(&ce->signal_link, &b->signalers);
 
                set_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags);
+               spin_unlock(&b->irq_lock);
        }
-       spin_unlock(&b->irq_lock);
 
        return !__request_completed(rq);
 }
@@ -294,9 +324,15 @@ void i915_request_cancel_breadcrumb(struct i915_request *rq)
 {
        struct intel_breadcrumbs *b = &rq->engine->breadcrumbs;
 
-       if (!test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags))
-               return;
+       lockdep_assert_held(&rq->lock);
+       lockdep_assert_irqs_disabled();
 
+       /*
+        * We must wait for b->irq_lock so that we know the interrupt handler
+        * has released its reference to the intel_context and has completed
+        * the DMA_FENCE_FLAG_SIGNALED_BIT/I915_FENCE_FLAG_SIGNAL dance (if
+        * required).
+        */
        spin_lock(&b->irq_lock);
        if (test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)) {
                struct intel_context *ce = rq->hw_context;
index 8931e0f..924cc55 100644 (file)
@@ -230,6 +230,7 @@ intel_context_init(struct intel_context *ce,
        ce->gem_context = ctx;
        ce->engine = engine;
        ce->ops = engine->cops;
+       ce->saturated = 0;
 
        INIT_LIST_HEAD(&ce->signal_link);
        INIT_LIST_HEAD(&ce->signals);
index 68b4ca1..339c743 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 
 #include "i915_active_types.h"
+#include "intel_engine_types.h"
 
 struct i915_gem_context;
 struct i915_vma;
@@ -58,6 +59,8 @@ struct intel_context {
        atomic_t pin_count;
        struct mutex pin_mutex; /* guards pinning and associated on-gpuing */
 
+       intel_engine_mask_t saturated; /* submitting semaphores too late? */
+
        /**
         * active_tracker: Active tracker for the external rq activity
         * on this intel_context object.
index 3bd40a4..5098228 100644 (file)
@@ -12082,6 +12082,7 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
                          struct intel_crtc_state *pipe_config,
                          bool adjust)
 {
+       struct intel_crtc *crtc = to_intel_crtc(current_config->base.crtc);
        bool ret = true;
        bool fixup_inherited = adjust &&
                (current_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED) &&
@@ -12303,6 +12304,14 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
                PIPE_CONF_CHECK_X(gmch_pfit.pgm_ratios);
        PIPE_CONF_CHECK_X(gmch_pfit.lvds_border_bits);
 
+       /*
+        * Changing the EDP transcoder input mux
+        * (A_ONOFF vs. A_ON) requires a full modeset.
+        */
+       if (IS_HASWELL(dev_priv) && crtc->pipe == PIPE_A &&
+           current_config->cpu_transcoder == TRANSCODER_EDP)
+               PIPE_CONF_CHECK_BOOL(pch_pfit.enabled);
+
        if (!adjust) {
                PIPE_CONF_CHECK_I(pipe_src_w);
                PIPE_CONF_CHECK_I(pipe_src_h);
index c805a09..5679f2f 100644 (file)
@@ -1280,6 +1280,10 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv)
        if (!HAS_FBC(dev_priv))
                return 0;
 
+       /* https://bugs.freedesktop.org/show_bug.cgi?id=108085 */
+       if (IS_GEMINILAKE(dev_priv))
+               return 0;
+
        if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9)
                return 1;
 
index 37f60cb..46cd0e7 100644 (file)
@@ -23,7 +23,6 @@
  */
 
 #include <linux/circ_buf.h>
-#include <trace/events/dma_fence.h>
 
 #include "intel_guc_submission.h"
 #include "intel_lrc_reg.h"
index e94b5b1..e7c7be4 100644 (file)
@@ -311,10 +311,17 @@ retry:
        pipe_config->base.mode_changed = pipe_config->has_psr;
        pipe_config->crc_enabled = enable;
 
-       if (IS_HASWELL(dev_priv) && crtc->pipe == PIPE_A) {
+       if (IS_HASWELL(dev_priv) &&
+           pipe_config->base.active && crtc->pipe == PIPE_A &&
+           pipe_config->cpu_transcoder == TRANSCODER_EDP) {
+               bool old_need_power_well = pipe_config->pch_pfit.enabled ||
+                       pipe_config->pch_pfit.force_thru;
+               bool new_need_power_well = pipe_config->pch_pfit.enabled ||
+                       enable;
+
                pipe_config->pch_pfit.force_thru = enable;
-               if (pipe_config->cpu_transcoder == TRANSCODER_EDP &&
-                   pipe_config->pch_pfit.enabled != enable)
+
+               if (old_need_power_well != new_need_power_well)
                        pipe_config->base.connectors_changed = true;
        }
 
index 9155daf..38e2cfa 100644 (file)
@@ -747,7 +747,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
         * will make sure that the refcounting is correct in case we need to
         * bring down the GX after a GMU failure
         */
-       if (!IS_ERR(gmu->gxpd))
+       if (!IS_ERR_OR_NULL(gmu->gxpd))
                pm_runtime_get(gmu->gxpd);
 
 out:
@@ -863,7 +863,7 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu)
         * domain. Usually the GMU does this but only if the shutdown sequence
         * was successful
         */
-       if (!IS_ERR(gmu->gxpd))
+       if (!IS_ERR_OR_NULL(gmu->gxpd))
                pm_runtime_put_sync(gmu->gxpd);
 
        clk_bulk_disable_unprepare(gmu->nr_clocks, gmu->clocks);
@@ -1234,7 +1234,7 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
 
        pm_runtime_disable(gmu->dev);
 
-       if (!IS_ERR(gmu->gxpd)) {
+       if (!IS_ERR_OR_NULL(gmu->gxpd)) {
                pm_runtime_disable(gmu->gxpd);
                dev_pm_domain_detach(gmu->gxpd, false);
        }
index 018df2c..45a5bc6 100644 (file)
@@ -15,7 +15,6 @@
 #include "dpu_hwio.h"
 #include "dpu_hw_lm.h"
 #include "dpu_hw_mdss.h"
-#include "dpu_kms.h"
 
 #define LM_OP_MODE                        0x00
 #define LM_OUT_SIZE                       0x04
index da1f727..ce1a555 100644 (file)
@@ -780,7 +780,6 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
        struct dpu_plane_state *pstate = to_dpu_plane_state(new_state);
        struct dpu_hw_fmt_layout layout;
        struct drm_gem_object *obj;
-       struct msm_gem_object *msm_obj;
        struct dma_fence *fence;
        struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
        int ret;
@@ -799,8 +798,7 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
         *       implicit fence and fb prepare by hand here.
         */
        obj = msm_framebuffer_bo(new_state->fb, 0);
-       msm_obj = to_msm_bo(obj);
-       fence = reservation_object_get_excl_rcu(msm_obj->resv);
+       fence = reservation_object_get_excl_rcu(obj->resv);
        if (fence)
                drm_atomic_set_fence_for_plane(new_state, fence);
 
index f5b1256..131c23a 100644 (file)
@@ -49,15 +49,13 @@ int msm_atomic_prepare_fb(struct drm_plane *plane,
        struct msm_drm_private *priv = plane->dev->dev_private;
        struct msm_kms *kms = priv->kms;
        struct drm_gem_object *obj;
-       struct msm_gem_object *msm_obj;
        struct dma_fence *fence;
 
        if (!new_state->fb)
                return 0;
 
        obj = msm_framebuffer_bo(new_state->fb, 0);
-       msm_obj = to_msm_bo(obj);
-       fence = reservation_object_get_excl_rcu(msm_obj->resv);
+       fence = reservation_object_get_excl_rcu(obj->resv);
 
        drm_atomic_set_fence_for_plane(new_state, fence);
 
index eb33d2d..e20e6b4 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/types.h>
 #include <linux/of_graph.h>
 #include <linux/of_device.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <linux/kthread.h>
 
 #include <drm/drmP.h>
index 31d5a74..35f55dd 100644 (file)
@@ -803,7 +803,8 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
                seq_puts(m, "      vmas:");
 
                list_for_each_entry(vma, &msm_obj->vmas, list)
-                       seq_printf(m, " [%s: %08llx,%s,inuse=%d]", vma->aspace->name,
+                       seq_printf(m, " [%s: %08llx,%s,inuse=%d]",
+                               vma->aspace != NULL ? vma->aspace->name : NULL,
                                vma->iova, vma->mapped ? "mapped" : "unmapped",
                                vma->inuse);
 
index c5ac781..812d1b1 100644 (file)
@@ -86,10 +86,6 @@ struct msm_gem_object {
 
        struct llist_node freed;
 
-       /* normally (resv == &_resv) except for imported bo's */
-       struct reservation_object *resv;
-       struct reservation_object _resv;
-
        /* For physically contiguous buffers.  Used when we don't have
         * an IOMMU.  Also used for stolen/splashscreen buffer.
         */
index 553c7da..1f13951 100644 (file)
@@ -5,14 +5,12 @@ config DRM_NOUVEAU
        select DRM_KMS_HELPER
        select DRM_TTM
        select BACKLIGHT_CLASS_DEVICE if DRM_NOUVEAU_BACKLIGHT
-       select BACKLIGHT_LCD_SUPPORT if DRM_NOUVEAU_BACKLIGHT
        select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && INPUT
        select X86_PLATFORM_DEVICES if ACPI && X86
        select ACPI_WMI if ACPI && X86
        select MXM_WMI if ACPI && X86
        select POWER_SUPPLY
        # Similar to i915, we need to select ACPI_VIDEO and it's dependencies
-       select BACKLIGHT_LCD_SUPPORT if ACPI && X86
        select BACKLIGHT_CLASS_DEVICE if ACPI && X86
        select INPUT if ACPI && X86
        select THERMAL if ACPI && X86
index 2216c58..7c41b05 100644 (file)
@@ -41,6 +41,7 @@ struct nv50_disp_interlock {
                NV50_DISP_INTERLOCK__SIZE
        } type;
        u32 data;
+       u32 wimm;
 };
 
 void corec37d_ntfy_init(struct nouveau_bo *, u32);
index 2e7a0c3..06ee238 100644 (file)
@@ -306,7 +306,7 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
                        asyh->set.or = head->func->or != NULL;
                }
 
-               if (asyh->state.mode_changed)
+               if (asyh->state.mode_changed || asyh->state.connectors_changed)
                        nv50_head_atomic_check_mode(head, asyh);
 
                if (asyh->state.color_mgmt_changed ||
@@ -413,6 +413,7 @@ nv50_head_atomic_duplicate_state(struct drm_crtc *crtc)
        asyh->ovly = armh->ovly;
        asyh->dither = armh->dither;
        asyh->procamp = armh->procamp;
+       asyh->or = armh->or;
        asyh->dp = armh->dp;
        asyh->clr.mask = 0;
        asyh->set.mask = 0;
index 9103b84..f7dbd96 100644 (file)
@@ -75,6 +75,7 @@ wimmc37b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm,
                return ret;
        }
 
+       wndw->interlock.wimm = wndw->interlock.data;
        wndw->immd = func;
        return 0;
 }
index b951810..283ff69 100644 (file)
@@ -127,7 +127,7 @@ void
 nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock,
                    struct nv50_wndw_atom *asyw)
 {
-       if (interlock) {
+       if (interlock[NV50_DISP_INTERLOCK_CORE]) {
                asyw->image.mode = 0;
                asyw->image.interval = 1;
        }
@@ -149,7 +149,7 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock,
        if (asyw->set.point) {
                if (asyw->set.point = false, asyw->set.mask)
                        interlock[wndw->interlock.type] |= wndw->interlock.data;
-               interlock[NV50_DISP_INTERLOCK_WIMM] |= wndw->interlock.data;
+               interlock[NV50_DISP_INTERLOCK_WIMM] |= wndw->interlock.wimm;
 
                wndw->immd->point(wndw, asyw);
                wndw->immd->update(wndw, interlock);
index 22cd458..7c2fcab 100644 (file)
@@ -631,7 +631,8 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
        /* We need to check that the chipset is supported before booting
         * fbdev off the hardware, as there's no way to put it back.
         */
-       ret = nvkm_device_pci_new(pdev, NULL, "error", true, false, 0, &device);
+       ret = nvkm_device_pci_new(pdev, nouveau_config, "error",
+                                 true, false, 0, &device);
        if (ret)
                return ret;
 
index 7971096..10d91e8 100644 (file)
@@ -2540,6 +2540,41 @@ nv166_chipset = {
        .sec2 = tu102_sec2_new,
 };
 
+static const struct nvkm_device_chip
+nv167_chipset = {
+       .name = "TU117",
+       .bar = tu102_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .devinit = tu102_devinit_new,
+       .fault = tu102_fault_new,
+       .fb = gv100_fb_new,
+       .fuse = gm107_fuse_new,
+       .gpio = gk104_gpio_new,
+       .gsp = gv100_gsp_new,
+       .i2c = gm200_i2c_new,
+       .ibus = gm200_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gp102_ltc_new,
+       .mc = tu102_mc_new,
+       .mmu = tu102_mmu_new,
+       .pci = gp100_pci_new,
+       .pmu = gp102_pmu_new,
+       .therm = gp100_therm_new,
+       .timer = gk20a_timer_new,
+       .top = gk104_top_new,
+       .ce[0] = tu102_ce_new,
+       .ce[1] = tu102_ce_new,
+       .ce[2] = tu102_ce_new,
+       .ce[3] = tu102_ce_new,
+       .ce[4] = tu102_ce_new,
+       .disp = tu102_disp_new,
+       .dma = gv100_dma_new,
+       .fifo = tu102_fifo_new,
+       .nvdec[0] = gp102_nvdec_new,
+       .sec2 = tu102_sec2_new,
+};
+
 static int
 nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size,
                       struct nvkm_notify *notify)
@@ -2824,8 +2859,8 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
        u64 mmio_base, mmio_size;
        u32 boot0, strap;
        void __iomem *map;
-       int ret = -EEXIST;
-       int i;
+       int ret = -EEXIST, i;
+       unsigned chipset;
 
        mutex_lock(&nv_devices_mutex);
        if (nvkm_device_find_locked(handle))
@@ -2870,6 +2905,26 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
                strap = ioread32_native(map + 0x101000);
                iounmap(map);
 
+               /* chipset can be overridden for devel/testing purposes */
+               chipset = nvkm_longopt(device->cfgopt, "NvChipset", 0);
+               if (chipset) {
+                       u32 override_boot0;
+
+                       if (chipset >= 0x10) {
+                               override_boot0  = ((chipset & 0x1ff) << 20);
+                               override_boot0 |= 0x000000a1;
+                       } else {
+                               if (chipset != 0x04)
+                                       override_boot0 = 0x20104000;
+                               else
+                                       override_boot0 = 0x20004000;
+                       }
+
+                       nvdev_warn(device, "CHIPSET OVERRIDE: %08x -> %08x\n",
+                                  boot0, override_boot0);
+                       boot0 = override_boot0;
+               }
+
                /* determine chipset and derive architecture from it */
                if ((boot0 & 0x1f000000) > 0) {
                        device->chipset = (boot0 & 0x1ff00000) >> 20;
@@ -2996,6 +3051,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
                case 0x162: device->chip = &nv162_chipset; break;
                case 0x164: device->chip = &nv164_chipset; break;
                case 0x166: device->chip = &nv166_chipset; break;
+               case 0x167: device->chip = &nv167_chipset; break;
                default:
                        nvdev_error(device, "unknown chipset (%08x)\n", boot0);
                        goto done;
index 5f301e6..818d21b 100644 (file)
@@ -365,8 +365,15 @@ nvkm_dp_train(struct nvkm_dp *dp, u32 dataKBps)
         * and it's better to have a failed modeset than that.
         */
        for (cfg = nvkm_dp_rates; cfg->rate; cfg++) {
-               if (cfg->nr <= outp_nr && cfg->nr <= outp_bw)
-                       failsafe = cfg;
+               if (cfg->nr <= outp_nr && cfg->nr <= outp_bw) {
+                       /* Try to respect sink limits too when selecting
+                        * lowest link configuration.
+                        */
+                       if (!failsafe ||
+                           (cfg->nr <= sink_nr && cfg->bw <= sink_bw))
+                               failsafe = cfg;
+               }
+
                if (failsafe && cfg[1].rate < dataKBps)
                        break;
        }
index 970f669..3b2bced 100644 (file)
@@ -165,6 +165,10 @@ err_out0:
 
 void panfrost_device_fini(struct panfrost_device *pfdev)
 {
+       panfrost_job_fini(pfdev);
+       panfrost_mmu_fini(pfdev);
+       panfrost_gpu_fini(pfdev);
+       panfrost_reset_fini(pfdev);
        panfrost_regulator_fini(pfdev);
        panfrost_clk_fini(pfdev);
 }
index 94b0819..d11e228 100644 (file)
@@ -219,7 +219,8 @@ static int panfrost_ioctl_submit(struct drm_device *dev, void *data,
 fail_job:
        panfrost_job_put(job);
 fail_out_sync:
-       drm_syncobj_put(sync_out);
+       if (sync_out)
+               drm_syncobj_put(sync_out);
 
        return ret;
 }
index 0c5d391..4501597 100644 (file)
@@ -531,14 +531,15 @@ pl111_init_clock_divider(struct drm_device *drm)
                dev_err(drm->dev, "CLCD: unable to get clcdclk.\n");
                return PTR_ERR(parent);
        }
+
+       spin_lock_init(&priv->tim2_lock);
+
        /* If the clock divider is broken, use the parent directly */
        if (priv->variant->broken_clockdivider) {
                priv->clk = parent;
                return 0;
        }
        parent_name = __clk_get_name(parent);
-
-       spin_lock_init(&priv->tim2_lock);
        div->init = &init;
 
        ret = devm_clk_hw_register(drm->dev, div);
index aa898c6..433df70 100644 (file)
@@ -922,12 +922,12 @@ static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div,
        ref_div_max = max(min(100 / post_div, ref_div_max), 1u);
 
        /* get matching reference and feedback divider */
-       *ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max);
+       *ref_div = min(max(den/post_div, 1u), ref_div_max);
        *fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den);
 
        /* limit fb divider to its maximum */
        if (*fb_div > fb_div_max) {
-               *ref_div = DIV_ROUND_CLOSEST(*ref_div * fb_div_max, *fb_div);
+               *ref_div = (*ref_div * fb_div_max)/(*fb_div);
                *fb_div = fb_div_max;
        }
 }
index b301950..c9bd127 100644 (file)
@@ -133,7 +133,7 @@ static int radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
        /* TODO we should be able to split locking for interval tree and
         * the tear down.
         */
-       if (range->blockable)
+       if (mmu_notifier_range_blockable(range))
                mutex_lock(&rmn->lock);
        else if (!mutex_trylock(&rmn->lock))
                return -EAGAIN;
@@ -144,7 +144,7 @@ static int radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
                struct radeon_bo *bo;
                long r;
 
-               if (!range->blockable) {
+               if (!mmu_notifier_range_blockable(range)) {
                        ret = -EAGAIN;
                        goto out_unlock;
                }
index a8db758..a2ebb08 100644 (file)
@@ -221,26 +221,13 @@ static int rockchip_drm_gem_object_mmap_iommu(struct drm_gem_object *obj,
                                              struct vm_area_struct *vma)
 {
        struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);
-       unsigned int i, count = obj->size >> PAGE_SHIFT;
+       unsigned int count = obj->size >> PAGE_SHIFT;
        unsigned long user_count = vma_pages(vma);
-       unsigned long uaddr = vma->vm_start;
-       unsigned long offset = vma->vm_pgoff;
-       unsigned long end = user_count + offset;
-       int ret;
 
        if (user_count == 0)
                return -ENXIO;
-       if (end > count)
-               return -ENXIO;
 
-       for (i = offset; i < end; i++) {
-               ret = vm_insert_page(vma, uaddr, rk_obj->pages[i]);
-               if (ret)
-                       return ret;
-               uaddr += PAGE_SIZE;
-       }
-
-       return 0;
+       return vm_map_pages(vma, rk_obj->pages, count);
 }
 
 static int rockchip_drm_gem_object_mmap_dma(struct drm_gem_object *obj,
index 61bbe8e..e2a6c82 100644 (file)
@@ -4,7 +4,6 @@ config DRM_SHMOBILE
        depends on DRM && ARM
        depends on ARCH_SHMOBILE || COMPILE_TEST
        select BACKLIGHT_CLASS_DEVICE
-       select BACKLIGHT_LCD_SUPPORT
        select DRM_KMS_HELPER
        select DRM_KMS_CMA_HELPER
        select DRM_GEM_CMA_HELPER
index fb985ba..2598741 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "sun4i_hdmi.h"
 
index 5259804..cb7df20 100644 (file)
@@ -8,7 +8,6 @@ config DRM_TILCDC
        select DRM_PANEL_BRIDGE
        select VIDEOMODE_HELPERS
        select BACKLIGHT_CLASS_DEVICE
-       select BACKLIGHT_LCD_SUPPORT
        help
          Choose this option if you have an TI SoC with LCDC display
          controller, for example AM33xx in beagle-bone, DA8xx, or
index 9412709..2ea4e20 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/component.h>
 #include <linux/dmaengine.h>
 #include <linux/i2c.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
index 8bf3a7c..0620674 100644 (file)
@@ -243,7 +243,8 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg,  drm_via_dmablit_t *xfer)
        if (NULL == vsg->pages)
                return -ENOMEM;
        ret = get_user_pages_fast((unsigned long)xfer->mem_addr,
-                       vsg->num_pages, vsg->direction == DMA_FROM_DEVICE,
+                       vsg->num_pages,
+                       vsg->direction == DMA_FROM_DEVICE ? FOLL_WRITE : 0,
                        vsg->pages);
        if (ret != vsg->num_pages) {
                if (ret < 0)
index 53c376d..a245484 100644 (file)
@@ -224,8 +224,7 @@ xen_drm_front_gem_import_sg_table(struct drm_device *dev,
 static int gem_mmap_obj(struct xen_gem_object *xen_obj,
                        struct vm_area_struct *vma)
 {
-       unsigned long addr = vma->vm_start;
-       int i;
+       int ret;
 
        /*
         * clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
@@ -252,18 +251,11 @@ static int gem_mmap_obj(struct xen_gem_object *xen_obj,
         * FIXME: as we insert all the pages now then no .fault handler must
         * be called, so don't provide one
         */
-       for (i = 0; i < xen_obj->num_pages; i++) {
-               int ret;
-
-               ret = vm_insert_page(vma, addr, xen_obj->pages[i]);
-               if (ret < 0) {
-                       DRM_ERROR("Failed to insert pages into vma: %d\n", ret);
-                       return ret;
-               }
+       ret = vm_map_pages(vma, xen_obj->pages, xen_obj->num_pages);
+       if (ret < 0)
+               DRM_ERROR("Failed to map pages into vma: %d\n", ret);
 
-               addr += PAGE_SIZE;
-       }
-       return 0;
+       return ret;
 }
 
 int xen_drm_front_gem_mmap(struct file *filp, struct vm_area_struct *vma)
index 46c6efe..abdb018 100644 (file)
@@ -1051,6 +1051,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x28b: map_key_clear(KEY_FORWARDMAIL);     break;
                case 0x28c: map_key_clear(KEY_SEND);            break;
 
+               case 0x29d: map_key_clear(KEY_KBD_LAYOUT_NEXT); break;
+
                case 0x2c7: map_key_clear(KEY_KBDINPUTASSIST_PREV);             break;
                case 0x2c8: map_key_clear(KEY_KBDINPUTASSIST_NEXT);             break;
                case 0x2c9: map_key_clear(KEY_KBDINPUTASSIST_PREVGROUP);                break;
index c4dd630..0daf0b3 100644 (file)
@@ -830,10 +830,8 @@ static int aspeed_create_pwm_cooling(struct device *dev,
        }
        snprintf(cdev->name, MAX_CDEV_NAME_LEN, "%pOFn%d", child, pwm_port);
 
-       cdev->tcdev = thermal_of_cooling_device_register(child,
-                                                        cdev->name,
-                                                        cdev,
-                                                        &aspeed_pwm_cool_ops);
+       cdev->tcdev = devm_thermal_of_cooling_device_register(dev, child,
+                                       cdev->name, cdev, &aspeed_pwm_cool_ops);
        if (IS_ERR(cdev->tcdev))
                return PTR_ERR(cdev->tcdev);
 
index f1bf67a..3f6e5b4 100644 (file)
@@ -498,6 +498,11 @@ static const struct of_device_id of_gpio_fan_match[] = {
 };
 MODULE_DEVICE_TABLE(of, of_gpio_fan_match);
 
+static void gpio_fan_stop(void *data)
+{
+       set_fan_speed(data, 0);
+}
+
 static int gpio_fan_probe(struct platform_device *pdev)
 {
        int err;
@@ -532,6 +537,7 @@ static int gpio_fan_probe(struct platform_device *pdev)
                err = fan_ctrl_init(fan_data);
                if (err)
                        return err;
+               devm_add_action_or_reset(dev, gpio_fan_stop, fan_data);
        }
 
        /* Make this driver part of hwmon class. */
@@ -543,32 +549,20 @@ static int gpio_fan_probe(struct platform_device *pdev)
                return PTR_ERR(fan_data->hwmon_dev);
 
        /* Optional cooling device register for Device tree platforms */
-       fan_data->cdev = thermal_of_cooling_device_register(np,
-                                                           "gpio-fan",
-                                                           fan_data,
-                                                           &gpio_fan_cool_ops);
+       fan_data->cdev = devm_thermal_of_cooling_device_register(dev, np,
+                               "gpio-fan", fan_data, &gpio_fan_cool_ops);
 
        dev_info(dev, "GPIO fan initialized\n");
 
        return 0;
 }
 
-static int gpio_fan_remove(struct platform_device *pdev)
+static void gpio_fan_shutdown(struct platform_device *pdev)
 {
        struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
 
-       if (!IS_ERR(fan_data->cdev))
-               thermal_cooling_device_unregister(fan_data->cdev);
-
        if (fan_data->gpios)
                set_fan_speed(fan_data, 0);
-
-       return 0;
-}
-
-static void gpio_fan_shutdown(struct platform_device *pdev)
-{
-       gpio_fan_remove(pdev);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -602,7 +596,6 @@ static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume);
 
 static struct platform_driver gpio_fan_driver = {
        .probe          = gpio_fan_probe,
-       .remove         = gpio_fan_remove,
        .shutdown       = gpio_fan_shutdown,
        .driver = {
                .name   = "gpio-fan",
index cd91510..e694c46 100644 (file)
@@ -118,9 +118,7 @@ static DEFINE_IDA(hwmon_ida);
  * The complex conditional is necessary to avoid a cyclic dependency
  * between hwmon and thermal_sys modules.
  */
-#if IS_REACHABLE(CONFIG_THERMAL) && defined(CONFIG_THERMAL_OF) && \
-       (!defined(CONFIG_THERMAL_HWMON) || \
-        !(defined(MODULE) && IS_MODULE(CONFIG_THERMAL)))
+#ifdef CONFIG_THERMAL_OF
 static int hwmon_thermal_get_temp(void *data, int *temp)
 {
        struct hwmon_thermal_data *tdata = data;
index f816d2a..ed8d59d 100644 (file)
@@ -465,42 +465,42 @@ static int mlxreg_fan_config(struct mlxreg_fan *fan,
 static int mlxreg_fan_probe(struct platform_device *pdev)
 {
        struct mlxreg_core_platform_data *pdata;
+       struct device *dev = &pdev->dev;
        struct mlxreg_fan *fan;
        struct device *hwm;
        int err;
 
-       pdata = dev_get_platdata(&pdev->dev);
+       pdata = dev_get_platdata(dev);
        if (!pdata) {
-               dev_err(&pdev->dev, "Failed to get platform data.\n");
+               dev_err(dev, "Failed to get platform data.\n");
                return -EINVAL;
        }
 
-       fan = devm_kzalloc(&pdev->dev, sizeof(*fan), GFP_KERNEL);
+       fan = devm_kzalloc(dev, sizeof(*fan), GFP_KERNEL);
        if (!fan)
                return -ENOMEM;
 
-       fan->dev = &pdev->dev;
+       fan->dev = dev;
        fan->regmap = pdata->regmap;
-       platform_set_drvdata(pdev, fan);
 
        err = mlxreg_fan_config(fan, pdata);
        if (err)
                return err;
 
-       hwm = devm_hwmon_device_register_with_info(&pdev->dev, "mlxreg_fan",
+       hwm = devm_hwmon_device_register_with_info(dev, "mlxreg_fan",
                                                   fan,
                                                   &mlxreg_fan_hwmon_chip_info,
                                                   NULL);
        if (IS_ERR(hwm)) {
-               dev_err(&pdev->dev, "Failed to register hwmon device\n");
+               dev_err(dev, "Failed to register hwmon device\n");
                return PTR_ERR(hwm);
        }
 
        if (IS_REACHABLE(CONFIG_THERMAL)) {
-               fan->cdev = thermal_cooling_device_register("mlxreg_fan", fan,
-                                               &mlxreg_fan_cooling_ops);
+               fan->cdev = devm_thermal_of_cooling_device_register(dev,
+                       NULL, "mlxreg_fan", fan, &mlxreg_fan_cooling_ops);
                if (IS_ERR(fan->cdev)) {
-                       dev_err(&pdev->dev, "Failed to register cooling device\n");
+                       dev_err(dev, "Failed to register cooling device\n");
                        return PTR_ERR(fan->cdev);
                }
        }
@@ -508,22 +508,11 @@ static int mlxreg_fan_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int mlxreg_fan_remove(struct platform_device *pdev)
-{
-       struct mlxreg_fan *fan = platform_get_drvdata(pdev);
-
-       if (IS_REACHABLE(CONFIG_THERMAL))
-               thermal_cooling_device_unregister(fan->cdev);
-
-       return 0;
-}
-
 static struct platform_driver mlxreg_fan_driver = {
        .driver = {
            .name = "mlxreg-fan",
        },
        .probe = mlxreg_fan_probe,
-       .remove = mlxreg_fan_remove,
 };
 
 module_platform_driver(mlxreg_fan_driver);
index 1dc0cd4..09aaefa 100644 (file)
@@ -846,10 +846,8 @@ static int npcm7xx_create_pwm_cooling(struct device *dev,
        snprintf(cdev->name, THERMAL_NAME_LENGTH, "%pOFn%d", child,
                 pwm_port);
 
-       cdev->tcdev = thermal_of_cooling_device_register(child,
-                                                        cdev->name,
-                                                        cdev,
-                                                        &npcm7xx_pwm_cool_ops);
+       cdev->tcdev = devm_thermal_of_cooling_device_register(dev, child,
+                               cdev->name, cdev, &npcm7xx_pwm_cool_ops);
        if (IS_ERR(cdev->tcdev))
                return PTR_ERR(cdev->tcdev);
 
index eead8af..5fb2745 100644 (file)
@@ -273,27 +273,40 @@ static int pwm_fan_of_get_cooling_data(struct device *dev,
        return 0;
 }
 
+static void pwm_fan_regulator_disable(void *data)
+{
+       regulator_disable(data);
+}
+
+static void pwm_fan_pwm_disable(void *__ctx)
+{
+       struct pwm_fan_ctx *ctx = __ctx;
+       pwm_disable(ctx->pwm);
+       del_timer_sync(&ctx->rpm_timer);
+}
+
 static int pwm_fan_probe(struct platform_device *pdev)
 {
        struct thermal_cooling_device *cdev;
+       struct device *dev = &pdev->dev;
        struct pwm_fan_ctx *ctx;
        struct device *hwmon;
        int ret;
        struct pwm_state state = { };
        u32 ppr = 2;
 
-       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
 
        mutex_init(&ctx->lock);
 
-       ctx->pwm = devm_of_pwm_get(&pdev->dev, pdev->dev.of_node, NULL);
+       ctx->pwm = devm_of_pwm_get(dev, dev->of_node, NULL);
        if (IS_ERR(ctx->pwm)) {
                ret = PTR_ERR(ctx->pwm);
 
                if (ret != -EPROBE_DEFER)
-                       dev_err(&pdev->dev, "Could not get PWM: %d\n", ret);
+                       dev_err(dev, "Could not get PWM: %d\n", ret);
 
                return ret;
        }
@@ -304,7 +317,7 @@ static int pwm_fan_probe(struct platform_device *pdev)
        if (ctx->irq == -EPROBE_DEFER)
                return ctx->irq;
 
-       ctx->reg_en = devm_regulator_get_optional(&pdev->dev, "fan");
+       ctx->reg_en = devm_regulator_get_optional(dev, "fan");
        if (IS_ERR(ctx->reg_en)) {
                if (PTR_ERR(ctx->reg_en) != -ENODEV)
                        return PTR_ERR(ctx->reg_en);
@@ -313,10 +326,11 @@ static int pwm_fan_probe(struct platform_device *pdev)
        } else {
                ret = regulator_enable(ctx->reg_en);
                if (ret) {
-                       dev_err(&pdev->dev,
-                               "Failed to enable fan supply: %d\n", ret);
+                       dev_err(dev, "Failed to enable fan supply: %d\n", ret);
                        return ret;
                }
+               devm_add_action_or_reset(dev, pwm_fan_regulator_disable,
+                                        ctx->reg_en);
        }
 
        ctx->pwm_value = MAX_PWM;
@@ -328,91 +342,57 @@ static int pwm_fan_probe(struct platform_device *pdev)
 
        ret = pwm_apply_state(ctx->pwm, &state);
        if (ret) {
-               dev_err(&pdev->dev, "Failed to configure PWM: %d\n", ret);
-               goto err_reg_disable;
+               dev_err(dev, "Failed to configure PWM: %d\n", ret);
+               return ret;
        }
-
        timer_setup(&ctx->rpm_timer, sample_timer, 0);
+       devm_add_action_or_reset(dev, pwm_fan_pwm_disable, ctx);
 
-       of_property_read_u32(pdev->dev.of_node, "pulses-per-revolution", &ppr);
+       of_property_read_u32(dev->of_node, "pulses-per-revolution", &ppr);
        ctx->pulses_per_revolution = ppr;
        if (!ctx->pulses_per_revolution) {
-               dev_err(&pdev->dev, "pulses-per-revolution can't be zero.\n");
-               ret = -EINVAL;
-               goto err_pwm_disable;
+               dev_err(dev, "pulses-per-revolution can't be zero.\n");
+               return -EINVAL;
        }
 
        if (ctx->irq > 0) {
-               ret = devm_request_irq(&pdev->dev, ctx->irq, pulse_handler, 0,
+               ret = devm_request_irq(dev, ctx->irq, pulse_handler, 0,
                                       pdev->name, ctx);
                if (ret) {
-                       dev_err(&pdev->dev,
-                               "Failed to request interrupt: %d\n", ret);
-                       goto err_pwm_disable;
+                       dev_err(dev, "Failed to request interrupt: %d\n", ret);
+                       return ret;
                }
                ctx->sample_start = ktime_get();
                mod_timer(&ctx->rpm_timer, jiffies + HZ);
        }
 
-       hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, "pwmfan",
+       hwmon = devm_hwmon_device_register_with_groups(dev, "pwmfan",
                                                       ctx, pwm_fan_groups);
        if (IS_ERR(hwmon)) {
-               ret = PTR_ERR(hwmon);
-               dev_err(&pdev->dev,
-                       "Failed to register hwmon device: %d\n", ret);
-               goto err_del_timer;
+               dev_err(dev, "Failed to register hwmon device\n");
+               return PTR_ERR(hwmon);
        }
 
-       ret = pwm_fan_of_get_cooling_data(&pdev->dev, ctx);
+       ret = pwm_fan_of_get_cooling_data(dev, ctx);
        if (ret)
-               goto err_del_timer;
+               return ret;
 
        ctx->pwm_fan_state = ctx->pwm_fan_max_state;
        if (IS_ENABLED(CONFIG_THERMAL)) {
-               cdev = thermal_of_cooling_device_register(pdev->dev.of_node,
-                                                         "pwm-fan", ctx,
-                                                         &pwm_fan_cooling_ops);
+               cdev = devm_thermal_of_cooling_device_register(dev,
+                       dev->of_node, "pwm-fan", ctx, &pwm_fan_cooling_ops);
                if (IS_ERR(cdev)) {
                        ret = PTR_ERR(cdev);
-                       dev_err(&pdev->dev,
+                       dev_err(dev,
                                "Failed to register pwm-fan as cooling device: %d\n",
                                ret);
-                       goto err_del_timer;
+                       return ret;
                }
                ctx->cdev = cdev;
                thermal_cdev_update(cdev);
        }
 
        return 0;
-
-err_del_timer:
-       del_timer_sync(&ctx->rpm_timer);
-
-err_pwm_disable:
-       state.enabled = false;
-       pwm_apply_state(ctx->pwm, &state);
-
-err_reg_disable:
-       if (ctx->reg_en)
-               regulator_disable(ctx->reg_en);
-
-       return ret;
-}
-
-static int pwm_fan_remove(struct platform_device *pdev)
-{
-       struct pwm_fan_ctx *ctx = platform_get_drvdata(pdev);
-
-       thermal_cooling_device_unregister(ctx->cdev);
-       del_timer_sync(&ctx->rpm_timer);
-
-       if (ctx->pwm_value)
-               pwm_disable(ctx->pwm);
-
-       if (ctx->reg_en)
-               regulator_disable(ctx->reg_en);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -480,7 +460,6 @@ MODULE_DEVICE_TABLE(of, of_pwm_fan_match);
 
 static struct platform_driver pwm_fan_driver = {
        .probe          = pwm_fan_probe,
-       .remove         = pwm_fan_remove,
        .driver = {
                .name           = "pwm-fan",
                .pm             = &pwm_fan_pm,
index 06ca3f7..4a5eff3 100644 (file)
@@ -733,11 +733,11 @@ static int iio_channel_read_avail(struct iio_channel *chan,
                                                 vals, type, length, info);
 }
 
-int iio_read_avail_channel_raw(struct iio_channel *chan,
-                              const int **vals, int *length)
+int iio_read_avail_channel_attribute(struct iio_channel *chan,
+                                    const int **vals, int *type, int *length,
+                                    enum iio_chan_info_enum attribute)
 {
        int ret;
-       int type;
 
        mutex_lock(&chan->indio_dev->info_exist_lock);
        if (!chan->indio_dev->info) {
@@ -745,11 +745,23 @@ int iio_read_avail_channel_raw(struct iio_channel *chan,
                goto err_unlock;
        }
 
-       ret = iio_channel_read_avail(chan,
-                                    vals, &type, length, IIO_CHAN_INFO_RAW);
+       ret = iio_channel_read_avail(chan, vals, type, length, attribute);
 err_unlock:
        mutex_unlock(&chan->indio_dev->info_exist_lock);
 
+       return ret;
+}
+EXPORT_SYMBOL_GPL(iio_read_avail_channel_attribute);
+
+int iio_read_avail_channel_raw(struct iio_channel *chan,
+                              const int **vals, int *length)
+{
+       int ret;
+       int type;
+
+       ret = iio_read_avail_channel_attribute(chan, vals, &type, length,
+                                        IIO_CHAN_INFO_RAW);
+
        if (ret >= 0 && type != IIO_VAL_INT)
                /* raw values are assumed to be IIO_VAL_INT */
                ret = -EINVAL;
index ba01b90..2f7d141 100644 (file)
@@ -731,8 +731,8 @@ int roce_resolve_route_from_path(struct sa_path_rec *rec,
        if (rec->roce.route_resolved)
                return 0;
 
-       rdma_gid2ip(&sgid._sockaddr, &rec->sgid);
-       rdma_gid2ip(&dgid._sockaddr, &rec->dgid);
+       rdma_gid2ip((struct sockaddr *)&sgid, &rec->sgid);
+       rdma_gid2ip((struct sockaddr *)&dgid, &rec->dgid);
 
        if (sgid._sockaddr.sa_family != dgid._sockaddr.sa_family)
                return -EINVAL;
@@ -743,7 +743,7 @@ int roce_resolve_route_from_path(struct sa_path_rec *rec,
        dev_addr.net = &init_net;
        dev_addr.sgid_attr = attr;
 
-       ret = addr_resolve(&sgid._sockaddr, &dgid._sockaddr,
+       ret = addr_resolve((struct sockaddr *)&sgid, (struct sockaddr *)&dgid,
                           &dev_addr, false, true, 0);
        if (ret)
                return ret;
@@ -815,22 +815,22 @@ int rdma_addr_find_l2_eth_by_grh(const union ib_gid *sgid,
        struct rdma_dev_addr dev_addr;
        struct resolve_cb_context ctx;
        union {
-               struct sockaddr     _sockaddr;
                struct sockaddr_in  _sockaddr_in;
                struct sockaddr_in6 _sockaddr_in6;
        } sgid_addr, dgid_addr;
        int ret;
 
-       rdma_gid2ip(&sgid_addr._sockaddr, sgid);
-       rdma_gid2ip(&dgid_addr._sockaddr, dgid);
+       rdma_gid2ip((struct sockaddr *)&sgid_addr, sgid);
+       rdma_gid2ip((struct sockaddr *)&dgid_addr, dgid);
 
        memset(&dev_addr, 0, sizeof(dev_addr));
        dev_addr.net = &init_net;
        dev_addr.sgid_attr = sgid_attr;
 
        init_completion(&ctx.comp);
-       ret = rdma_resolve_ip(&sgid_addr._sockaddr, &dgid_addr._sockaddr,
-                             &dev_addr, 1000, resolve_cb, true, &ctx);
+       ret = rdma_resolve_ip((struct sockaddr *)&sgid_addr,
+                             (struct sockaddr *)&dgid_addr, &dev_addr, 1000,
+                             resolve_cb, true, &ctx);
        if (ret)
                return ret;
 
index 98eadd3..69188cb 100644 (file)
@@ -1347,32 +1347,35 @@ static int nldev_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
        return 0;
 }
 
-static int nldev_get_sys_get_dumpit(struct sk_buff *skb,
-                                   struct netlink_callback *cb)
+static int nldev_sys_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
+                             struct netlink_ext_ack *extack)
 {
        struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
-       struct nlmsghdr *nlh;
+       struct sk_buff *msg;
        int err;
 
-       err = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
-                         nldev_policy, NULL);
+       err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
+                         nldev_policy, extack);
        if (err)
                return err;
 
-       nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
+       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
+       nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
                        RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
                                         RDMA_NLDEV_CMD_SYS_GET),
                        0, 0);
 
-       err = nla_put_u8(skb, RDMA_NLDEV_SYS_ATTR_NETNS_MODE,
+       err = nla_put_u8(msg, RDMA_NLDEV_SYS_ATTR_NETNS_MODE,
                         (u8)ib_devices_shared_netns);
        if (err) {
-               nlmsg_cancel(skb, nlh);
+               nlmsg_free(msg);
                return err;
        }
-
-       nlmsg_end(skb, nlh);
-       return skb->len;
+       nlmsg_end(msg, nlh);
+       return rdma_nl_unicast(msg, NETLINK_CB(skb).portid);
 }
 
 static int nldev_set_sys_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -1442,7 +1445,7 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
                .dump = nldev_res_get_pd_dumpit,
        },
        [RDMA_NLDEV_CMD_SYS_GET] = {
-               .dump = nldev_get_sys_get_dumpit,
+               .doit = nldev_sys_get_doit,
        },
        [RDMA_NLDEV_CMD_SYS_SET] = {
                .doit = nldev_set_sys_set_doit,
index 0a23048..e7ea819 100644 (file)
@@ -295,10 +295,11 @@ struct ib_umem *ib_umem_get(struct ib_udata *udata, unsigned long addr,
 
        while (npages) {
                down_read(&mm->mmap_sem);
-               ret = get_user_pages_longterm(cur_base,
+               ret = get_user_pages(cur_base,
                                     min_t(unsigned long, npages,
                                           PAGE_SIZE / sizeof (struct page *)),
-                                    gup_flags, page_list, NULL);
+                                    gup_flags | FOLL_LONGTERM,
+                                    page_list, NULL);
                if (ret < 0) {
                        up_read(&mm->mmap_sem);
                        goto umem_release;
index c7226cf..f962b5b 100644 (file)
@@ -152,7 +152,7 @@ static int ib_umem_notifier_invalidate_range_start(struct mmu_notifier *mn,
        struct ib_ucontext_per_mm *per_mm =
                container_of(mn, struct ib_ucontext_per_mm, mn);
 
-       if (range->blockable)
+       if (mmu_notifier_range_blockable(range))
                down_read(&per_mm->umem_rwsem);
        else if (!down_read_trylock(&per_mm->umem_rwsem))
                return -EAGAIN;
@@ -170,7 +170,8 @@ static int ib_umem_notifier_invalidate_range_start(struct mmu_notifier *mn,
        return rbt_ib_umem_for_each_in_range(&per_mm->umem_tree, range->start,
                                             range->end,
                                             invalidate_range_start_trampoline,
-                                            range->blockable, NULL);
+                                            mmu_notifier_range_blockable(range),
+                                            NULL);
 }
 
 static int invalidate_range_end_trampoline(struct ib_umem_odp *item, u64 start,
index 24b592c..02eee8e 100644 (file)
@@ -104,8 +104,9 @@ int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned long vaddr, size_t np
                            bool writable, struct page **pages)
 {
        int ret;
+       unsigned int gup_flags = FOLL_LONGTERM | (writable ? FOLL_WRITE : 0);
 
-       ret = get_user_pages_fast(vaddr, npages, writable, pages);
+       ret = get_user_pages_fast(vaddr, npages, gup_flags, pages);
        if (ret < 0)
                return ret;
 
index 169ffff..80b42d0 100644 (file)
@@ -154,7 +154,7 @@ bool mlx5_ib_devx_is_flow_counter(void *obj, u32 *counter_id)
  * must be considered upon checking for a valid object id.
  * For that the opcode of the creator command is encoded as part of the obj_id.
  */
-static u64 get_enc_obj_id(u16 opcode, u32 obj_id)
+static u64 get_enc_obj_id(u32 opcode, u32 obj_id)
 {
        return ((u64)opcode << 32) | obj_id;
 }
@@ -167,7 +167,9 @@ static u64 devx_get_obj_id(const void *in)
        switch (opcode) {
        case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
        case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
-               obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_GENERAL_OBJECT,
+               obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_GENERAL_OBJECT |
+                                       MLX5_GET(general_obj_in_cmd_hdr, in,
+                                                obj_type) << 16,
                                        MLX5_GET(general_obj_in_cmd_hdr, in,
                                                 obj_id));
                break;
@@ -1171,6 +1173,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
        struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
        u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
        struct devx_obj *obj;
+       u16 obj_type = 0;
        int err;
        int uid;
        u32 obj_id;
@@ -1230,7 +1233,11 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
        if (err)
                goto err_copy;
 
-       obj->obj_id = get_enc_obj_id(opcode, obj_id);
+       if (opcode == MLX5_CMD_OP_CREATE_GENERAL_OBJECT)
+               obj_type = MLX5_GET(general_obj_in_cmd_hdr, cmd_in, obj_type);
+
+       obj->obj_id = get_enc_obj_id(opcode | obj_type << 16, obj_id);
+
        return 0;
 
 err_copy:
index 112d2f3..8ff0e90 100644 (file)
@@ -472,7 +472,8 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
                goto out;
        }
 
-       ret = get_user_pages_fast(uaddr & PAGE_MASK, 1, FOLL_WRITE, pages);
+       ret = get_user_pages_fast(uaddr & PAGE_MASK, 1,
+                                 FOLL_WRITE | FOLL_LONGTERM, pages);
        if (ret < 0)
                goto out;
 
index 1d4ea13..8d3e36d 100644 (file)
@@ -83,7 +83,6 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
        struct iphdr ipv4;
        const struct ib_global_route *ib_grh;
        union {
-               struct sockaddr     _sockaddr;
                struct sockaddr_in  _sockaddr_in;
                struct sockaddr_in6 _sockaddr_in6;
        } sgid_addr, dgid_addr;
@@ -133,9 +132,9 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
                ipv4.tot_len = htons(0);
                ipv4.ttl = ib_grh->hop_limit;
                ipv4.protocol = nxthdr;
-               rdma_gid2ip(&sgid_addr._sockaddr, sgid);
+               rdma_gid2ip((struct sockaddr *)&sgid_addr, sgid);
                ipv4.saddr = sgid_addr._sockaddr_in.sin_addr.s_addr;
-               rdma_gid2ip(&dgid_addr._sockaddr, &ib_grh->dgid);
+               rdma_gid2ip((struct sockaddr*)&dgid_addr, &ib_grh->dgid);
                ipv4.daddr = dgid_addr._sockaddr_in.sin_addr.s_addr;
                memcpy((u8 *)ah->av + eth_sz, &ipv4, sizeof(struct iphdr));
        } else {
index 32674b2..5127e2e 100644 (file)
@@ -2499,7 +2499,6 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
        u16 vlan_id = 0xFFFF;
        u8 mac_addr[6], hdr_type;
        union {
-               struct sockaddr     _sockaddr;
                struct sockaddr_in  _sockaddr_in;
                struct sockaddr_in6 _sockaddr_in6;
        } sgid_addr, dgid_addr;
@@ -2542,8 +2541,8 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
 
        hdr_type = rdma_gid_attr_network_type(sgid_attr);
        if (hdr_type == RDMA_NETWORK_IPV4) {
-               rdma_gid2ip(&sgid_addr._sockaddr, &sgid_attr->gid);
-               rdma_gid2ip(&dgid_addr._sockaddr, &grh->dgid);
+               rdma_gid2ip((struct sockaddr *)&sgid_addr, &sgid_attr->gid);
+               rdma_gid2ip((struct sockaddr *)&dgid_addr, &grh->dgid);
                memcpy(&cmd->params.dgid[0],
                       &dgid_addr._sockaddr_in.sin_addr.s_addr, 4);
                memcpy(&cmd->params.sgid[0],
index 123ca8f..f712fb7 100644 (file)
@@ -114,10 +114,10 @@ int qib_get_user_pages(unsigned long start_page, size_t num_pages,
 
        down_read(&current->mm->mmap_sem);
        for (got = 0; got < num_pages; got += ret) {
-               ret = get_user_pages_longterm(start_page + got * PAGE_SIZE,
-                                             num_pages - got,
-                                             FOLL_WRITE | FOLL_FORCE,
-                                             p + got, NULL);
+               ret = get_user_pages(start_page + got * PAGE_SIZE,
+                                    num_pages - got,
+                                    FOLL_LONGTERM | FOLL_WRITE | FOLL_FORCE,
+                                    p + got, NULL);
                if (ret < 0) {
                        up_read(&current->mm->mmap_sem);
                        goto bail_release;
index ef19d39..0c20477 100644 (file)
@@ -670,7 +670,7 @@ static int qib_user_sdma_pin_pages(const struct qib_devdata *dd,
                else
                        j = npages;
 
-               ret = get_user_pages_fast(addr, j, 0, pages);
+               ret = get_user_pages_fast(addr, j, FOLL_LONGTERM, pages);
                if (ret != j) {
                        i = 0;
                        j = ret;
index da35d6f..e312f52 100644 (file)
@@ -143,10 +143,11 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
        ret = 0;
 
        while (npages) {
-               ret = get_user_pages_longterm(cur_base,
-                                       min_t(unsigned long, npages,
-                                       PAGE_SIZE / sizeof(struct page *)),
-                                       gup_flags, page_list, NULL);
+               ret = get_user_pages(cur_base,
+                                    min_t(unsigned long, npages,
+                                    PAGE_SIZE / sizeof(struct page *)),
+                                    gup_flags | FOLL_LONGTERM,
+                                    page_list, NULL);
 
                if (ret < 0)
                        goto out;
index f040d88..d1e25ab 100644 (file)
@@ -503,14 +503,13 @@ static int evdev_open(struct inode *inode, struct file *file)
 {
        struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev);
        unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev);
-       unsigned int size = sizeof(struct evdev_client) +
-                                       bufsize * sizeof(struct input_event);
        struct evdev_client *client;
        int error;
 
-       client = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
+       client = kzalloc(struct_size(client, buffer, bufsize),
+                        GFP_KERNEL | __GFP_NOWARN);
        if (!client)
-               client = vzalloc(size);
+               client = vzalloc(struct_size(client, buffer, bufsize));
        if (!client)
                return -ENOMEM;
 
index 52d7f55..8239882 100644 (file)
@@ -137,6 +137,17 @@ config KEYBOARD_ATKBD_RDI_KEYCODES
          right-hand column will be interpreted as the key shown in the
          left-hand column.
 
+config KEYBOARD_QT1050
+       tristate "Microchip AT42QT1050 Touch Sensor Chip"
+       depends on I2C
+       select REGMAP_I2C
+       help
+         Say Y here if you want to use Microchip AT42QT1050 QTouch
+         Sensor chip as input device.
+
+         To compile this driver as a module, choose M here:
+         the module will be called qt1050
+
 config KEYBOARD_QT1070
        tristate "Atmel AT42QT1070 Touch Sensor Chip"
        depends on I2C
@@ -194,7 +205,7 @@ config KEYBOARD_LKKBD
 
 config KEYBOARD_EP93XX
        tristate "EP93xx Matrix Keypad support"
-       depends on ARCH_EP93XX
+       depends on ARCH_EP93XX || COMPILE_TEST
        select INPUT_MATRIXKMAP
        help
          Say Y here to enable the matrix keypad on the Cirrus EP93XX.
index 182e929..f0291ca 100644 (file)
@@ -50,6 +50,7 @@ obj-$(CONFIG_KEYBOARD_OPENCORES)      += opencores-kbd.o
 obj-$(CONFIG_KEYBOARD_PMIC8XXX)                += pmic8xxx-keypad.o
 obj-$(CONFIG_KEYBOARD_PXA27x)          += pxa27x_keypad.o
 obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)   += pxa930_rotary.o
+obj-$(CONFIG_KEYBOARD_QT1050)           += qt1050.o
 obj-$(CONFIG_KEYBOARD_QT1070)           += qt1070.o
 obj-$(CONFIG_KEYBOARD_QT2160)          += qt2160.o
 obj-$(CONFIG_KEYBOARD_SAMSUNG)         += samsung-keypad.o
index 850bb25..3ad93e3 100644 (file)
@@ -401,6 +401,8 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
                if  (ps2_handle_response(&atkbd->ps2dev, data))
                        goto out;
 
+       pm_wakeup_event(&serio->dev, 0);
+
        if (!atkbd->enabled)
                goto out;
 
index f77b295..575dac5 100644 (file)
@@ -27,8 +27,7 @@
 #include <linux/io.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/slab.h>
-
-#include <mach/hardware.h>
+#include <linux/soc/cirrus/ep93xx.h>
 #include <linux/platform_data/keypad-ep93xx.h>
 
 /*
@@ -137,10 +136,7 @@ static void ep93xx_keypad_config(struct ep93xx_keypad *keypad)
        struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
        unsigned int val = 0;
 
-       if (pdata->flags & EP93XX_KEYPAD_KDIV)
-               clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV4);
-       else
-               clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV16);
+       clk_set_rate(keypad->clk, pdata->clk_rate);
 
        if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY)
                val |= KEY_INIT_DIS3KY;
diff --git a/drivers/input/keyboard/qt1050.c b/drivers/input/keyboard/qt1050.c
new file mode 100644 (file)
index 0000000..403060d
--- /dev/null
@@ -0,0 +1,598 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Microchip AT42QT1050 QTouch Sensor Controller
+ *
+ *  Copyright (C) 2019 Pengutronix, Marco Felsch <kernel@pengutronix.de>
+ *
+ *  Base on AT42QT1070 driver by:
+ *  Bo Shen <voice.shen@atmel.com>
+ *  Copyright (C) 2011 Atmel
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/log2.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+/* Chip ID */
+#define QT1050_CHIP_ID         0x00
+#define QT1050_CHIP_ID_VER     0x46
+
+/* Firmware version */
+#define QT1050_FW_VERSION      0x01
+
+/* Detection status */
+#define QT1050_DET_STATUS      0x02
+
+/* Key status */
+#define QT1050_KEY_STATUS      0x03
+
+/* Key Signals */
+#define QT1050_KEY_SIGNAL_0_MSB        0x06
+#define QT1050_KEY_SIGNAL_0_LSB        0x07
+#define QT1050_KEY_SIGNAL_1_MSB        0x08
+#define QT1050_KEY_SIGNAL_1_LSB        0x09
+#define QT1050_KEY_SIGNAL_2_MSB        0x0c
+#define QT1050_KEY_SIGNAL_2_LSB        0x0d
+#define QT1050_KEY_SIGNAL_3_MSB        0x0e
+#define QT1050_KEY_SIGNAL_3_LSB        0x0f
+#define QT1050_KEY_SIGNAL_4_MSB        0x10
+#define QT1050_KEY_SIGNAL_4_LSB        0x11
+
+/* Reference data */
+#define QT1050_REF_DATA_0_MSB  0x14
+#define QT1050_REF_DATA_0_LSB  0x15
+#define QT1050_REF_DATA_1_MSB  0x16
+#define QT1050_REF_DATA_1_LSB  0x17
+#define QT1050_REF_DATA_2_MSB  0x1a
+#define QT1050_REF_DATA_2_LSB  0x1b
+#define QT1050_REF_DATA_3_MSB  0x1c
+#define QT1050_REF_DATA_3_LSB  0x1d
+#define QT1050_REF_DATA_4_MSB  0x1e
+#define QT1050_REF_DATA_4_LSB  0x1f
+
+/* Negative threshold level */
+#define QT1050_NTHR_0          0x21
+#define QT1050_NTHR_1          0x22
+#define QT1050_NTHR_2          0x24
+#define QT1050_NTHR_3          0x25
+#define QT1050_NTHR_4          0x26
+
+/* Pulse / Scale  */
+#define QT1050_PULSE_SCALE_0   0x28
+#define QT1050_PULSE_SCALE_1   0x29
+#define QT1050_PULSE_SCALE_2   0x2b
+#define QT1050_PULSE_SCALE_3   0x2c
+#define QT1050_PULSE_SCALE_4   0x2d
+
+/* Detection integrator counter / AKS */
+#define QT1050_DI_AKS_0                0x2f
+#define QT1050_DI_AKS_1                0x30
+#define QT1050_DI_AKS_2                0x32
+#define QT1050_DI_AKS_3                0x33
+#define QT1050_DI_AKS_4                0x34
+
+/* Charge Share Delay */
+#define QT1050_CSD_0           0x36
+#define QT1050_CSD_1           0x37
+#define QT1050_CSD_2           0x39
+#define QT1050_CSD_3           0x3a
+#define QT1050_CSD_4           0x3b
+
+/* Low Power Mode */
+#define QT1050_LPMODE          0x3d
+
+/* Calibration and Reset */
+#define QT1050_RES_CAL         0x3f
+#define QT1050_RES_CAL_RESET           BIT(7)
+#define QT1050_RES_CAL_CALIBRATE       BIT(1)
+
+#define QT1050_MAX_KEYS                5
+#define QT1050_RESET_TIME      255
+
+struct qt1050_key_regs {
+       unsigned int nthr;
+       unsigned int pulse_scale;
+       unsigned int di_aks;
+       unsigned int csd;
+};
+
+struct qt1050_key {
+       u32 num;
+       u32 charge_delay;
+       u32 thr_cnt;
+       u32 samples;
+       u32 scale;
+       u32 keycode;
+};
+
+struct qt1050_priv {
+       struct i2c_client       *client;
+       struct input_dev        *input;
+       struct regmap           *regmap;
+       struct qt1050_key       keys[QT1050_MAX_KEYS];
+       unsigned short          keycodes[QT1050_MAX_KEYS];
+       u8                      reg_keys;
+       u8                      last_keys;
+};
+
+static const struct qt1050_key_regs qt1050_key_regs_data[] = {
+       {
+               .nthr = QT1050_NTHR_0,
+               .pulse_scale = QT1050_PULSE_SCALE_0,
+               .di_aks = QT1050_DI_AKS_0,
+               .csd = QT1050_CSD_0,
+       }, {
+               .nthr = QT1050_NTHR_1,
+               .pulse_scale = QT1050_PULSE_SCALE_1,
+               .di_aks = QT1050_DI_AKS_1,
+               .csd = QT1050_CSD_1,
+       }, {
+               .nthr = QT1050_NTHR_2,
+               .pulse_scale = QT1050_PULSE_SCALE_2,
+               .di_aks = QT1050_DI_AKS_2,
+               .csd = QT1050_CSD_2,
+       }, {
+               .nthr = QT1050_NTHR_3,
+               .pulse_scale = QT1050_PULSE_SCALE_3,
+               .di_aks = QT1050_DI_AKS_3,
+               .csd = QT1050_CSD_3,
+       }, {
+               .nthr = QT1050_NTHR_4,
+               .pulse_scale = QT1050_PULSE_SCALE_4,
+               .di_aks = QT1050_DI_AKS_4,
+               .csd = QT1050_CSD_4,
+       }
+};
+
+static bool qt1050_volatile_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case QT1050_DET_STATUS:
+       case QT1050_KEY_STATUS:
+       case QT1050_KEY_SIGNAL_0_MSB:
+       case QT1050_KEY_SIGNAL_0_LSB:
+       case QT1050_KEY_SIGNAL_1_MSB:
+       case QT1050_KEY_SIGNAL_1_LSB:
+       case QT1050_KEY_SIGNAL_2_MSB:
+       case QT1050_KEY_SIGNAL_2_LSB:
+       case QT1050_KEY_SIGNAL_3_MSB:
+       case QT1050_KEY_SIGNAL_3_LSB:
+       case QT1050_KEY_SIGNAL_4_MSB:
+       case QT1050_KEY_SIGNAL_4_LSB:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static const struct regmap_range qt1050_readable_ranges[] = {
+       regmap_reg_range(QT1050_CHIP_ID, QT1050_KEY_STATUS),
+       regmap_reg_range(QT1050_KEY_SIGNAL_0_MSB, QT1050_KEY_SIGNAL_1_LSB),
+       regmap_reg_range(QT1050_KEY_SIGNAL_2_MSB, QT1050_KEY_SIGNAL_4_LSB),
+       regmap_reg_range(QT1050_REF_DATA_0_MSB, QT1050_REF_DATA_1_LSB),
+       regmap_reg_range(QT1050_REF_DATA_2_MSB, QT1050_REF_DATA_4_LSB),
+       regmap_reg_range(QT1050_NTHR_0, QT1050_NTHR_1),
+       regmap_reg_range(QT1050_NTHR_2, QT1050_NTHR_4),
+       regmap_reg_range(QT1050_PULSE_SCALE_0, QT1050_PULSE_SCALE_1),
+       regmap_reg_range(QT1050_PULSE_SCALE_2, QT1050_PULSE_SCALE_4),
+       regmap_reg_range(QT1050_DI_AKS_0, QT1050_DI_AKS_1),
+       regmap_reg_range(QT1050_DI_AKS_2, QT1050_DI_AKS_4),
+       regmap_reg_range(QT1050_CSD_0, QT1050_CSD_1),
+       regmap_reg_range(QT1050_CSD_2, QT1050_RES_CAL),
+};
+
+static const struct regmap_access_table qt1050_readable_table = {
+       .yes_ranges = qt1050_readable_ranges,
+       .n_yes_ranges = ARRAY_SIZE(qt1050_readable_ranges),
+};
+
+static const struct regmap_range qt1050_writeable_ranges[] = {
+       regmap_reg_range(QT1050_NTHR_0, QT1050_NTHR_1),
+       regmap_reg_range(QT1050_NTHR_2, QT1050_NTHR_4),
+       regmap_reg_range(QT1050_PULSE_SCALE_0, QT1050_PULSE_SCALE_1),
+       regmap_reg_range(QT1050_PULSE_SCALE_2, QT1050_PULSE_SCALE_4),
+       regmap_reg_range(QT1050_DI_AKS_0, QT1050_DI_AKS_1),
+       regmap_reg_range(QT1050_DI_AKS_2, QT1050_DI_AKS_4),
+       regmap_reg_range(QT1050_CSD_0, QT1050_CSD_1),
+       regmap_reg_range(QT1050_CSD_2, QT1050_RES_CAL),
+};
+
+static const struct regmap_access_table qt1050_writeable_table = {
+       .yes_ranges = qt1050_writeable_ranges,
+       .n_yes_ranges = ARRAY_SIZE(qt1050_writeable_ranges),
+};
+
+static struct regmap_config qt1050_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = QT1050_RES_CAL,
+
+       .cache_type = REGCACHE_RBTREE,
+
+       .wr_table = &qt1050_writeable_table,
+       .rd_table = &qt1050_readable_table,
+       .volatile_reg = qt1050_volatile_reg,
+};
+
+static bool qt1050_identify(struct qt1050_priv *ts)
+{
+       unsigned int val;
+       int err;
+
+       /* Read Chip ID */
+       regmap_read(ts->regmap, QT1050_CHIP_ID, &val);
+       if (val != QT1050_CHIP_ID_VER) {
+               dev_err(&ts->client->dev, "ID %d not supported\n", val);
+               return false;
+       }
+
+       /* Read firmware version */
+       err = regmap_read(ts->regmap, QT1050_FW_VERSION, &val);
+       if (err) {
+               dev_err(&ts->client->dev, "could not read the firmware version\n");
+               return false;
+       }
+
+       dev_info(&ts->client->dev, "AT42QT1050 firmware version %1d.%1d\n",
+                val >> 4, val & 0xf);
+
+       return true;
+}
+
+static irqreturn_t qt1050_irq_threaded(int irq, void *dev_id)
+{
+       struct qt1050_priv *ts = dev_id;
+       struct input_dev *input = ts->input;
+       unsigned long new_keys, changed;
+       unsigned int val;
+       int i, err;
+
+       /* Read the detected status register, thus clearing interrupt */
+       err = regmap_read(ts->regmap, QT1050_DET_STATUS, &val);
+       if (err) {
+               dev_err(&ts->client->dev, "Fail to read detection status: %d\n",
+                       err);
+               return IRQ_NONE;
+       }
+
+       /* Read which key changed, keys are not continuous */
+       err = regmap_read(ts->regmap, QT1050_KEY_STATUS, &val);
+       if (err) {
+               dev_err(&ts->client->dev,
+                       "Fail to determine the key status: %d\n", err);
+               return IRQ_NONE;
+       }
+       new_keys = (val & 0x70) >> 2 | (val & 0x6) >> 1;
+       changed = ts->last_keys ^ new_keys;
+       /* Report registered keys only */
+       changed &= ts->reg_keys;
+
+       for_each_set_bit(i, &changed, QT1050_MAX_KEYS)
+               input_report_key(input, ts->keys[i].keycode,
+                                test_bit(i, &new_keys));
+
+       ts->last_keys = new_keys;
+       input_sync(input);
+
+       return IRQ_HANDLED;
+}
+
+static const struct qt1050_key_regs *qt1050_get_key_regs(int key_num)
+{
+       return &qt1050_key_regs_data[key_num];
+}
+
+static int qt1050_set_key(struct regmap *map, int number, int on)
+{
+       const struct qt1050_key_regs *key_regs;
+
+       key_regs = qt1050_get_key_regs(number);
+
+       return regmap_update_bits(map, key_regs->di_aks, 0xfc,
+                                 on ? BIT(4) : 0x00);
+}
+
+static int qt1050_apply_fw_data(struct qt1050_priv *ts)
+{
+       struct regmap *map = ts->regmap;
+       struct qt1050_key *button = &ts->keys[0];
+       const struct qt1050_key_regs *key_regs;
+       int i, err;
+
+       /* Disable all keys and enable only the specified ones */
+       for (i = 0; i < QT1050_MAX_KEYS; i++) {
+               err = qt1050_set_key(map, i, 0);
+               if (err)
+                       return err;
+       }
+
+       for (i = 0; i < QT1050_MAX_KEYS; i++, button++) {
+               /* Keep KEY_RESERVED keys off */
+               if (button->keycode == KEY_RESERVED)
+                       continue;
+
+               err = qt1050_set_key(map, button->num, 1);
+               if (err)
+                       return err;
+
+               key_regs = qt1050_get_key_regs(button->num);
+
+               err = regmap_write(map, key_regs->pulse_scale,
+                                  (button->samples << 4) | (button->scale));
+               if (err)
+                       return err;
+               err = regmap_write(map, key_regs->csd, button->charge_delay);
+               if (err)
+                       return err;
+               err = regmap_write(map, key_regs->nthr, button->thr_cnt);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+static int qt1050_parse_fw(struct qt1050_priv *ts)
+{
+       struct device *dev = &ts->client->dev;
+       struct fwnode_handle *child;
+       int nbuttons;
+
+       nbuttons = device_get_child_node_count(dev);
+       if (nbuttons == 0 || nbuttons > QT1050_MAX_KEYS)
+               return -ENODEV;
+
+       device_for_each_child_node(dev, child) {
+               struct qt1050_key button;
+
+               /* Required properties */
+               if (fwnode_property_read_u32(child, "linux,code",
+                                            &button.keycode)) {
+                       dev_err(dev, "Button without keycode\n");
+                       goto err;
+               }
+               if (button.keycode >= KEY_MAX) {
+                       dev_err(dev, "Invalid keycode 0x%x\n",
+                               button.keycode);
+                       goto err;
+               }
+
+               if (fwnode_property_read_u32(child, "reg",
+                                            &button.num)) {
+                       dev_err(dev, "Button without pad number\n");
+                       goto err;
+               }
+               if (button.num < 0 || button.num > QT1050_MAX_KEYS - 1)
+                       goto err;
+
+               ts->reg_keys |= BIT(button.num);
+
+               /* Optional properties */
+               if (fwnode_property_read_u32(child,
+                                            "microchip,pre-charge-time-ns",
+                                            &button.charge_delay)) {
+                       button.charge_delay = 0;
+               } else {
+                       if (button.charge_delay % 2500 == 0)
+                               button.charge_delay =
+                                       button.charge_delay / 2500;
+                       else
+                               button.charge_delay = 0;
+               }
+
+               if (fwnode_property_read_u32(child, "microchip,average-samples",
+                                        &button.samples)) {
+                       button.samples = 0;
+               } else {
+                       if (is_power_of_2(button.samples))
+                               button.samples = ilog2(button.samples);
+                       else
+                               button.samples = 0;
+               }
+
+               if (fwnode_property_read_u32(child, "microchip,average-scaling",
+                                            &button.scale)) {
+                       button.scale = 0;
+               } else {
+                       if (is_power_of_2(button.scale))
+                               button.scale = ilog2(button.scale);
+                       else
+                               button.scale = 0;
+
+               }
+
+               if (fwnode_property_read_u32(child, "microchip,threshold",
+                                        &button.thr_cnt)) {
+                       button.thr_cnt = 20;
+               } else {
+                       if (button.thr_cnt > 255)
+                               button.thr_cnt = 20;
+               }
+
+               ts->keys[button.num] = button;
+       }
+
+       return 0;
+
+err:
+       fwnode_handle_put(child);
+       return -EINVAL;
+}
+
+static int qt1050_probe(struct i2c_client *client)
+{
+       struct qt1050_priv *ts;
+       struct input_dev *input;
+       struct device *dev = &client->dev;
+       struct regmap *map;
+       unsigned int status, i;
+       int err;
+
+       /* Check basic functionality */
+       err = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE);
+       if (!err) {
+               dev_err(&client->dev, "%s adapter not supported\n",
+                       dev_driver_string(&client->adapter->dev));
+               return -ENODEV;
+       }
+
+       if (!client->irq) {
+               dev_err(dev, "assign a irq line to this device\n");
+               return -EINVAL;
+       }
+
+       ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
+       if (!ts)
+               return -ENOMEM;
+
+       input = devm_input_allocate_device(dev);
+       if (!input)
+               return -ENOMEM;
+
+       map = devm_regmap_init_i2c(client, &qt1050_regmap_config);
+       if (IS_ERR(map))
+               return PTR_ERR(map);
+
+       ts->client = client;
+       ts->input = input;
+       ts->regmap = map;
+
+       i2c_set_clientdata(client, ts);
+
+       /* Identify the qt1050 chip */
+       if (!qt1050_identify(ts))
+               return -ENODEV;
+
+       /* Get pdata */
+       err = qt1050_parse_fw(ts);
+       if (err) {
+               dev_err(dev, "Failed to parse firmware: %d\n", err);
+               return err;
+       }
+
+       input->name = "AT42QT1050 QTouch Sensor";
+       input->dev.parent = &client->dev;
+       input->id.bustype = BUS_I2C;
+
+       /* Add the keycode */
+       input->keycode = ts->keycodes;
+       input->keycodesize = sizeof(ts->keycodes[0]);
+       input->keycodemax = QT1050_MAX_KEYS;
+
+       __set_bit(EV_KEY, input->evbit);
+       for (i = 0; i < QT1050_MAX_KEYS; i++) {
+               ts->keycodes[i] = ts->keys[i].keycode;
+               __set_bit(ts->keycodes[i], input->keybit);
+       }
+
+       /* Trigger re-calibration */
+       err = regmap_update_bits(ts->regmap, QT1050_RES_CAL, 0x7f,
+                                QT1050_RES_CAL_CALIBRATE);
+       if (err) {
+               dev_err(dev, "Trigger calibration failed: %d\n", err);
+               return err;
+       }
+       err = regmap_read_poll_timeout(ts->regmap, QT1050_DET_STATUS, status,
+                                status >> 7 == 1, 10000, 200000);
+       if (err) {
+               dev_err(dev, "Calibration failed: %d\n", err);
+               return err;
+       }
+
+       /* Soft reset to set defaults */
+       err = regmap_update_bits(ts->regmap, QT1050_RES_CAL,
+                                QT1050_RES_CAL_RESET, QT1050_RES_CAL_RESET);
+       if (err) {
+               dev_err(dev, "Trigger soft reset failed: %d\n", err);
+               return err;
+       }
+       msleep(QT1050_RESET_TIME);
+
+       /* Set pdata */
+       err = qt1050_apply_fw_data(ts);
+       if (err) {
+               dev_err(dev, "Failed to set firmware data: %d\n", err);
+               return err;
+       }
+
+       err = devm_request_threaded_irq(dev, client->irq, NULL,
+                                       qt1050_irq_threaded, IRQF_ONESHOT,
+                                       "qt1050", ts);
+       if (err) {
+               dev_err(&client->dev, "Failed to request irq: %d\n", err);
+               return err;
+       }
+
+       /* Clear #CHANGE line */
+       err = regmap_read(ts->regmap, QT1050_DET_STATUS, &status);
+       if (err) {
+               dev_err(dev, "Failed to clear #CHANGE line level: %d\n", err);
+               return err;
+       }
+
+       /* Register the input device */
+       err = input_register_device(ts->input);
+       if (err) {
+               dev_err(&client->dev, "Failed to register input device: %d\n",
+                       err);
+               return err;
+       }
+
+       return 0;
+}
+
+static int __maybe_unused qt1050_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct qt1050_priv *ts = i2c_get_clientdata(client);
+
+       disable_irq(client->irq);
+
+       /*
+        * Set measurement interval to 1s (125 x 8ms) if wakeup is allowed
+        * else turn off. The 1s interval seems to be a good compromise between
+        * low power and response time.
+        */
+       return regmap_write(ts->regmap, QT1050_LPMODE,
+                           device_may_wakeup(dev) ? 125 : 0);
+}
+
+static int __maybe_unused qt1050_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct qt1050_priv *ts = i2c_get_clientdata(client);
+
+       enable_irq(client->irq);
+
+       /* Set measurement interval back to 16ms (2 x 8ms) */
+       return regmap_write(ts->regmap, QT1050_LPMODE, 2);
+}
+
+static SIMPLE_DEV_PM_OPS(qt1050_pm_ops, qt1050_suspend, qt1050_resume);
+
+static const struct of_device_id __maybe_unused qt1050_of_match[] = {
+       { .compatible = "microchip,qt1050", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, qt1050_of_match);
+
+static struct i2c_driver qt1050_driver = {
+       .driver = {
+               .name = "qt1050",
+               .of_match_table = of_match_ptr(qt1050_of_match),
+               .pm = &qt1050_pm_ops,
+       },
+       .probe_new = qt1050_probe,
+};
+
+module_i2c_driver(qt1050_driver);
+
+MODULE_AUTHOR("Marco Felsch <kernel@pengutronix.de");
+MODULE_DESCRIPTION("Driver for AT42QT1050 QTouch sensor");
+MODULE_LICENSE("GPL v2");
index 4c67cf3..5342d8d 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 
@@ -167,28 +168,9 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
        }
 
        device_init_wakeup(&pdev->dev, pdata->wakeup);
-
-       return 0;
-}
-
-static int __maybe_unused imx_snvs_pwrkey_suspend(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
-
-       if (device_may_wakeup(&pdev->dev))
-               enable_irq_wake(pdata->irq);
-
-       return 0;
-}
-
-static int __maybe_unused imx_snvs_pwrkey_resume(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
-
-       if (device_may_wakeup(&pdev->dev))
-               disable_irq_wake(pdata->irq);
+       error = dev_pm_set_wake_irq(&pdev->dev, pdata->irq);
+       if (error)
+               dev_err(&pdev->dev, "irq wake enable failed.\n");
 
        return 0;
 }
@@ -199,13 +181,9 @@ static const struct of_device_id imx_snvs_pwrkey_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, imx_snvs_pwrkey_ids);
 
-static SIMPLE_DEV_PM_OPS(imx_snvs_pwrkey_pm_ops, imx_snvs_pwrkey_suspend,
-                               imx_snvs_pwrkey_resume);
-
 static struct platform_driver imx_snvs_pwrkey_driver = {
        .driver = {
                .name = "snvs_pwrkey",
-               .pm     = &imx_snvs_pwrkey_pm_ops,
                .of_match_table = imx_snvs_pwrkey_ids,
        },
        .probe = imx_snvs_pwrkey_probe,
index 57272df..df3eec7 100644 (file)
@@ -46,6 +46,7 @@
 #define CONTINUE_TIME_SEL(x)   ((x) << 16) /* 4 bits */
 #define KEY_MODE_SEL(x)                ((x) << 12) /* 2 bits */
 #define LEVELA_B_CNT(x)                ((x) << 8)  /* 4 bits */
+#define HOLD_KEY_EN(x)         ((x) << 7)
 #define HOLD_EN(x)             ((x) << 6)
 #define LEVELB_VOL(x)          ((x) << 4)  /* 2 bits */
 #define SAMPLE_RATE(x)         ((x) << 2)  /* 2 bits */
 #define        CHAN0_KEYDOWN_IRQ       BIT(1)
 #define CHAN0_DATA_IRQ         BIT(0)
 
+/* struct lradc_variant - Describe sun4i-a10-lradc-keys hardware variant
+ * @divisor_numerator:         The numerator of lradc Vref internally divisor
+ * @divisor_denominator:       The denominator of lradc Vref internally divisor
+ */
+struct lradc_variant {
+       u8 divisor_numerator;
+       u8 divisor_denominator;
+};
+
+static const struct lradc_variant lradc_variant_a10 = {
+       .divisor_numerator = 2,
+       .divisor_denominator = 3
+};
+
+static const struct lradc_variant r_lradc_variant_a83t = {
+       .divisor_numerator = 3,
+       .divisor_denominator = 4
+};
+
 struct sun4i_lradc_keymap {
        u32 voltage;
        u32 keycode;
@@ -74,6 +94,7 @@ struct sun4i_lradc_data {
        void __iomem *base;
        struct regulator *vref_supply;
        struct sun4i_lradc_keymap *chan0_map;
+       const struct lradc_variant *variant;
        u32 chan0_map_count;
        u32 chan0_keycode;
        u32 vref;
@@ -128,9 +149,9 @@ static int sun4i_lradc_open(struct input_dev *dev)
        if (error)
                return error;
 
-       /* lradc Vref internally is divided by 2/3 */
-       lradc->vref = regulator_get_voltage(lradc->vref_supply) * 2 / 3;
-
+       lradc->vref = regulator_get_voltage(lradc->vref_supply) *
+                     lradc->variant->divisor_numerator /
+                     lradc->variant->divisor_denominator;
        /*
         * Set sample time to 4 ms / 250 Hz. Wait 2 * 4 ms for key to
         * stabilize on press, wait (1 + 1) * 4 ms for key release
@@ -222,6 +243,12 @@ static int sun4i_lradc_probe(struct platform_device *pdev)
        if (error)
                return error;
 
+       lradc->variant = of_device_get_match_data(&pdev->dev);
+       if (!lradc->variant) {
+               dev_err(&pdev->dev, "Missing sun4i-a10-lradc-keys variant\n");
+               return -EINVAL;
+       }
+
        lradc->vref_supply = devm_regulator_get(dev, "vref");
        if (IS_ERR(lradc->vref_supply))
                return PTR_ERR(lradc->vref_supply);
@@ -265,7 +292,10 @@ static int sun4i_lradc_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id sun4i_lradc_of_match[] = {
-       { .compatible = "allwinner,sun4i-a10-lradc-keys", },
+       { .compatible = "allwinner,sun4i-a10-lradc-keys",
+               .data = &lradc_variant_a10 },
+       { .compatible = "allwinner,sun8i-a83t-r-lradc",
+               .data = &r_lradc_variant_a83t },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_lradc_of_match);
index e15ed1b..54d36f9 100644 (file)
@@ -190,6 +190,15 @@ config INPUT_M68K_BEEP
        tristate "M68k Beeper support"
        depends on M68K
 
+config INPUT_MAX77650_ONKEY
+       tristate "Maxim MAX77650 ONKEY support"
+       depends on MFD_MAX77650
+       help
+         Support the ONKEY of the MAX77650 PMIC as an input device.
+
+         To compile this driver as a module, choose M here: the module
+         will be called max77650-onkey.
+
 config INPUT_MAX77693_HAPTIC
        tristate "MAXIM MAX77693/MAX77843 haptic controller support"
        depends on (MFD_MAX77693 || MFD_MAX77843) && PWM
@@ -290,6 +299,18 @@ config INPUT_GPIO_DECODER
         To compile this driver as a module, choose M here: the module
         will be called gpio_decoder.
 
+config INPUT_GPIO_VIBRA
+       tristate "GPIO vibrator support"
+       depends on GPIOLIB || COMPILE_TEST
+       select INPUT_FF_MEMLESS
+       help
+         Say Y here to get support for GPIO based vibrator devices.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the module will be
+         called gpio-vibra.
+
 config INPUT_IXP4XX_BEEPER
        tristate "IXP4XX Beeper support"
        depends on ARCH_IXP4XX
index b936c5b..8fd187f 100644 (file)
@@ -36,6 +36,7 @@ obj-$(CONFIG_INPUT_DRV2667_HAPTICS)   += drv2667.o
 obj-$(CONFIG_INPUT_GP2A)               += gp2ap002a00f.o
 obj-$(CONFIG_INPUT_GPIO_BEEPER)                += gpio-beeper.o
 obj-$(CONFIG_INPUT_GPIO_DECODER)       += gpio_decoder.o
+obj-$(CONFIG_INPUT_GPIO_VIBRA)         += gpio-vibra.o
 obj-$(CONFIG_INPUT_HISI_POWERKEY)      += hisi_powerkey.o
 obj-$(CONFIG_HP_SDC_RTC)               += hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IMS_PCU)            += ims-pcu.o
@@ -43,6 +44,7 @@ obj-$(CONFIG_INPUT_IXP4XX_BEEPER)     += ixp4xx-beeper.o
 obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)     += keyspan_remote.o
 obj-$(CONFIG_INPUT_KXTJ9)              += kxtj9.o
 obj-$(CONFIG_INPUT_M68K_BEEP)          += m68kspkr.o
+obj-$(CONFIG_INPUT_MAX77650_ONKEY)     += max77650-onkey.o
 obj-$(CONFIG_INPUT_MAX77693_HAPTIC)    += max77693-haptic.o
 obj-$(CONFIG_INPUT_MAX8925_ONKEY)      += max8925_onkey.o
 obj-$(CONFIG_INPUT_MAX8997_HAPTIC)     += max8997_haptic.o
diff --git a/drivers/input/misc/gpio-vibra.c b/drivers/input/misc/gpio-vibra.c
new file mode 100644 (file)
index 0000000..f79f755
--- /dev/null
@@ -0,0 +1,207 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  GPIO vibrator driver
+ *
+ *  Copyright (C) 2019 Luca Weiss <luca@z3ntu.xyz>
+ *
+ *  Based on PWM vibrator driver:
+ *  Copyright (C) 2017 Collabora Ltd.
+ *
+ *  Based on previous work from:
+ *  Copyright (C) 2012 Dmitry Torokhov <dmitry.torokhov@gmail.com>
+ *
+ *  Based on PWM beeper driver:
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+struct gpio_vibrator {
+       struct input_dev *input;
+       struct gpio_desc *gpio;
+       struct regulator *vcc;
+
+       struct work_struct play_work;
+       bool running;
+       bool vcc_on;
+};
+
+static int gpio_vibrator_start(struct gpio_vibrator *vibrator)
+{
+       struct device *pdev = vibrator->input->dev.parent;
+       int err;
+
+       if (!vibrator->vcc_on) {
+               err = regulator_enable(vibrator->vcc);
+               if (err) {
+                       dev_err(pdev, "failed to enable regulator: %d\n", err);
+                       return err;
+               }
+               vibrator->vcc_on = true;
+       }
+
+       gpiod_set_value_cansleep(vibrator->gpio, 1);
+
+       return 0;
+}
+
+static void gpio_vibrator_stop(struct gpio_vibrator *vibrator)
+{
+       gpiod_set_value_cansleep(vibrator->gpio, 0);
+
+       if (vibrator->vcc_on) {
+               regulator_disable(vibrator->vcc);
+               vibrator->vcc_on = false;
+       }
+}
+
+static void gpio_vibrator_play_work(struct work_struct *work)
+{
+       struct gpio_vibrator *vibrator =
+               container_of(work, struct gpio_vibrator, play_work);
+
+       if (vibrator->running)
+               gpio_vibrator_start(vibrator);
+       else
+               gpio_vibrator_stop(vibrator);
+}
+
+static int gpio_vibrator_play_effect(struct input_dev *dev, void *data,
+                                    struct ff_effect *effect)
+{
+       struct gpio_vibrator *vibrator = input_get_drvdata(dev);
+       int level;
+
+       level = effect->u.rumble.strong_magnitude;
+       if (!level)
+               level = effect->u.rumble.weak_magnitude;
+
+       vibrator->running = level;
+       schedule_work(&vibrator->play_work);
+
+       return 0;
+}
+
+static void gpio_vibrator_close(struct input_dev *input)
+{
+       struct gpio_vibrator *vibrator = input_get_drvdata(input);
+
+       cancel_work_sync(&vibrator->play_work);
+       gpio_vibrator_stop(vibrator);
+       vibrator->running = false;
+}
+
+static int gpio_vibrator_probe(struct platform_device *pdev)
+{
+       struct gpio_vibrator *vibrator;
+       int err;
+
+       vibrator = devm_kzalloc(&pdev->dev, sizeof(*vibrator), GFP_KERNEL);
+       if (!vibrator)
+               return -ENOMEM;
+
+       vibrator->input = devm_input_allocate_device(&pdev->dev);
+       if (!vibrator->input)
+               return -ENOMEM;
+
+       vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc");
+       err = PTR_ERR_OR_ZERO(vibrator->vcc);
+       if (err) {
+               if (err != -EPROBE_DEFER)
+                       dev_err(&pdev->dev, "Failed to request regulator: %d\n",
+                               err);
+               return err;
+       }
+
+       vibrator->gpio = devm_gpiod_get(&pdev->dev, "enable", GPIOD_OUT_LOW);
+       err = PTR_ERR_OR_ZERO(vibrator->gpio);
+       if (err) {
+               if (err != -EPROBE_DEFER)
+                       dev_err(&pdev->dev, "Failed to request main gpio: %d\n",
+                               err);
+               return err;
+       }
+
+       INIT_WORK(&vibrator->play_work, gpio_vibrator_play_work);
+
+       vibrator->input->name = "gpio-vibrator";
+       vibrator->input->id.bustype = BUS_HOST;
+       vibrator->input->close = gpio_vibrator_close;
+
+       input_set_drvdata(vibrator->input, vibrator);
+       input_set_capability(vibrator->input, EV_FF, FF_RUMBLE);
+
+       err = input_ff_create_memless(vibrator->input, NULL,
+                                     gpio_vibrator_play_effect);
+       if (err) {
+               dev_err(&pdev->dev, "Couldn't create FF dev: %d\n", err);
+               return err;
+       }
+
+       err = input_register_device(vibrator->input);
+       if (err) {
+               dev_err(&pdev->dev, "Couldn't register input dev: %d\n", err);
+               return err;
+       }
+
+       platform_set_drvdata(pdev, vibrator);
+
+       return 0;
+}
+
+static int __maybe_unused gpio_vibrator_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct gpio_vibrator *vibrator = platform_get_drvdata(pdev);
+
+       cancel_work_sync(&vibrator->play_work);
+       if (vibrator->running)
+               gpio_vibrator_stop(vibrator);
+
+       return 0;
+}
+
+static int __maybe_unused gpio_vibrator_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct gpio_vibrator *vibrator = platform_get_drvdata(pdev);
+
+       if (vibrator->running)
+               gpio_vibrator_start(vibrator);
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(gpio_vibrator_pm_ops,
+                        gpio_vibrator_suspend, gpio_vibrator_resume);
+
+#ifdef CONFIG_OF
+static const struct of_device_id gpio_vibra_dt_match_table[] = {
+       { .compatible = "gpio-vibrator" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, gpio_vibra_dt_match_table);
+#endif
+
+static struct platform_driver gpio_vibrator_driver = {
+       .probe  = gpio_vibrator_probe,
+       .driver = {
+               .name   = "gpio-vibrator",
+               .pm     = &gpio_vibrator_pm_ops,
+               .of_match_table = of_match_ptr(gpio_vibra_dt_match_table),
+       },
+};
+module_platform_driver(gpio_vibrator_driver);
+
+MODULE_AUTHOR("Luca Weiss <luca@z3ntu.xy>");
+MODULE_DESCRIPTION("GPIO vibrator driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-vibrator");
index 1fe149f..4776273 100644 (file)
@@ -30,6 +30,8 @@ MODULE_ALIAS("platform:ixp4xx-beeper");
 
 static DEFINE_SPINLOCK(beep_lock);
 
+static int ixp4xx_timer2_irq;
+
 static void ixp4xx_spkr_control(unsigned int pin, unsigned int count)
 {
        unsigned long flags;
@@ -90,6 +92,7 @@ static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id)
 static int ixp4xx_spkr_probe(struct platform_device *dev)
 {
        struct input_dev *input_dev;
+       int irq;
        int err;
 
        input_dev = input_allocate_device();
@@ -110,15 +113,22 @@ static int ixp4xx_spkr_probe(struct platform_device *dev)
        input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
        input_dev->event = ixp4xx_spkr_event;
 
+       irq = platform_get_irq(dev, 0);
+       if (irq < 0) {
+               err = irq;
+               goto err_free_device;
+       }
+
        err = gpio_request(dev->id, "ixp4-beeper");
        if (err)
                goto err_free_device;
 
-       err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt,
+       err = request_irq(irq, &ixp4xx_spkr_interrupt,
                          IRQF_NO_SUSPEND, "ixp4xx-beeper",
                          (void *) dev->id);
        if (err)
                goto err_free_gpio;
+       ixp4xx_timer2_irq = irq;
 
        err = input_register_device(input_dev);
        if (err)
@@ -129,7 +139,7 @@ static int ixp4xx_spkr_probe(struct platform_device *dev)
        return 0;
 
  err_free_irq:
-       free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id);
+       free_irq(irq, (void *)dev->id);
  err_free_gpio:
        gpio_free(dev->id);
  err_free_device:
@@ -146,10 +156,10 @@ static int ixp4xx_spkr_remove(struct platform_device *dev)
        input_unregister_device(input_dev);
 
        /* turn the speaker off */
-       disable_irq(IRQ_IXP4XX_TIMER2);
+       disable_irq(ixp4xx_timer2_irq);
        ixp4xx_spkr_control(pin, 0);
 
-       free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id);
+       free_irq(ixp4xx_timer2_irq, (void *)dev->id);
        gpio_free(dev->id);
 
        return 0;
@@ -161,7 +171,7 @@ static void ixp4xx_spkr_shutdown(struct platform_device *dev)
        unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
 
        /* turn off the speaker */
-       disable_irq(IRQ_IXP4XX_TIMER2);
+       disable_irq(ixp4xx_timer2_irq);
        ixp4xx_spkr_control(pin, 0);
 }
 
diff --git a/drivers/input/misc/max77650-onkey.c b/drivers/input/misc/max77650-onkey.c
new file mode 100644 (file)
index 0000000..fbf6caa
--- /dev/null
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// ONKEY driver for MAXIM 77650/77651 charger/power-supply.
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/max77650.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define MAX77650_ONKEY_MODE_MASK       BIT(3)
+#define MAX77650_ONKEY_MODE_PUSH       0x00
+#define MAX77650_ONKEY_MODE_SLIDE      BIT(3)
+
+struct max77650_onkey {
+       struct input_dev *input;
+       unsigned int code;
+};
+
+static irqreturn_t max77650_onkey_falling(int irq, void *data)
+{
+       struct max77650_onkey *onkey = data;
+
+       input_report_key(onkey->input, onkey->code, 0);
+       input_sync(onkey->input);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t max77650_onkey_rising(int irq, void *data)
+{
+       struct max77650_onkey *onkey = data;
+
+       input_report_key(onkey->input, onkey->code, 1);
+       input_sync(onkey->input);
+
+       return IRQ_HANDLED;
+}
+
+static int max77650_onkey_probe(struct platform_device *pdev)
+{
+       int irq_r, irq_f, error, mode;
+       struct max77650_onkey *onkey;
+       struct device *dev, *parent;
+       struct regmap *map;
+       unsigned int type;
+
+       dev = &pdev->dev;
+       parent = dev->parent;
+
+       map = dev_get_regmap(parent, NULL);
+       if (!map)
+               return -ENODEV;
+
+       onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL);
+       if (!onkey)
+               return -ENOMEM;
+
+       error = device_property_read_u32(dev, "linux,code", &onkey->code);
+       if (error)
+               onkey->code = KEY_POWER;
+
+       if (device_property_read_bool(dev, "maxim,onkey-slide")) {
+               mode = MAX77650_ONKEY_MODE_SLIDE;
+               type = EV_SW;
+       } else {
+               mode = MAX77650_ONKEY_MODE_PUSH;
+               type = EV_KEY;
+       }
+
+       error = regmap_update_bits(map, MAX77650_REG_CNFG_GLBL,
+                                  MAX77650_ONKEY_MODE_MASK, mode);
+       if (error)
+               return error;
+
+       irq_f = platform_get_irq_byname(pdev, "nEN_F");
+       if (irq_f < 0)
+               return irq_f;
+
+       irq_r = platform_get_irq_byname(pdev, "nEN_R");
+       if (irq_r < 0)
+               return irq_r;
+
+       onkey->input = devm_input_allocate_device(dev);
+       if (!onkey->input)
+               return -ENOMEM;
+
+       onkey->input->name = "max77650_onkey";
+       onkey->input->phys = "max77650_onkey/input0";
+       onkey->input->id.bustype = BUS_I2C;
+       input_set_capability(onkey->input, type, onkey->code);
+
+       error = devm_request_any_context_irq(dev, irq_f, max77650_onkey_falling,
+                                            IRQF_ONESHOT, "onkey-down", onkey);
+       if (error < 0)
+               return error;
+
+       error = devm_request_any_context_irq(dev, irq_r, max77650_onkey_rising,
+                                            IRQF_ONESHOT, "onkey-up", onkey);
+       if (error < 0)
+               return error;
+
+       return input_register_device(onkey->input);
+}
+
+static struct platform_driver max77650_onkey_driver = {
+       .driver = {
+               .name = "max77650-onkey",
+       },
+       .probe = max77650_onkey_probe,
+};
+module_platform_driver(max77650_onkey_driver);
+
+MODULE_DESCRIPTION("MAXIM 77650/77651 ONKEY driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL v2");
index d3ff1fc..94f7ca5 100644 (file)
@@ -373,6 +373,8 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
                if  (ps2_handle_response(&psmouse->ps2dev, data))
                        goto out;
 
+       pm_wakeup_event(&serio->dev, 0);
+
        if (psmouse->state <= PSMOUSE_RESYNCING)
                goto out;
 
index a6f515b..516fea0 100644 (file)
@@ -456,25 +456,15 @@ static int rmi_f54_vidioc_fmt(struct file *file, void *priv,
 static int rmi_f54_vidioc_enum_fmt(struct file *file, void *priv,
                                   struct v4l2_fmtdesc *fmt)
 {
+       struct f54_data *f54 = video_drvdata(file);
+
        if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
-       switch (fmt->index) {
-       case 0:
-               fmt->pixelformat = V4L2_TCH_FMT_DELTA_TD16;
-               break;
-
-       case 1:
-               fmt->pixelformat = V4L2_TCH_FMT_DELTA_TD08;
-               break;
-
-       case 2:
-               fmt->pixelformat = V4L2_TCH_FMT_TU16;
-               break;
-
-       default:
+       if (fmt->index)
                return -EINVAL;
-       }
+
+       fmt->pixelformat = f54->format.pixelformat;
 
        return 0;
 }
@@ -692,6 +682,7 @@ static int rmi_f54_probe(struct rmi_function *fn)
                return -ENOMEM;
 
        rmi_f54_create_input_map(f54);
+       rmi_f54_set_input(f54, 0);
 
        /* register video device */
        strlcpy(f54->v4l2.name, F54_NAME, sizeof(f54->v4l2.name));
index c9c7224..bfe436c 100644 (file)
@@ -254,6 +254,7 @@ config SERIO_APBPS2
 
 config SERIO_OLPC_APSP
        tristate "OLPC AP-SP input support"
+       depends on ARCH_MMP || COMPILE_TEST
        help
          Say Y here if you want support for the keyboard and touchpad included
          in the OLPC XO-1.75 and XO-4 laptops.
index a8b9be3..7935e52 100644 (file)
@@ -440,5 +440,7 @@ static void __exit hv_kbd_exit(void)
 }
 
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Keyboard Driver");
+
 module_init(hv_kbd_init);
 module_exit(hv_kbd_exit);
index 95a78cc..6462f17 100644 (file)
@@ -573,9 +573,6 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
        port = &i8042_ports[port_no];
        serio = port->exists ? port->serio : NULL;
 
-       if (irq && serio)
-               pm_wakeup_event(&serio->dev, 0);
-
        filter_dbg(port->driver_bound, data, "<- i8042 (interrupt, %d, %d%s%s)\n",
                   port_no, irq,
                   dfl & SERIO_PARITY ? ", bad parity" : "",
index e6a07e6..22b8e05 100644 (file)
@@ -409,6 +409,7 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
                        ps2dev->nak = PS2_RET_ERR;
                        break;
                }
+               /* Fall through */
 
        /*
         * Workaround for mice which don't ACK the Get ID command.
index 7a4884a..a2029c3 100644 (file)
@@ -1312,4 +1312,14 @@ config TOUCHSCREEN_ROHM_BU21023
          To compile this driver as a module, choose M here: the
          module will be called bu21023_ts.
 
+config TOUCHSCREEN_IQS5XX
+       tristate "Azoteq IQS550/572/525 trackpad/touchscreen controller"
+       depends on I2C
+       help
+         Say Y to enable support for the Azoteq IQS550/572/525
+         family of trackpad/touchscreen controllers.
+
+         To compile this driver as a module, choose M here: the
+         module will be called iqs5xx.
+
 endif
index fcc7605..084a596 100644 (file)
@@ -110,3 +110,4 @@ obj-$(CONFIG_TOUCHSCREEN_ZFORCE)    += zforce_ts.o
 obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
 obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
 obj-$(CONFIG_TOUCHSCREEN_RASPBERRYPI_FW)       += raspberrypi-ts.o
+obj-$(CONFIG_TOUCHSCREEN_IQS5XX)       += iqs5xx.o
index 702bfda..c639ebc 100644 (file)
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de>
  * Daniel Wagener <daniel.wagener@kernelconcepts.de> (M09 firmware support)
  * Lothar Waßmann <LW@KARO-electronics.de> (DT support)
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 /*
@@ -39,7 +27,6 @@
 #include <linux/gpio/consumer.h>
 #include <linux/input/mt.h>
 #include <linux/input/touchscreen.h>
-#include <linux/of_device.h>
 
 #define WORK_REGISTER_THRESHOLD                0x00
 #define WORK_REGISTER_REPORT_RATE      0x08
@@ -1073,7 +1060,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
                return -ENOMEM;
        }
 
-       chip_data = of_device_get_match_data(&client->dev);
+       chip_data = device_get_match_data(&client->dev);
        if (!chip_data)
                chip_data = (const struct edt_i2c_chip_data *)id->driver_data;
        if (!chip_data || !chip_data->max_support_points) {
@@ -1254,7 +1241,6 @@ static const struct i2c_device_id edt_ft5x06_ts_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id);
 
-#ifdef CONFIG_OF
 static const struct of_device_id edt_ft5x06_of_match[] = {
        { .compatible = "edt,edt-ft5206", .data = &edt_ft5x06_data },
        { .compatible = "edt,edt-ft5306", .data = &edt_ft5x06_data },
@@ -1266,12 +1252,11 @@ static const struct of_device_id edt_ft5x06_of_match[] = {
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match);
-#endif
 
 static struct i2c_driver edt_ft5x06_ts_driver = {
        .driver = {
                .name = "edt_ft5x06",
-               .of_match_table = of_match_ptr(edt_ft5x06_of_match),
+               .of_match_table = edt_ft5x06_of_match,
                .pm = &edt_ft5x06_ts_pm_ops,
        },
        .id_table = edt_ft5x06_ts_id,
@@ -1283,4 +1268,4 @@ module_i2c_driver(edt_ft5x06_ts_driver);
 
 MODULE_AUTHOR("Simon Budig <simon.budig@kernelconcepts.de>");
 MODULE_DESCRIPTION("EDT FT5x06 I2C Touchscreen Driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index f57d822..f7c1d16 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/of.h>
@@ -47,6 +48,8 @@ struct goodix_ts_data {
        struct touchscreen_properties prop;
        unsigned int max_touch_num;
        unsigned int int_trigger_type;
+       struct regulator *avdd28;
+       struct regulator *vddio;
        struct gpio_desc *gpiod_int;
        struct gpio_desc *gpiod_rst;
        u16 id;
@@ -216,6 +219,7 @@ static const struct goodix_chip_data *goodix_get_chip_data(u16 id)
 {
        switch (id) {
        case 1151:
+       case 5663:
        case 5688:
                return &gt1x_chip_data;
 
@@ -532,6 +536,24 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
                return -EINVAL;
        dev = &ts->client->dev;
 
+       ts->avdd28 = devm_regulator_get(dev, "AVDD28");
+       if (IS_ERR(ts->avdd28)) {
+               error = PTR_ERR(ts->avdd28);
+               if (error != -EPROBE_DEFER)
+                       dev_err(dev,
+                               "Failed to get AVDD28 regulator: %d\n", error);
+               return error;
+       }
+
+       ts->vddio = devm_regulator_get(dev, "VDDIO");
+       if (IS_ERR(ts->vddio)) {
+               error = PTR_ERR(ts->vddio);
+               if (error != -EPROBE_DEFER)
+                       dev_err(dev,
+                               "Failed to get VDDIO regulator: %d\n", error);
+               return error;
+       }
+
        /* Get the interrupt GPIO pin number */
        gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_INT_NAME, GPIOD_IN);
        if (IS_ERR(gpiod)) {
@@ -764,6 +786,14 @@ err_release_cfg:
        complete_all(&ts->firmware_loading_complete);
 }
 
+static void goodix_disable_regulators(void *arg)
+{
+       struct goodix_ts_data *ts = arg;
+
+       regulator_disable(ts->vddio);
+       regulator_disable(ts->avdd28);
+}
+
 static int goodix_ts_probe(struct i2c_client *client,
                           const struct i2c_device_id *id)
 {
@@ -789,6 +819,29 @@ static int goodix_ts_probe(struct i2c_client *client,
        if (error)
                return error;
 
+       /* power up the controller */
+       error = regulator_enable(ts->avdd28);
+       if (error) {
+               dev_err(&client->dev,
+                       "Failed to enable AVDD28 regulator: %d\n",
+                       error);
+               return error;
+       }
+
+       error = regulator_enable(ts->vddio);
+       if (error) {
+               dev_err(&client->dev,
+                       "Failed to enable VDDIO regulator: %d\n",
+                       error);
+               regulator_disable(ts->avdd28);
+               return error;
+       }
+
+       error = devm_add_action_or_reset(&client->dev,
+                                        goodix_disable_regulators, ts);
+       if (error)
+               return error;
+
        if (ts->gpiod_int && ts->gpiod_rst) {
                /* reset the controller */
                error = goodix_reset(ts);
@@ -945,6 +998,7 @@ MODULE_DEVICE_TABLE(acpi, goodix_acpi_match);
 #ifdef CONFIG_OF
 static const struct of_device_id goodix_of_match[] = {
        { .compatible = "goodix,gt1151" },
+       { .compatible = "goodix,gt5663" },
        { .compatible = "goodix,gt5688" },
        { .compatible = "goodix,gt911" },
        { .compatible = "goodix,gt9110" },
diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c
new file mode 100644 (file)
index 0000000..b832fe0
--- /dev/null
@@ -0,0 +1,1133 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Azoteq IQS550/572/525 Trackpad/Touchscreen Controller
+ *
+ * Copyright (C) 2018
+ * Author: Jeff LaBundy <jeff@labundy.com>
+ *
+ * These devices require firmware exported from a PC-based configuration tool
+ * made available by the vendor. Firmware files may be pushed to the device's
+ * nonvolatile memory by writing the filename to the 'fw_file' sysfs control.
+ *
+ * Link to PC-based configuration tool and data sheet: http://www.azoteq.com/
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+
+#define IQS5XX_FW_FILE_LEN     64
+#define IQS5XX_NUM_RETRIES     10
+#define IQS5XX_NUM_POINTS      256
+#define IQS5XX_NUM_CONTACTS    5
+#define IQS5XX_WR_BYTES_MAX    2
+
+#define IQS5XX_PROD_NUM_IQS550 40
+#define IQS5XX_PROD_NUM_IQS572 58
+#define IQS5XX_PROD_NUM_IQS525 52
+#define IQS5XX_PROJ_NUM_A000   0
+#define IQS5XX_PROJ_NUM_B000   15
+#define IQS5XX_MAJOR_VER_MIN   2
+
+#define IQS5XX_RESUME          0x00
+#define IQS5XX_SUSPEND         0x01
+
+#define IQS5XX_SW_INPUT_EVENT  0x10
+#define IQS5XX_SETUP_COMPLETE  0x40
+#define IQS5XX_EVENT_MODE      0x01
+#define IQS5XX_TP_EVENT                0x04
+
+#define IQS5XX_FLIP_X          0x01
+#define IQS5XX_FLIP_Y          0x02
+#define IQS5XX_SWITCH_XY_AXIS  0x04
+
+#define IQS5XX_PROD_NUM                0x0000
+#define IQS5XX_ABS_X           0x0016
+#define IQS5XX_ABS_Y           0x0018
+#define IQS5XX_SYS_CTRL0       0x0431
+#define IQS5XX_SYS_CTRL1       0x0432
+#define IQS5XX_SYS_CFG0                0x058E
+#define IQS5XX_SYS_CFG1                0x058F
+#define IQS5XX_TOTAL_RX                0x063D
+#define IQS5XX_TOTAL_TX                0x063E
+#define IQS5XX_XY_CFG0         0x0669
+#define IQS5XX_X_RES           0x066E
+#define IQS5XX_Y_RES           0x0670
+#define IQS5XX_CHKSM           0x83C0
+#define IQS5XX_APP             0x8400
+#define IQS5XX_CSTM            0xBE00
+#define IQS5XX_PMAP_END                0xBFFF
+#define IQS5XX_END_COMM                0xEEEE
+
+#define IQS5XX_CHKSM_LEN       (IQS5XX_APP - IQS5XX_CHKSM)
+#define IQS5XX_APP_LEN         (IQS5XX_CSTM - IQS5XX_APP)
+#define IQS5XX_CSTM_LEN                (IQS5XX_PMAP_END + 1 - IQS5XX_CSTM)
+#define IQS5XX_PMAP_LEN                (IQS5XX_PMAP_END + 1 - IQS5XX_CHKSM)
+
+#define IQS5XX_REC_HDR_LEN     4
+#define IQS5XX_REC_LEN_MAX     255
+#define IQS5XX_REC_TYPE_DATA   0x00
+#define IQS5XX_REC_TYPE_EOF    0x01
+
+#define IQS5XX_BL_ADDR_MASK    0x40
+#define IQS5XX_BL_CMD_VER      0x00
+#define IQS5XX_BL_CMD_READ     0x01
+#define IQS5XX_BL_CMD_EXEC     0x02
+#define IQS5XX_BL_CMD_CRC      0x03
+#define IQS5XX_BL_BLK_LEN_MAX  64
+#define IQS5XX_BL_ID           0x0200
+#define IQS5XX_BL_STATUS_RESET 0x00
+#define IQS5XX_BL_STATUS_AVAIL 0xA5
+#define IQS5XX_BL_STATUS_NONE  0xEE
+#define IQS5XX_BL_CRC_PASS     0x00
+#define IQS5XX_BL_CRC_FAIL     0x01
+#define IQS5XX_BL_ATTEMPTS     3
+
+struct iqs5xx_private {
+       struct i2c_client *client;
+       struct input_dev *input;
+       struct gpio_desc *reset_gpio;
+       struct mutex lock;
+       u8 bl_status;
+};
+
+struct iqs5xx_dev_id_info {
+       __be16 prod_num;
+       __be16 proj_num;
+       u8 major_ver;
+       u8 minor_ver;
+       u8 bl_status;
+} __packed;
+
+struct iqs5xx_ihex_rec {
+       char start;
+       char len[2];
+       char addr[4];
+       char type[2];
+       char data[2];
+} __packed;
+
+struct iqs5xx_touch_data {
+       __be16 abs_x;
+       __be16 abs_y;
+       __be16 strength;
+       u8 area;
+} __packed;
+
+static int iqs5xx_read_burst(struct i2c_client *client,
+                            u16 reg, void *val, u16 len)
+{
+       __be16 reg_buf = cpu_to_be16(reg);
+       int ret, i;
+       struct i2c_msg msg[] = {
+               {
+                       .addr = client->addr,
+                       .flags = 0,
+                       .len = sizeof(reg_buf),
+                       .buf = (u8 *)&reg_buf,
+               },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = len,
+                       .buf = (u8 *)val,
+               },
+       };
+
+       /*
+        * The first addressing attempt outside of a communication window fails
+        * and must be retried, after which the device clock stretches until it
+        * is available.
+        */
+       for (i = 0; i < IQS5XX_NUM_RETRIES; i++) {
+               ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+               if (ret == ARRAY_SIZE(msg))
+                       return 0;
+
+               usleep_range(200, 300);
+       }
+
+       if (ret >= 0)
+               ret = -EIO;
+
+       dev_err(&client->dev, "Failed to read from address 0x%04X: %d\n",
+               reg, ret);
+
+       return ret;
+}
+
+static int iqs5xx_read_word(struct i2c_client *client, u16 reg, u16 *val)
+{
+       __be16 val_buf;
+       int error;
+
+       error = iqs5xx_read_burst(client, reg, &val_buf, sizeof(val_buf));
+       if (error)
+               return error;
+
+       *val = be16_to_cpu(val_buf);
+
+       return 0;
+}
+
+static int iqs5xx_read_byte(struct i2c_client *client, u16 reg, u8 *val)
+{
+       return iqs5xx_read_burst(client, reg, val, sizeof(*val));
+}
+
+static int iqs5xx_write_burst(struct i2c_client *client,
+                             u16 reg, const void *val, u16 len)
+{
+       int ret, i;
+       u16 mlen = sizeof(reg) + len;
+       u8 mbuf[sizeof(reg) + IQS5XX_WR_BYTES_MAX];
+
+       if (len > IQS5XX_WR_BYTES_MAX)
+               return -EINVAL;
+
+       put_unaligned_be16(reg, mbuf);
+       memcpy(mbuf + sizeof(reg), val, len);
+
+       /*
+        * The first addressing attempt outside of a communication window fails
+        * and must be retried, after which the device clock stretches until it
+        * is available.
+        */
+       for (i = 0; i < IQS5XX_NUM_RETRIES; i++) {
+               ret = i2c_master_send(client, mbuf, mlen);
+               if (ret == mlen)
+                       return 0;
+
+               usleep_range(200, 300);
+       }
+
+       if (ret >= 0)
+               ret = -EIO;
+
+       dev_err(&client->dev, "Failed to write to address 0x%04X: %d\n",
+               reg, ret);
+
+       return ret;
+}
+
+static int iqs5xx_write_word(struct i2c_client *client, u16 reg, u16 val)
+{
+       __be16 val_buf = cpu_to_be16(val);
+
+       return iqs5xx_write_burst(client, reg, &val_buf, sizeof(val_buf));
+}
+
+static int iqs5xx_write_byte(struct i2c_client *client, u16 reg, u8 val)
+{
+       return iqs5xx_write_burst(client, reg, &val, sizeof(val));
+}
+
+static void iqs5xx_reset(struct i2c_client *client)
+{
+       struct iqs5xx_private *iqs5xx = i2c_get_clientdata(client);
+
+       gpiod_set_value_cansleep(iqs5xx->reset_gpio, 1);
+       usleep_range(200, 300);
+
+       gpiod_set_value_cansleep(iqs5xx->reset_gpio, 0);
+}
+
+static int iqs5xx_bl_cmd(struct i2c_client *client, u8 bl_cmd, u16 bl_addr)
+{
+       struct i2c_msg msg;
+       int ret;
+       u8 mbuf[sizeof(bl_cmd) + sizeof(bl_addr)];
+
+       msg.addr = client->addr ^ IQS5XX_BL_ADDR_MASK;
+       msg.flags = 0;
+       msg.len = sizeof(bl_cmd);
+       msg.buf = mbuf;
+
+       *mbuf = bl_cmd;
+
+       switch (bl_cmd) {
+       case IQS5XX_BL_CMD_VER:
+       case IQS5XX_BL_CMD_CRC:
+       case IQS5XX_BL_CMD_EXEC:
+               break;
+       case IQS5XX_BL_CMD_READ:
+               msg.len += sizeof(bl_addr);
+               put_unaligned_be16(bl_addr, mbuf + sizeof(bl_cmd));
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = i2c_transfer(client->adapter, &msg, 1);
+       if (ret != 1)
+               goto msg_fail;
+
+       switch (bl_cmd) {
+       case IQS5XX_BL_CMD_VER:
+               msg.len = sizeof(u16);
+               break;
+       case IQS5XX_BL_CMD_CRC:
+               msg.len = sizeof(u8);
+               /*
+                * This delay saves the bus controller the trouble of having to
+                * tolerate a relatively long clock-stretching period while the
+                * CRC is calculated.
+                */
+               msleep(50);
+               break;
+       case IQS5XX_BL_CMD_EXEC:
+               usleep_range(10000, 10100);
+               /* fall through */
+       default:
+               return 0;
+       }
+
+       msg.flags = I2C_M_RD;
+
+       ret = i2c_transfer(client->adapter, &msg, 1);
+       if (ret != 1)
+               goto msg_fail;
+
+       if (bl_cmd == IQS5XX_BL_CMD_VER &&
+           get_unaligned_be16(mbuf) != IQS5XX_BL_ID) {
+               dev_err(&client->dev, "Unrecognized bootloader ID: 0x%04X\n",
+                       get_unaligned_be16(mbuf));
+               return -EINVAL;
+       }
+
+       if (bl_cmd == IQS5XX_BL_CMD_CRC && *mbuf != IQS5XX_BL_CRC_PASS) {
+               dev_err(&client->dev, "Bootloader CRC failed\n");
+               return -EIO;
+       }
+
+       return 0;
+
+msg_fail:
+       if (ret >= 0)
+               ret = -EIO;
+
+       if (bl_cmd != IQS5XX_BL_CMD_VER)
+               dev_err(&client->dev,
+                       "Unsuccessful bootloader command 0x%02X: %d\n",
+                       bl_cmd, ret);
+
+       return ret;
+}
+
+static int iqs5xx_bl_open(struct i2c_client *client)
+{
+       int error, i, j;
+
+       /*
+        * The device opens a bootloader polling window for 2 ms following the
+        * release of reset. If the host cannot establish communication during
+        * this time frame, it must cycle reset again.
+        */
+       for (i = 0; i < IQS5XX_BL_ATTEMPTS; i++) {
+               iqs5xx_reset(client);
+
+               for (j = 0; j < IQS5XX_NUM_RETRIES; j++) {
+                       error = iqs5xx_bl_cmd(client, IQS5XX_BL_CMD_VER, 0);
+                       if (!error || error == -EINVAL)
+                               return error;
+               }
+       }
+
+       dev_err(&client->dev, "Failed to open bootloader: %d\n", error);
+
+       return error;
+}
+
+static int iqs5xx_bl_write(struct i2c_client *client,
+                          u16 bl_addr, u8 *pmap_data, u16 pmap_len)
+{
+       struct i2c_msg msg;
+       int ret, i;
+       u8 mbuf[sizeof(bl_addr) + IQS5XX_BL_BLK_LEN_MAX];
+
+       if (pmap_len % IQS5XX_BL_BLK_LEN_MAX)
+               return -EINVAL;
+
+       msg.addr = client->addr ^ IQS5XX_BL_ADDR_MASK;
+       msg.flags = 0;
+       msg.len = sizeof(mbuf);
+       msg.buf = mbuf;
+
+       for (i = 0; i < pmap_len; i += IQS5XX_BL_BLK_LEN_MAX) {
+               put_unaligned_be16(bl_addr + i, mbuf);
+               memcpy(mbuf + sizeof(bl_addr), pmap_data + i,
+                      sizeof(mbuf) - sizeof(bl_addr));
+
+               ret = i2c_transfer(client->adapter, &msg, 1);
+               if (ret != 1)
+                       goto msg_fail;
+
+               usleep_range(10000, 10100);
+       }
+
+       return 0;
+
+msg_fail:
+       if (ret >= 0)
+               ret = -EIO;
+
+       dev_err(&client->dev, "Failed to write block at address 0x%04X: %d\n",
+               bl_addr + i, ret);
+
+       return ret;
+}
+
+static int iqs5xx_bl_verify(struct i2c_client *client,
+                           u16 bl_addr, u8 *pmap_data, u16 pmap_len)
+{
+       struct i2c_msg msg;
+       int ret, i;
+       u8 bl_data[IQS5XX_BL_BLK_LEN_MAX];
+
+       if (pmap_len % IQS5XX_BL_BLK_LEN_MAX)
+               return -EINVAL;
+
+       msg.addr = client->addr ^ IQS5XX_BL_ADDR_MASK;
+       msg.flags = I2C_M_RD;
+       msg.len = sizeof(bl_data);
+       msg.buf = bl_data;
+
+       for (i = 0; i < pmap_len; i += IQS5XX_BL_BLK_LEN_MAX) {
+               ret = iqs5xx_bl_cmd(client, IQS5XX_BL_CMD_READ, bl_addr + i);
+               if (ret)
+                       return ret;
+
+               ret = i2c_transfer(client->adapter, &msg, 1);
+               if (ret != 1)
+                       goto msg_fail;
+
+               if (memcmp(bl_data, pmap_data + i, sizeof(bl_data))) {
+                       dev_err(&client->dev,
+                               "Failed to verify block at address 0x%04X\n",
+                               bl_addr + i);
+                       return -EIO;
+               }
+       }
+
+       return 0;
+
+msg_fail:
+       if (ret >= 0)
+               ret = -EIO;
+
+       dev_err(&client->dev, "Failed to read block at address 0x%04X: %d\n",
+               bl_addr + i, ret);
+
+       return ret;
+}
+
+static int iqs5xx_set_state(struct i2c_client *client, u8 state)
+{
+       struct iqs5xx_private *iqs5xx = i2c_get_clientdata(client);
+       int error1, error2;
+
+       if (iqs5xx->bl_status == IQS5XX_BL_STATUS_RESET)
+               return 0;
+
+       mutex_lock(&iqs5xx->lock);
+
+       /*
+        * Addressing the device outside of a communication window prompts it
+        * to assert the RDY output, so disable the interrupt line to prevent
+        * the handler from servicing a false interrupt.
+        */
+       disable_irq(client->irq);
+
+       error1 = iqs5xx_write_byte(client, IQS5XX_SYS_CTRL1, state);
+       error2 = iqs5xx_write_byte(client, IQS5XX_END_COMM, 0);
+
+       usleep_range(50, 100);
+       enable_irq(client->irq);
+
+       mutex_unlock(&iqs5xx->lock);
+
+       if (error1)
+               return error1;
+
+       return error2;
+}
+
+static int iqs5xx_open(struct input_dev *input)
+{
+       struct iqs5xx_private *iqs5xx = input_get_drvdata(input);
+
+       return iqs5xx_set_state(iqs5xx->client, IQS5XX_RESUME);
+}
+
+static void iqs5xx_close(struct input_dev *input)
+{
+       struct iqs5xx_private *iqs5xx = input_get_drvdata(input);
+
+       iqs5xx_set_state(iqs5xx->client, IQS5XX_SUSPEND);
+}
+
+static int iqs5xx_axis_init(struct i2c_client *client)
+{
+       struct iqs5xx_private *iqs5xx = i2c_get_clientdata(client);
+       struct touchscreen_properties prop;
+       struct input_dev *input;
+       int error;
+       u16 max_x, max_x_hw;
+       u16 max_y, max_y_hw;
+       u8 val;
+
+       if (!iqs5xx->input) {
+               input = devm_input_allocate_device(&client->dev);
+               if (!input)
+                       return -ENOMEM;
+
+               input->name = client->name;
+               input->id.bustype = BUS_I2C;
+               input->open = iqs5xx_open;
+               input->close = iqs5xx_close;
+
+               input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
+               input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
+               input_set_capability(input, EV_ABS, ABS_MT_PRESSURE);
+
+               error = input_mt_init_slots(input,
+                               IQS5XX_NUM_CONTACTS, INPUT_MT_DIRECT);
+               if (error) {
+                       dev_err(&client->dev,
+                               "Failed to initialize slots: %d\n", error);
+                       return error;
+               }
+
+               input_set_drvdata(input, iqs5xx);
+               iqs5xx->input = input;
+       }
+
+       touchscreen_parse_properties(iqs5xx->input, true, &prop);
+
+       error = iqs5xx_read_byte(client, IQS5XX_TOTAL_RX, &val);
+       if (error)
+               return error;
+       max_x_hw = (val - 1) * IQS5XX_NUM_POINTS;
+
+       error = iqs5xx_read_byte(client, IQS5XX_TOTAL_TX, &val);
+       if (error)
+               return error;
+       max_y_hw = (val - 1) * IQS5XX_NUM_POINTS;
+
+       error = iqs5xx_read_byte(client, IQS5XX_XY_CFG0, &val);
+       if (error)
+               return error;
+
+       if (val & IQS5XX_SWITCH_XY_AXIS)
+               swap(max_x_hw, max_y_hw);
+
+       if (prop.swap_x_y)
+               val ^= IQS5XX_SWITCH_XY_AXIS;
+
+       if (prop.invert_x)
+               val ^= prop.swap_x_y ? IQS5XX_FLIP_Y : IQS5XX_FLIP_X;
+
+       if (prop.invert_y)
+               val ^= prop.swap_x_y ? IQS5XX_FLIP_X : IQS5XX_FLIP_Y;
+
+       error = iqs5xx_write_byte(client, IQS5XX_XY_CFG0, val);
+       if (error)
+               return error;
+
+       if (prop.max_x > max_x_hw) {
+               dev_err(&client->dev, "Invalid maximum x-coordinate: %u > %u\n",
+                       prop.max_x, max_x_hw);
+               return -EINVAL;
+       } else if (prop.max_x == 0) {
+               error = iqs5xx_read_word(client, IQS5XX_X_RES, &max_x);
+               if (error)
+                       return error;
+
+               input_abs_set_max(iqs5xx->input,
+                                 prop.swap_x_y ? ABS_MT_POSITION_Y :
+                                                 ABS_MT_POSITION_X,
+                                 max_x);
+       } else {
+               max_x = (u16)prop.max_x;
+       }
+
+       if (prop.max_y > max_y_hw) {
+               dev_err(&client->dev, "Invalid maximum y-coordinate: %u > %u\n",
+                       prop.max_y, max_y_hw);
+               return -EINVAL;
+       } else if (prop.max_y == 0) {
+               error = iqs5xx_read_word(client, IQS5XX_Y_RES, &max_y);
+               if (error)
+                       return error;
+
+               input_abs_set_max(iqs5xx->input,
+                                 prop.swap_x_y ? ABS_MT_POSITION_X :
+                                                 ABS_MT_POSITION_Y,
+                                 max_y);
+       } else {
+               max_y = (u16)prop.max_y;
+       }
+
+       /*
+        * Write horizontal and vertical resolution to the device in case its
+        * original defaults were overridden or swapped as per the properties
+        * specified in the device tree.
+        */
+       error = iqs5xx_write_word(client,
+                                 prop.swap_x_y ? IQS5XX_Y_RES : IQS5XX_X_RES,
+                                 max_x);
+       if (error)
+               return error;
+
+       return iqs5xx_write_word(client,
+                                prop.swap_x_y ? IQS5XX_X_RES : IQS5XX_Y_RES,
+                                max_y);
+}
+
+static int iqs5xx_dev_init(struct i2c_client *client)
+{
+       struct iqs5xx_private *iqs5xx = i2c_get_clientdata(client);
+       struct iqs5xx_dev_id_info *dev_id_info;
+       int error;
+       u8 val;
+       u8 buf[sizeof(*dev_id_info) + 1];
+
+       error = iqs5xx_read_burst(client, IQS5XX_PROD_NUM,
+                                 &buf[1], sizeof(*dev_id_info));
+       if (error)
+               return iqs5xx_bl_open(client);
+
+       /*
+        * A000 and B000 devices use 8-bit and 16-bit addressing, respectively.
+        * Querying an A000 device's version information with 16-bit addressing
+        * gives the appearance that the data is shifted by one byte; a nonzero
+        * leading array element suggests this could be the case (in which case
+        * the missing zero is prepended).
+        */
+       buf[0] = 0;
+       dev_id_info = (struct iqs5xx_dev_id_info *)&buf[(buf[1] > 0) ? 0 : 1];
+
+       switch (be16_to_cpu(dev_id_info->prod_num)) {
+       case IQS5XX_PROD_NUM_IQS550:
+       case IQS5XX_PROD_NUM_IQS572:
+       case IQS5XX_PROD_NUM_IQS525:
+               break;
+       default:
+               dev_err(&client->dev, "Unrecognized product number: %u\n",
+                       be16_to_cpu(dev_id_info->prod_num));
+               return -EINVAL;
+       }
+
+       switch (be16_to_cpu(dev_id_info->proj_num)) {
+       case IQS5XX_PROJ_NUM_A000:
+               dev_err(&client->dev, "Unsupported project number: %u\n",
+                       be16_to_cpu(dev_id_info->proj_num));
+               return iqs5xx_bl_open(client);
+       case IQS5XX_PROJ_NUM_B000:
+               break;
+       default:
+               dev_err(&client->dev, "Unrecognized project number: %u\n",
+                       be16_to_cpu(dev_id_info->proj_num));
+               return -EINVAL;
+       }
+
+       if (dev_id_info->major_ver < IQS5XX_MAJOR_VER_MIN) {
+               dev_err(&client->dev, "Unsupported major version: %u\n",
+                       dev_id_info->major_ver);
+               return iqs5xx_bl_open(client);
+       }
+
+       switch (dev_id_info->bl_status) {
+       case IQS5XX_BL_STATUS_AVAIL:
+       case IQS5XX_BL_STATUS_NONE:
+               break;
+       default:
+               dev_err(&client->dev,
+                       "Unrecognized bootloader status: 0x%02X\n",
+                       dev_id_info->bl_status);
+               return -EINVAL;
+       }
+
+       error = iqs5xx_axis_init(client);
+       if (error)
+               return error;
+
+       error = iqs5xx_read_byte(client, IQS5XX_SYS_CFG0, &val);
+       if (error)
+               return error;
+
+       val |= IQS5XX_SETUP_COMPLETE;
+       val &= ~IQS5XX_SW_INPUT_EVENT;
+       error = iqs5xx_write_byte(client, IQS5XX_SYS_CFG0, val);
+       if (error)
+               return error;
+
+       val = IQS5XX_TP_EVENT | IQS5XX_EVENT_MODE;
+       error = iqs5xx_write_byte(client, IQS5XX_SYS_CFG1, val);
+       if (error)
+               return error;
+
+       error = iqs5xx_write_byte(client, IQS5XX_END_COMM, 0);
+       if (error)
+               return error;
+
+       iqs5xx->bl_status = dev_id_info->bl_status;
+
+       /*
+        * Closure of the first communication window that appears following the
+        * release of reset appears to kick off an initialization period during
+        * which further communication is met with clock stretching. The return
+        * from this function is delayed so that further communication attempts
+        * avoid this period.
+        */
+       msleep(100);
+
+       return 0;
+}
+
+static irqreturn_t iqs5xx_irq(int irq, void *data)
+{
+       struct iqs5xx_private *iqs5xx = data;
+       struct iqs5xx_touch_data touch_data[IQS5XX_NUM_CONTACTS];
+       struct i2c_client *client = iqs5xx->client;
+       struct input_dev *input = iqs5xx->input;
+       int error, i;
+
+       /*
+        * This check is purely a precaution, as the device does not assert the
+        * RDY output during bootloader mode. If the device operates outside of
+        * bootloader mode, the input device is guaranteed to be allocated.
+        */
+       if (iqs5xx->bl_status == IQS5XX_BL_STATUS_RESET)
+               return IRQ_NONE;
+
+       error = iqs5xx_read_burst(client, IQS5XX_ABS_X,
+                                 touch_data, sizeof(touch_data));
+       if (error)
+               return IRQ_NONE;
+
+       for (i = 0; i < ARRAY_SIZE(touch_data); i++) {
+               u16 pressure = be16_to_cpu(touch_data[i].strength);
+
+               input_mt_slot(input, i);
+               if (input_mt_report_slot_state(input, MT_TOOL_FINGER,
+                                              pressure != 0)) {
+                       input_report_abs(input, ABS_MT_POSITION_X,
+                                        be16_to_cpu(touch_data[i].abs_x));
+                       input_report_abs(input, ABS_MT_POSITION_Y,
+                                        be16_to_cpu(touch_data[i].abs_y));
+                       input_report_abs(input, ABS_MT_PRESSURE, pressure);
+               }
+       }
+
+       input_mt_sync_frame(input);
+       input_sync(input);
+
+       error = iqs5xx_write_byte(client, IQS5XX_END_COMM, 0);
+       if (error)
+               return IRQ_NONE;
+
+       /*
+        * Once the communication window is closed, a small delay is added to
+        * ensure the device's RDY output has been deasserted by the time the
+        * interrupt handler returns.
+        */
+       usleep_range(50, 100);
+
+       return IRQ_HANDLED;
+}
+
+static int iqs5xx_fw_file_parse(struct i2c_client *client,
+                               const char *fw_file, u8 *pmap)
+{
+       const struct firmware *fw;
+       struct iqs5xx_ihex_rec *rec;
+       size_t pos = 0;
+       int error, i;
+       u16 rec_num = 1;
+       u16 rec_addr;
+       u8 rec_len, rec_type, rec_chksm, chksm;
+       u8 rec_hdr[IQS5XX_REC_HDR_LEN];
+       u8 rec_data[IQS5XX_REC_LEN_MAX];
+
+       /*
+        * Firmware exported from the vendor's configuration tool deviates from
+        * standard ihex as follows: (1) the checksum for records corresponding
+        * to user-exported settings is not recalculated, and (2) an address of
+        * 0xFFFF is used for the EOF record.
+        *
+        * Because the ihex2fw tool tolerates neither (1) nor (2), the slightly
+        * nonstandard ihex firmware is parsed directly by the driver.
+        */
+       error = request_firmware(&fw, fw_file, &client->dev);
+       if (error) {
+               dev_err(&client->dev, "Failed to request firmware %s: %d\n",
+                       fw_file, error);
+               return error;
+       }
+
+       do {
+               if (pos + sizeof(*rec) > fw->size) {
+                       dev_err(&client->dev, "Insufficient firmware size\n");
+                       error = -EINVAL;
+                       break;
+               }
+               rec = (struct iqs5xx_ihex_rec *)(fw->data + pos);
+               pos += sizeof(*rec);
+
+               if (rec->start != ':') {
+                       dev_err(&client->dev, "Invalid start at record %u\n",
+                               rec_num);
+                       error = -EINVAL;
+                       break;
+               }
+
+               error = hex2bin(rec_hdr, rec->len, sizeof(rec_hdr));
+               if (error) {
+                       dev_err(&client->dev, "Invalid header at record %u\n",
+                               rec_num);
+                       break;
+               }
+
+               rec_len = *rec_hdr;
+               rec_addr = get_unaligned_be16(rec_hdr + sizeof(rec_len));
+               rec_type = *(rec_hdr + sizeof(rec_len) + sizeof(rec_addr));
+
+               if (pos + rec_len * 2 > fw->size) {
+                       dev_err(&client->dev, "Insufficient firmware size\n");
+                       error = -EINVAL;
+                       break;
+               }
+               pos += (rec_len * 2);
+
+               error = hex2bin(rec_data, rec->data, rec_len);
+               if (error) {
+                       dev_err(&client->dev, "Invalid data at record %u\n",
+                               rec_num);
+                       break;
+               }
+
+               error = hex2bin(&rec_chksm,
+                               rec->data + rec_len * 2, sizeof(rec_chksm));
+               if (error) {
+                       dev_err(&client->dev, "Invalid checksum at record %u\n",
+                               rec_num);
+                       break;
+               }
+
+               chksm = 0;
+               for (i = 0; i < sizeof(rec_hdr); i++)
+                       chksm += rec_hdr[i];
+               for (i = 0; i < rec_len; i++)
+                       chksm += rec_data[i];
+               chksm = ~chksm + 1;
+
+               if (chksm != rec_chksm && rec_addr < IQS5XX_CSTM) {
+                       dev_err(&client->dev,
+                               "Incorrect checksum at record %u\n",
+                               rec_num);
+                       error = -EINVAL;
+                       break;
+               }
+
+               switch (rec_type) {
+               case IQS5XX_REC_TYPE_DATA:
+                       if (rec_addr < IQS5XX_CHKSM ||
+                           rec_addr > IQS5XX_PMAP_END) {
+                               dev_err(&client->dev,
+                                       "Invalid address at record %u\n",
+                                       rec_num);
+                               error = -EINVAL;
+                       } else {
+                               memcpy(pmap + rec_addr - IQS5XX_CHKSM,
+                                      rec_data, rec_len);
+                       }
+                       break;
+               case IQS5XX_REC_TYPE_EOF:
+                       break;
+               default:
+                       dev_err(&client->dev, "Invalid type at record %u\n",
+                               rec_num);
+                       error = -EINVAL;
+               }
+
+               if (error)
+                       break;
+
+               rec_num++;
+               while (pos < fw->size) {
+                       if (*(fw->data + pos) == ':')
+                               break;
+                       pos++;
+               }
+       } while (rec_type != IQS5XX_REC_TYPE_EOF);
+
+       release_firmware(fw);
+
+       return error;
+}
+
+static int iqs5xx_fw_file_write(struct i2c_client *client, const char *fw_file)
+{
+       struct iqs5xx_private *iqs5xx = i2c_get_clientdata(client);
+       int error;
+       u8 *pmap;
+
+       if (iqs5xx->bl_status == IQS5XX_BL_STATUS_NONE)
+               return -EPERM;
+
+       pmap = kzalloc(IQS5XX_PMAP_LEN, GFP_KERNEL);
+       if (!pmap)
+               return -ENOMEM;
+
+       error = iqs5xx_fw_file_parse(client, fw_file, pmap);
+       if (error)
+               goto err_kfree;
+
+       mutex_lock(&iqs5xx->lock);
+
+       /*
+        * Disable the interrupt line in case the first attempt(s) to enter the
+        * bootloader don't happen quickly enough, in which case the device may
+        * assert the RDY output until the next attempt.
+        */
+       disable_irq(client->irq);
+
+       iqs5xx->bl_status = IQS5XX_BL_STATUS_RESET;
+
+       error = iqs5xx_bl_cmd(client, IQS5XX_BL_CMD_VER, 0);
+       if (error) {
+               error = iqs5xx_bl_open(client);
+               if (error)
+                       goto err_reset;
+       }
+
+       error = iqs5xx_bl_write(client, IQS5XX_CHKSM, pmap, IQS5XX_PMAP_LEN);
+       if (error)
+               goto err_reset;
+
+       error = iqs5xx_bl_cmd(client, IQS5XX_BL_CMD_CRC, 0);
+       if (error)
+               goto err_reset;
+
+       error = iqs5xx_bl_verify(client, IQS5XX_CSTM,
+                                pmap + IQS5XX_CHKSM_LEN + IQS5XX_APP_LEN,
+                                IQS5XX_CSTM_LEN);
+       if (error)
+               goto err_reset;
+
+       error = iqs5xx_bl_cmd(client, IQS5XX_BL_CMD_EXEC, 0);
+
+err_reset:
+       if (error) {
+               iqs5xx_reset(client);
+               usleep_range(10000, 10100);
+       }
+
+       error = iqs5xx_dev_init(client);
+       if (!error && iqs5xx->bl_status == IQS5XX_BL_STATUS_RESET)
+               error = -EINVAL;
+
+       enable_irq(client->irq);
+
+       mutex_unlock(&iqs5xx->lock);
+
+err_kfree:
+       kfree(pmap);
+
+       return error;
+}
+
+static ssize_t fw_file_store(struct device *dev, struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct iqs5xx_private *iqs5xx = dev_get_drvdata(dev);
+       struct i2c_client *client = iqs5xx->client;
+       size_t len = count;
+       bool input_reg = !iqs5xx->input;
+       char fw_file[IQS5XX_FW_FILE_LEN + 1];
+       int error;
+
+       if (!len)
+               return -EINVAL;
+
+       if (buf[len - 1] == '\n')
+               len--;
+
+       if (len > IQS5XX_FW_FILE_LEN)
+               return -ENAMETOOLONG;
+
+       memcpy(fw_file, buf, len);
+       fw_file[len] = '\0';
+
+       error = iqs5xx_fw_file_write(client, fw_file);
+       if (error)
+               return error;
+
+       /*
+        * If the input device was not allocated already, it is guaranteed to
+        * be allocated by this point and can finally be registered.
+        */
+       if (input_reg) {
+               error = input_register_device(iqs5xx->input);
+               if (error) {
+                       dev_err(&client->dev,
+                               "Failed to register device: %d\n",
+                               error);
+                       return error;
+               }
+       }
+
+       return count;
+}
+
+static DEVICE_ATTR_WO(fw_file);
+
+static struct attribute *iqs5xx_attrs[] = {
+       &dev_attr_fw_file.attr,
+       NULL,
+};
+
+static const struct attribute_group iqs5xx_attr_group = {
+       .attrs = iqs5xx_attrs,
+};
+
+static int __maybe_unused iqs5xx_suspend(struct device *dev)
+{
+       struct iqs5xx_private *iqs5xx = dev_get_drvdata(dev);
+       struct input_dev *input = iqs5xx->input;
+       int error = 0;
+
+       if (!input)
+               return error;
+
+       mutex_lock(&input->mutex);
+
+       if (input->users)
+               error = iqs5xx_set_state(iqs5xx->client, IQS5XX_SUSPEND);
+
+       mutex_unlock(&input->mutex);
+
+       return error;
+}
+
+static int __maybe_unused iqs5xx_resume(struct device *dev)
+{
+       struct iqs5xx_private *iqs5xx = dev_get_drvdata(dev);
+       struct input_dev *input = iqs5xx->input;
+       int error = 0;
+
+       if (!input)
+               return error;
+
+       mutex_lock(&input->mutex);
+
+       if (input->users)
+               error = iqs5xx_set_state(iqs5xx->client, IQS5XX_RESUME);
+
+       mutex_unlock(&input->mutex);
+
+       return error;
+}
+
+static SIMPLE_DEV_PM_OPS(iqs5xx_pm, iqs5xx_suspend, iqs5xx_resume);
+
+static int iqs5xx_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       struct iqs5xx_private *iqs5xx;
+       int error;
+
+       iqs5xx = devm_kzalloc(&client->dev, sizeof(*iqs5xx), GFP_KERNEL);
+       if (!iqs5xx)
+               return -ENOMEM;
+
+       dev_set_drvdata(&client->dev, iqs5xx);
+
+       i2c_set_clientdata(client, iqs5xx);
+       iqs5xx->client = client;
+
+       iqs5xx->reset_gpio = devm_gpiod_get(&client->dev,
+                                           "reset", GPIOD_OUT_LOW);
+       if (IS_ERR(iqs5xx->reset_gpio)) {
+               error = PTR_ERR(iqs5xx->reset_gpio);
+               dev_err(&client->dev, "Failed to request GPIO: %d\n", error);
+               return error;
+       }
+
+       mutex_init(&iqs5xx->lock);
+
+       iqs5xx_reset(client);
+       usleep_range(10000, 10100);
+
+       error = iqs5xx_dev_init(client);
+       if (error)
+               return error;
+
+       error = devm_request_threaded_irq(&client->dev, client->irq,
+                                         NULL, iqs5xx_irq, IRQF_ONESHOT,
+                                         client->name, iqs5xx);
+       if (error) {
+               dev_err(&client->dev, "Failed to request IRQ: %d\n", error);
+               return error;
+       }
+
+       error = devm_device_add_group(&client->dev, &iqs5xx_attr_group);
+       if (error) {
+               dev_err(&client->dev, "Failed to add attributes: %d\n", error);
+               return error;
+       }
+
+       if (iqs5xx->input) {
+               error = input_register_device(iqs5xx->input);
+               if (error)
+                       dev_err(&client->dev,
+                               "Failed to register device: %d\n",
+                               error);
+       }
+
+       return error;
+}
+
+static const struct i2c_device_id iqs5xx_id[] = {
+       { "iqs550", 0 },
+       { "iqs572", 1 },
+       { "iqs525", 2 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, iqs5xx_id);
+
+static const struct of_device_id iqs5xx_of_match[] = {
+       { .compatible = "azoteq,iqs550" },
+       { .compatible = "azoteq,iqs572" },
+       { .compatible = "azoteq,iqs525" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, iqs5xx_of_match);
+
+static struct i2c_driver iqs5xx_i2c_driver = {
+       .driver = {
+               .name           = "iqs5xx",
+               .of_match_table = iqs5xx_of_match,
+               .pm             = &iqs5xx_pm,
+       },
+       .id_table       = iqs5xx_id,
+       .probe          = iqs5xx_probe,
+};
+module_i2c_driver(iqs5xx_i2c_driver);
+
+MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>");
+MODULE_DESCRIPTION("Azoteq IQS550/572/525 Trackpad/Touchscreen Controller");
+MODULE_LICENSE("GPL");
index fde16c5..09c9e45 100644 (file)
@@ -165,7 +165,7 @@ static inline u16 get_pci_device_id(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
 
-       return PCI_DEVID(pdev->bus->number, pdev->devfn);
+       return pci_dev_id(pdev);
 }
 
 static inline int get_acpihid_device_id(struct device *dev,
index 77aabe6..5e89804 100644 (file)
@@ -206,12 +206,13 @@ static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie,
        return 0;
 }
 
-static void iova_reserve_pci_windows(struct pci_dev *dev,
+static int iova_reserve_pci_windows(struct pci_dev *dev,
                struct iova_domain *iovad)
 {
        struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus);
        struct resource_entry *window;
        unsigned long lo, hi;
+       phys_addr_t start = 0, end;
 
        resource_list_for_each_entry(window, &bridge->windows) {
                if (resource_type(window->res) != IORESOURCE_MEM)
@@ -221,6 +222,31 @@ static void iova_reserve_pci_windows(struct pci_dev *dev,
                hi = iova_pfn(iovad, window->res->end - window->offset);
                reserve_iova(iovad, lo, hi);
        }
+
+       /* Get reserved DMA windows from host bridge */
+       resource_list_for_each_entry(window, &bridge->dma_ranges) {
+               end = window->res->start - window->offset;
+resv_iova:
+               if (end > start) {
+                       lo = iova_pfn(iovad, start);
+                       hi = iova_pfn(iovad, end);
+                       reserve_iova(iovad, lo, hi);
+               } else {
+                       /* dma_ranges list should be sorted */
+                       dev_err(&dev->dev, "Failed to reserve IOVA\n");
+                       return -EINVAL;
+               }
+
+               start = window->res->end - window->offset + 1;
+               /* If window is last entry */
+               if (window->node.next == &bridge->dma_ranges &&
+                   end != ~(dma_addr_t)0) {
+                       end = ~(dma_addr_t)0;
+                       goto resv_iova;
+               }
+       }
+
+       return 0;
 }
 
 static int iova_reserve_iommu_regions(struct device *dev,
@@ -232,8 +258,11 @@ static int iova_reserve_iommu_regions(struct device *dev,
        LIST_HEAD(resv_regions);
        int ret = 0;
 
-       if (dev_is_pci(dev))
-               iova_reserve_pci_windows(to_pci_dev(dev), iovad);
+       if (dev_is_pci(dev)) {
+               ret = iova_reserve_pci_windows(to_pci_dev(dev), iovad);
+               if (ret)
+                       return ret;
+       }
 
        iommu_get_resv_regions(dev, &resv_regions);
        list_for_each_entry(region, &resv_regions, list) {
@@ -619,17 +648,7 @@ out_free_pages:
 
 int iommu_dma_mmap(struct page **pages, size_t size, struct vm_area_struct *vma)
 {
-       unsigned long uaddr = vma->vm_start;
-       unsigned int i, count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-       int ret = -ENXIO;
-
-       for (i = vma->vm_pgoff; i < count && uaddr < vma->vm_end; i++) {
-               ret = vm_insert_page(vma, uaddr, pages[i]);
-               if (ret)
-                       break;
-               uaddr += PAGE_SIZE;
-       }
-       return ret;
+       return vm_map_pages(vma, pages, PAGE_ALIGN(size) >> PAGE_SHIFT);
 }
 
 static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
index a320bda..a209199 100644 (file)
@@ -1391,7 +1391,7 @@ static void iommu_enable_dev_iotlb(struct device_domain_info *info)
 
                /* pdev will be returned if device is not a vf */
                pf_pdev = pci_physfn(pdev);
-               info->pfsid = PCI_DEVID(pf_pdev->bus->number, pf_pdev->devfn);
+               info->pfsid = pci_dev_id(pf_pdev);
        }
 
 #ifdef CONFIG_INTEL_IOMMU_SVM
index 634d8f0..4160aa9 100644 (file)
@@ -424,7 +424,7 @@ static int set_msi_sid(struct irte *irte, struct pci_dev *dev)
                set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, data.alias);
        else
                set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
-                            PCI_DEVID(dev->bus->number, dev->devfn));
+                            pci_dev_id(dev));
 
        return 0;
 }
index 9fb0eb7..b4b87d6 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/of_iommu.h>
 
 #include <asm/cacheflush.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include "msm_iommu_hw-8xxx.h"
 #include "msm_iommu.h"
index 5438abb..cf79849 100644 (file)
@@ -160,6 +160,12 @@ config IMGPDC_IRQ
        select GENERIC_IRQ_CHIP
        select IRQ_DOMAIN
 
+config IXP4XX_IRQ
+       bool
+       select IRQ_DOMAIN
+       select GENERIC_IRQ_MULTI_HANDLER
+       select SPARSE_IRQ
+
 config MADERA_IRQ
        tristate
 
index 85972ae..f8c66e9 100644 (file)
@@ -43,6 +43,7 @@ obj-$(CONFIG_ATMEL_AIC5_IRQ)  += irq-atmel-aic-common.o irq-atmel-aic5.o
 obj-$(CONFIG_I8259)                    += irq-i8259.o
 obj-$(CONFIG_IMGPDC_IRQ)               += irq-imgpdc.o
 obj-$(CONFIG_IRQ_MIPS_CPU)             += irq-mips-cpu.o
+obj-$(CONFIG_IXP4XX_IRQ)               += irq-ixp4xx.o
 obj-$(CONFIG_SIRF_IRQ)                 += irq-sirfsoc.o
 obj-$(CONFIG_JCORE_AIC)                        += irq-jcore-aic.o
 obj-$(CONFIG_RDA_INTC)                 += irq-rda-intc.o
diff --git a/drivers/irqchip/irq-ixp4xx.c b/drivers/irqchip/irq-ixp4xx.c
new file mode 100644 (file)
index 0000000..d576809
--- /dev/null
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * irqchip for the IXP4xx interrupt controller
+ * Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
+ *
+ * Based on arch/arm/mach-ixp4xx/common.c
+ * Copyright 2002 (C) Intel Corporation
+ * Copyright 2003-2004 (C) MontaVista, Software, Inc.
+ * Copyright (C) Deepak Saxena <dsaxena@plexity.net>
+ */
+#include <linux/bitops.h>
+#include <linux/gpio/driver.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/irq-ixp4xx.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/cpu.h>
+
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#define IXP4XX_ICPR    0x00 /* Interrupt Status */
+#define IXP4XX_ICMR    0x04 /* Interrupt Enable */
+#define IXP4XX_ICLR    0x08 /* Interrupt IRQ/FIQ Select */
+#define IXP4XX_ICIP    0x0C /* IRQ Status */
+#define IXP4XX_ICFP    0x10 /* FIQ Status */
+#define IXP4XX_ICHR    0x14 /* Interrupt Priority */
+#define IXP4XX_ICIH    0x18 /* IRQ Highest Pri Int */
+#define IXP4XX_ICFH    0x1C /* FIQ Highest Pri Int */
+
+/* IXP43x and IXP46x-only */
+#define        IXP4XX_ICPR2    0x20 /* Interrupt Status 2 */
+#define        IXP4XX_ICMR2    0x24 /* Interrupt Enable 2 */
+#define        IXP4XX_ICLR2    0x28 /* Interrupt IRQ/FIQ Select 2 */
+#define IXP4XX_ICIP2   0x2C /* IRQ Status */
+#define IXP4XX_ICFP2   0x30 /* FIQ Status */
+#define IXP4XX_ICEEN   0x34 /* Error High Pri Enable */
+
+/**
+ * struct ixp4xx_irq - state container for the Faraday IRQ controller
+ * @irqbase: IRQ controller memory base in virtual memory
+ * @is_356: if this is an IXP43x, IXP45x or IX46x SoC (with 64 IRQs)
+ * @irqchip: irqchip for this instance
+ * @domain: IRQ domain for this instance
+ */
+struct ixp4xx_irq {
+       void __iomem *irqbase;
+       bool is_356;
+       struct irq_chip irqchip;
+       struct irq_domain *domain;
+};
+
+/* Local static state container */
+static struct ixp4xx_irq ixirq;
+
+/* GPIO Clocks */
+#define IXP4XX_GPIO_CLK_0              14
+#define IXP4XX_GPIO_CLK_1              15
+
+static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type)
+{
+       /* All are level active high (asserted) here */
+       if (type != IRQ_TYPE_LEVEL_HIGH)
+               return -EINVAL;
+       return 0;
+}
+
+static void ixp4xx_irq_mask(struct irq_data *d)
+{
+       struct ixp4xx_irq *ixi = irq_data_get_irq_chip_data(d);
+       u32 val;
+
+       if (ixi->is_356 && d->hwirq >= 32) {
+               val = __raw_readl(ixi->irqbase + IXP4XX_ICMR2);
+               val &= ~BIT(d->hwirq - 32);
+               __raw_writel(val, ixi->irqbase + IXP4XX_ICMR2);
+       } else {
+               val = __raw_readl(ixi->irqbase + IXP4XX_ICMR);
+               val &= ~BIT(d->hwirq);
+               __raw_writel(val, ixi->irqbase + IXP4XX_ICMR);
+       }
+}
+
+/*
+ * Level triggered interrupts on GPIO lines can only be cleared when the
+ * interrupt condition disappears.
+ */
+static void ixp4xx_irq_unmask(struct irq_data *d)
+{
+       struct ixp4xx_irq *ixi = irq_data_get_irq_chip_data(d);
+       u32 val;
+
+       if (ixi->is_356 && d->hwirq >= 32) {
+               val = __raw_readl(ixi->irqbase + IXP4XX_ICMR2);
+               val |= BIT(d->hwirq - 32);
+               __raw_writel(val, ixi->irqbase + IXP4XX_ICMR2);
+       } else {
+               val = __raw_readl(ixi->irqbase + IXP4XX_ICMR);
+               val |= BIT(d->hwirq);
+               __raw_writel(val, ixi->irqbase + IXP4XX_ICMR);
+       }
+}
+
+asmlinkage void __exception_irq_entry ixp4xx_handle_irq(struct pt_regs *regs)
+{
+       struct ixp4xx_irq *ixi = &ixirq;
+       unsigned long status;
+       int i;
+
+       status = __raw_readl(ixi->irqbase + IXP4XX_ICIP);
+       for_each_set_bit(i, &status, 32)
+               handle_domain_irq(ixi->domain, i, regs);
+
+       /*
+        * IXP465/IXP435 has an upper IRQ status register
+        */
+       if (ixi->is_356) {
+               status = __raw_readl(ixi->irqbase + IXP4XX_ICIP2);
+               for_each_set_bit(i, &status, 32)
+                       handle_domain_irq(ixi->domain, i + 32, regs);
+       }
+}
+
+static int ixp4xx_irq_domain_translate(struct irq_domain *domain,
+                                      struct irq_fwspec *fwspec,
+                                      unsigned long *hwirq,
+                                      unsigned int *type)
+{
+       /* We support standard DT translation */
+       if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) {
+               *hwirq = fwspec->param[0];
+               *type = fwspec->param[1];
+               return 0;
+       }
+
+       if (is_fwnode_irqchip(fwspec->fwnode)) {
+               if (fwspec->param_count != 2)
+                       return -EINVAL;
+               *hwirq = fwspec->param[0];
+               *type = fwspec->param[1];
+               WARN_ON(*type == IRQ_TYPE_NONE);
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static int ixp4xx_irq_domain_alloc(struct irq_domain *d,
+                                  unsigned int irq, unsigned int nr_irqs,
+                                  void *data)
+{
+       struct ixp4xx_irq *ixi = d->host_data;
+       irq_hw_number_t hwirq;
+       unsigned int type = IRQ_TYPE_NONE;
+       struct irq_fwspec *fwspec = data;
+       int ret;
+       int i;
+
+       ret = ixp4xx_irq_domain_translate(d, fwspec, &hwirq, &type);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < nr_irqs; i++) {
+               /*
+                * TODO: after converting IXP4xx to only device tree, set
+                * handle_bad_irq as default handler and assume all consumers
+                * call .set_type() as this is provided in the second cell in
+                * the device tree phandle.
+                */
+               irq_domain_set_info(d,
+                                   irq + i,
+                                   hwirq + i,
+                                   &ixi->irqchip,
+                                   ixi,
+                                   handle_level_irq,
+                                   NULL, NULL);
+               irq_set_probe(irq + i);
+       }
+
+       return 0;
+}
+
+/*
+ * This needs to be a hierarchical irqdomain to work well with the
+ * GPIO irqchip (which is lower in the hierarchy)
+ */
+static const struct irq_domain_ops ixp4xx_irqdomain_ops = {
+       .translate = ixp4xx_irq_domain_translate,
+       .alloc = ixp4xx_irq_domain_alloc,
+       .free = irq_domain_free_irqs_common,
+};
+
+/**
+ * ixp4xx_get_irq_domain() - retrieve the ixp4xx irq domain
+ *
+ * This function will go away when we transition to DT probing.
+ */
+struct irq_domain *ixp4xx_get_irq_domain(void)
+{
+       struct ixp4xx_irq *ixi = &ixirq;
+
+       return ixi->domain;
+}
+EXPORT_SYMBOL_GPL(ixp4xx_get_irq_domain);
+
+/*
+ * This is the Linux IRQ to hwirq mapping table. This goes away when
+ * we have DT support as all IRQ resources are defined in the device
+ * tree. It will register all the IRQs that are not used by the hierarchical
+ * GPIO IRQ chip. The "holes" inbetween these IRQs will be requested by
+ * the GPIO driver using . This is a step-gap solution.
+ */
+struct ixp4xx_irq_chunk {
+       int irq;
+       int hwirq;
+       int nr_irqs;
+};
+
+static const struct ixp4xx_irq_chunk ixp4xx_irq_chunks[] = {
+       {
+               .irq = 16,
+               .hwirq = 0,
+               .nr_irqs = 6,
+       },
+       {
+               .irq = 24,
+               .hwirq = 8,
+               .nr_irqs = 11,
+       },
+       {
+               .irq = 46,
+               .hwirq = 30,
+               .nr_irqs = 2,
+       },
+       /* Only on the 436 variants */
+       {
+               .irq = 48,
+               .hwirq = 32,
+               .nr_irqs = 10,
+       },
+};
+
+/**
+ * ixp4x_irq_setup() - Common setup code for the IXP4xx interrupt controller
+ * @ixi: State container
+ * @irqbase: Virtual memory base for the interrupt controller
+ * @fwnode: Corresponding fwnode abstraction for this controller
+ * @is_356: if this is an IXP43x, IXP45x or IXP46x SoC variant
+ */
+static int ixp4xx_irq_setup(struct ixp4xx_irq *ixi,
+                           void __iomem *irqbase,
+                           struct fwnode_handle *fwnode,
+                           bool is_356)
+{
+       int nr_irqs;
+
+       ixi->irqbase = irqbase;
+       ixi->is_356 = is_356;
+
+       /* Route all sources to IRQ instead of FIQ */
+       __raw_writel(0x0, ixi->irqbase + IXP4XX_ICLR);
+
+       /* Disable all interrupts */
+       __raw_writel(0x0, ixi->irqbase + IXP4XX_ICMR);
+
+       if (is_356) {
+               /* Route upper 32 sources to IRQ instead of FIQ */
+               __raw_writel(0x0, ixi->irqbase + IXP4XX_ICLR2);
+
+               /* Disable upper 32 interrupts */
+               __raw_writel(0x0, ixi->irqbase + IXP4XX_ICMR2);
+
+               nr_irqs = 64;
+       } else {
+               nr_irqs = 32;
+       }
+
+       ixi->irqchip.name = "IXP4xx";
+       ixi->irqchip.irq_mask = ixp4xx_irq_mask;
+       ixi->irqchip.irq_unmask = ixp4xx_irq_unmask;
+       ixi->irqchip.irq_set_type = ixp4xx_set_irq_type;
+
+       ixi->domain = irq_domain_create_linear(fwnode, nr_irqs,
+                                              &ixp4xx_irqdomain_ops,
+                                              ixi);
+       if (!ixi->domain) {
+               pr_crit("IXP4XX: can not add primary irqdomain\n");
+               return -ENODEV;
+       }
+
+       set_handle_irq(ixp4xx_handle_irq);
+
+       return 0;
+}
+
+/**
+ * ixp4xx_irq_init() - Function to initialize the irqchip from boardfiles
+ * @irqbase: physical base for the irq controller
+ * @is_356: if this is an IXP43x, IXP45x or IXP46x SoC variant
+ */
+void __init ixp4xx_irq_init(resource_size_t irqbase,
+                           bool is_356)
+{
+       struct ixp4xx_irq *ixi = &ixirq;
+       void __iomem *base;
+       struct fwnode_handle *fwnode;
+       struct irq_fwspec fwspec;
+       int nr_chunks;
+       int ret;
+       int i;
+
+       base = ioremap(irqbase, 0x100);
+       if (!base) {
+               pr_crit("IXP4XX: could not ioremap interrupt controller\n");
+               return;
+       }
+       fwnode = irq_domain_alloc_fwnode(base);
+       if (!fwnode) {
+               pr_crit("IXP4XX: no domain handle\n");
+               return;
+       }
+       ret = ixp4xx_irq_setup(ixi, base, fwnode, is_356);
+       if (ret) {
+               pr_crit("IXP4XX: failed to set up irqchip\n");
+               irq_domain_free_fwnode(fwnode);
+       }
+
+       nr_chunks = ARRAY_SIZE(ixp4xx_irq_chunks);
+       if (!is_356)
+               nr_chunks--;
+
+       /*
+        * After adding OF support, this is no longer needed: irqs
+        * will be allocated for the respective fwnodes.
+        */
+       for (i = 0; i < nr_chunks; i++) {
+               const struct ixp4xx_irq_chunk *chunk = &ixp4xx_irq_chunks[i];
+
+               pr_info("Allocate Linux IRQs %d..%d HW IRQs %d..%d\n",
+                       chunk->irq, chunk->irq + chunk->nr_irqs - 1,
+                       chunk->hwirq, chunk->hwirq + chunk->nr_irqs - 1);
+               fwspec.fwnode = fwnode;
+               fwspec.param[0] = chunk->hwirq;
+               fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
+               fwspec.param_count = 2;
+               ret = __irq_domain_alloc_irqs(ixi->domain,
+                                             chunk->irq,
+                                             chunk->nr_irqs,
+                                             NUMA_NO_NODE,
+                                             &fwspec,
+                                             false,
+                                             NULL);
+               if (ret < 0) {
+                       pr_crit("IXP4XX: can not allocate irqs in hierarchy %d\n",
+                               ret);
+                       return;
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(ixp4xx_irq_init);
+
+#ifdef CONFIG_OF
+int __init ixp4xx_of_init_irq(struct device_node *np,
+                             struct device_node *parent)
+{
+       struct ixp4xx_irq *ixi = &ixirq;
+       void __iomem *base;
+       struct fwnode_handle *fwnode;
+       bool is_356;
+       int ret;
+
+       base = of_iomap(np, 0);
+       if (!base) {
+               pr_crit("IXP4XX: could not ioremap interrupt controller\n");
+               return -ENODEV;
+       }
+       fwnode = of_node_to_fwnode(np);
+
+       /* These chip variants have 64 interrupts */
+       is_356 = of_device_is_compatible(np, "intel,ixp43x-interrupt") ||
+               of_device_is_compatible(np, "intel,ixp45x-interrupt") ||
+               of_device_is_compatible(np, "intel,ixp46x-interrupt");
+
+       ret = ixp4xx_irq_setup(ixi, base, fwnode, is_356);
+       if (ret)
+               pr_crit("IXP4XX: failed to set up irqchip\n");
+
+       return ret;
+}
+IRQCHIP_DECLARE(ixp42x, "intel,ixp42x-interrupt",
+               ixp4xx_of_init_irq);
+IRQCHIP_DECLARE(ixp43x, "intel,ixp43x-interrupt",
+               ixp4xx_of_init_irq);
+IRQCHIP_DECLARE(ixp45x, "intel,ixp45x-interrupt",
+               ixp4xx_of_init_irq);
+IRQCHIP_DECLARE(ixp46x, "intel,ixp46x-interrupt",
+               ixp4xx_of_init_irq);
+#endif
index f3000cc..71be87b 100644 (file)
@@ -619,6 +619,12 @@ config LEDS_TLC591XX
          This option enables support for Texas Instruments TLC59108
          and TLC59116 LED controllers.
 
+config LEDS_MAX77650
+       tristate "LED support for Maxim MAX77650 PMIC"
+       depends on LEDS_CLASS && MFD_MAX77650
+       help
+         LEDs driver for MAX77650 family of PMICs from Maxim Integrated.
+
 config LEDS_MAX77693
        tristate "LED support for MAX77693 Flash"
        depends on LEDS_CLASS_FLASH
index 7a8b1f5..1e9702e 100644 (file)
@@ -62,6 +62,7 @@ obj-$(CONFIG_LEDS_MC13783)            += leds-mc13783.o
 obj-$(CONFIG_LEDS_NS2)                 += leds-ns2.o
 obj-$(CONFIG_LEDS_NETXBIG)             += leds-netxbig.o
 obj-$(CONFIG_LEDS_ASIC3)               += leds-asic3.o
+obj-$(CONFIG_LEDS_MAX77650)            += leds-max77650.o
 obj-$(CONFIG_LEDS_MAX77693)            += leds-max77693.o
 obj-$(CONFIG_LEDS_MAX8997)             += leds-max8997.o
 obj-$(CONFIG_LEDS_LM355x)              += leds-lm355x.o
diff --git a/drivers/leds/leds-max77650.c b/drivers/leds/leds-max77650.c
new file mode 100644 (file)
index 0000000..6b74ce9
--- /dev/null
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// LED driver for MAXIM 77650/77651 charger/power-supply.
+
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/mfd/max77650.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define MAX77650_LED_NUM_LEDS          3
+
+#define MAX77650_LED_A_BASE            0x40
+#define MAX77650_LED_B_BASE            0x43
+
+#define MAX77650_LED_BR_MASK           GENMASK(4, 0)
+#define MAX77650_LED_EN_MASK           GENMASK(7, 6)
+
+#define MAX77650_LED_MAX_BRIGHTNESS    MAX77650_LED_BR_MASK
+
+/* Enable EN_LED_MSTR. */
+#define MAX77650_LED_TOP_DEFAULT       BIT(0)
+
+#define MAX77650_LED_ENABLE            GENMASK(7, 6)
+#define MAX77650_LED_DISABLE           0x00
+
+#define MAX77650_LED_A_DEFAULT         MAX77650_LED_DISABLE
+/* 100% on duty */
+#define MAX77650_LED_B_DEFAULT         GENMASK(3, 0)
+
+struct max77650_led {
+       struct led_classdev cdev;
+       struct regmap *map;
+       unsigned int regA;
+       unsigned int regB;
+};
+
+static struct max77650_led *max77650_to_led(struct led_classdev *cdev)
+{
+       return container_of(cdev, struct max77650_led, cdev);
+}
+
+static int max77650_led_brightness_set(struct led_classdev *cdev,
+                                      enum led_brightness brightness)
+{
+       struct max77650_led *led = max77650_to_led(cdev);
+       int val, mask;
+
+       mask = MAX77650_LED_BR_MASK | MAX77650_LED_EN_MASK;
+
+       if (brightness == LED_OFF)
+               val = MAX77650_LED_DISABLE;
+       else
+               val = MAX77650_LED_ENABLE | brightness;
+
+       return regmap_update_bits(led->map, led->regA, mask, val);
+}
+
+static int max77650_led_probe(struct platform_device *pdev)
+{
+       struct device_node *of_node, *child;
+       struct max77650_led *leds, *led;
+       struct device *parent;
+       struct device *dev;
+       struct regmap *map;
+       const char *label;
+       int rv, num_leds;
+       u32 reg;
+
+       dev = &pdev->dev;
+       parent = dev->parent;
+       of_node = dev->of_node;
+
+       if (!of_node)
+               return -ENODEV;
+
+       leds = devm_kcalloc(dev, sizeof(*leds),
+                           MAX77650_LED_NUM_LEDS, GFP_KERNEL);
+       if (!leds)
+               return -ENOMEM;
+
+       map = dev_get_regmap(dev->parent, NULL);
+       if (!map)
+               return -ENODEV;
+
+       num_leds = of_get_child_count(of_node);
+       if (!num_leds || num_leds > MAX77650_LED_NUM_LEDS)
+               return -ENODEV;
+
+       for_each_child_of_node(of_node, child) {
+               rv = of_property_read_u32(child, "reg", &reg);
+               if (rv || reg >= MAX77650_LED_NUM_LEDS)
+                       return -EINVAL;
+
+               led = &leds[reg];
+               led->map = map;
+               led->regA = MAX77650_LED_A_BASE + reg;
+               led->regB = MAX77650_LED_B_BASE + reg;
+               led->cdev.brightness_set_blocking = max77650_led_brightness_set;
+               led->cdev.max_brightness = MAX77650_LED_MAX_BRIGHTNESS;
+
+               label = of_get_property(child, "label", NULL);
+               if (!label) {
+                       led->cdev.name = "max77650::";
+               } else {
+                       led->cdev.name = devm_kasprintf(dev, GFP_KERNEL,
+                                                       "max77650:%s", label);
+                       if (!led->cdev.name)
+                               return -ENOMEM;
+               }
+
+               of_property_read_string(child, "linux,default-trigger",
+                                       &led->cdev.default_trigger);
+
+               rv = devm_of_led_classdev_register(dev, child, &led->cdev);
+               if (rv)
+                       return rv;
+
+               rv = regmap_write(map, led->regA, MAX77650_LED_A_DEFAULT);
+               if (rv)
+                       return rv;
+
+               rv = regmap_write(map, led->regB, MAX77650_LED_B_DEFAULT);
+               if (rv)
+                       return rv;
+       }
+
+       return regmap_write(map,
+                           MAX77650_REG_CNFG_LED_TOP,
+                           MAX77650_LED_TOP_DEFAULT);
+}
+
+static struct platform_driver max77650_led_driver = {
+       .driver = {
+               .name = "max77650-led",
+       },
+       .probe = max77650_led_probe,
+};
+module_platform_driver(max77650_led_driver);
+
+MODULE_DESCRIPTION("MAXIM 77650/77651 LED driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL v2");
index 5f82036..0df7454 100644 (file)
@@ -45,6 +45,8 @@ struct nvm_dev_map {
        int num_ch;
 };
 
+static void nvm_free(struct kref *ref);
+
 static struct nvm_target *nvm_find_target(struct nvm_dev *dev, const char *name)
 {
        struct nvm_target *tgt;
@@ -325,6 +327,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
        struct nvm_target *t;
        struct nvm_tgt_dev *tgt_dev;
        void *targetdata;
+       unsigned int mdts;
        int ret;
 
        switch (create->conf.type) {
@@ -412,8 +415,12 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
        tdisk->private_data = targetdata;
        tqueue->queuedata = targetdata;
 
-       blk_queue_max_hw_sectors(tqueue,
-                       (dev->geo.csecs >> 9) * NVM_MAX_VLBA);
+       mdts = (dev->geo.csecs >> 9) * NVM_MAX_VLBA;
+       if (dev->geo.mdts) {
+               mdts = min_t(u32, dev->geo.mdts,
+                               (dev->geo.csecs >> 9) * NVM_MAX_VLBA);
+       }
+       blk_queue_max_hw_sectors(tqueue, mdts);
 
        set_capacity(tdisk, tt->capacity(targetdata));
        add_disk(tdisk);
@@ -476,7 +483,6 @@ static void __nvm_remove_target(struct nvm_target *t, bool graceful)
 
 /**
  * nvm_remove_tgt - Removes a target from the media manager
- * @dev:       device
  * @remove:    ioctl structure with target name to remove.
  *
  * Returns:
@@ -484,18 +490,28 @@ static void __nvm_remove_target(struct nvm_target *t, bool graceful)
  * 1: on not found
  * <0: on error
  */
-static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove)
+static int nvm_remove_tgt(struct nvm_ioctl_remove *remove)
 {
        struct nvm_target *t;
+       struct nvm_dev *dev;
 
-       mutex_lock(&dev->mlock);
-       t = nvm_find_target(dev, remove->tgtname);
-       if (!t) {
+       down_read(&nvm_lock);
+       list_for_each_entry(dev, &nvm_devices, devices) {
+               mutex_lock(&dev->mlock);
+               t = nvm_find_target(dev, remove->tgtname);
+               if (t) {
+                       mutex_unlock(&dev->mlock);
+                       break;
+               }
                mutex_unlock(&dev->mlock);
-               return 1;
        }
+       up_read(&nvm_lock);
+
+       if (!t)
+               return 1;
+
        __nvm_remove_target(t, true);
-       mutex_unlock(&dev->mlock);
+       kref_put(&dev->ref, nvm_free);
 
        return 0;
 }
@@ -1089,15 +1105,16 @@ err_fmtype:
        return ret;
 }
 
-static void nvm_free(struct nvm_dev *dev)
+static void nvm_free(struct kref *ref)
 {
-       if (!dev)
-               return;
+       struct nvm_dev *dev = container_of(ref, struct nvm_dev, ref);
 
        if (dev->dma_pool)
                dev->ops->destroy_dma_pool(dev->dma_pool);
 
-       nvm_unregister_map(dev);
+       if (dev->rmap)
+               nvm_unregister_map(dev);
+
        kfree(dev->lun_map);
        kfree(dev);
 }
@@ -1134,7 +1151,13 @@ err:
 
 struct nvm_dev *nvm_alloc_dev(int node)
 {
-       return kzalloc_node(sizeof(struct nvm_dev), GFP_KERNEL, node);
+       struct nvm_dev *dev;
+
+       dev = kzalloc_node(sizeof(struct nvm_dev), GFP_KERNEL, node);
+       if (dev)
+               kref_init(&dev->ref);
+
+       return dev;
 }
 EXPORT_SYMBOL(nvm_alloc_dev);
 
@@ -1142,12 +1165,16 @@ int nvm_register(struct nvm_dev *dev)
 {
        int ret, exp_pool_size;
 
-       if (!dev->q || !dev->ops)
+       if (!dev->q || !dev->ops) {
+               kref_put(&dev->ref, nvm_free);
                return -EINVAL;
+       }
 
        ret = nvm_init(dev);
-       if (ret)
+       if (ret) {
+               kref_put(&dev->ref, nvm_free);
                return ret;
+       }
 
        exp_pool_size = max_t(int, PAGE_SIZE,
                              (NVM_MAX_VLBA * (sizeof(u64) + dev->geo.sos)));
@@ -1157,7 +1184,7 @@ int nvm_register(struct nvm_dev *dev)
                                                  exp_pool_size);
        if (!dev->dma_pool) {
                pr_err("nvm: could not create dma pool\n");
-               nvm_free(dev);
+               kref_put(&dev->ref, nvm_free);
                return -ENOMEM;
        }
 
@@ -1179,6 +1206,7 @@ void nvm_unregister(struct nvm_dev *dev)
                if (t->dev->parent != dev)
                        continue;
                __nvm_remove_target(t, false);
+               kref_put(&dev->ref, nvm_free);
        }
        mutex_unlock(&dev->mlock);
 
@@ -1186,13 +1214,14 @@ void nvm_unregister(struct nvm_dev *dev)
        list_del(&dev->devices);
        up_write(&nvm_lock);
 
-       nvm_free(dev);
+       kref_put(&dev->ref, nvm_free);
 }
 EXPORT_SYMBOL(nvm_unregister);
 
 static int __nvm_configure_create(struct nvm_ioctl_create *create)
 {
        struct nvm_dev *dev;
+       int ret;
 
        down_write(&nvm_lock);
        dev = nvm_find_nvm_dev(create->dev);
@@ -1203,7 +1232,12 @@ static int __nvm_configure_create(struct nvm_ioctl_create *create)
                return -EINVAL;
        }
 
-       return nvm_create_tgt(dev, create);
+       kref_get(&dev->ref);
+       ret = nvm_create_tgt(dev, create);
+       if (ret)
+               kref_put(&dev->ref, nvm_free);
+
+       return ret;
 }
 
 static long nvm_ioctl_info(struct file *file, void __user *arg)
@@ -1322,8 +1356,6 @@ static long nvm_ioctl_dev_create(struct file *file, void __user *arg)
 static long nvm_ioctl_dev_remove(struct file *file, void __user *arg)
 {
        struct nvm_ioctl_remove remove;
-       struct nvm_dev *dev;
-       int ret = 0;
 
        if (copy_from_user(&remove, arg, sizeof(struct nvm_ioctl_remove)))
                return -EFAULT;
@@ -1335,13 +1367,7 @@ static long nvm_ioctl_dev_remove(struct file *file, void __user *arg)
                return -EINVAL;
        }
 
-       list_for_each_entry(dev, &nvm_devices, devices) {
-               ret = nvm_remove_tgt(dev, &remove);
-               if (!ret)
-                       break;
-       }
-
-       return ret;
+       return nvm_remove_tgt(&remove);
 }
 
 /* kept for compatibility reasons */
index c9fa26f..5c1034c 100644 (file)
@@ -18,7 +18,8 @@
 
 #include "pblk.h"
 
-int pblk_write_to_cache(struct pblk *pblk, struct bio *bio, unsigned long flags)
+void pblk_write_to_cache(struct pblk *pblk, struct bio *bio,
+                               unsigned long flags)
 {
        struct request_queue *q = pblk->dev->q;
        struct pblk_w_ctx w_ctx;
@@ -43,6 +44,7 @@ retry:
                goto retry;
        case NVM_IO_ERR:
                pblk_pipeline_stop(pblk);
+               bio_io_error(bio);
                goto out;
        }
 
@@ -79,7 +81,9 @@ retry:
 out:
        generic_end_io_acct(q, REQ_OP_WRITE, &pblk->disk->part0, start_time);
        pblk_write_should_kick(pblk);
-       return ret;
+
+       if (ret == NVM_IO_DONE)
+               bio_endio(bio);
 }
 
 /*
index 6ca8688..7735378 100644 (file)
@@ -562,11 +562,9 @@ int pblk_submit_io_sync(struct pblk *pblk, struct nvm_rq *rqd)
 
 int pblk_submit_io_sync_sem(struct pblk *pblk, struct nvm_rq *rqd)
 {
-       struct ppa_addr *ppa_list;
+       struct ppa_addr *ppa_list = nvm_rq_to_ppa_list(rqd);
        int ret;
 
-       ppa_list = (rqd->nr_ppas > 1) ? rqd->ppa_list : &rqd->ppa_addr;
-
        pblk_down_chunk(pblk, ppa_list[0]);
        ret = pblk_submit_io_sync(pblk, rqd);
        pblk_up_chunk(pblk, ppa_list[0]);
@@ -725,6 +723,7 @@ int pblk_line_smeta_read(struct pblk *pblk, struct pblk_line *line)
        struct nvm_tgt_dev *dev = pblk->dev;
        struct pblk_line_meta *lm = &pblk->lm;
        struct bio *bio;
+       struct ppa_addr *ppa_list;
        struct nvm_rq rqd;
        u64 paddr = pblk_line_smeta_start(pblk, line);
        int i, ret;
@@ -748,9 +747,10 @@ int pblk_line_smeta_read(struct pblk *pblk, struct pblk_line *line)
        rqd.opcode = NVM_OP_PREAD;
        rqd.nr_ppas = lm->smeta_sec;
        rqd.is_seq = 1;
+       ppa_list = nvm_rq_to_ppa_list(&rqd);
 
        for (i = 0; i < lm->smeta_sec; i++, paddr++)
-               rqd.ppa_list[i] = addr_to_gen_ppa(pblk, paddr, line->id);
+               ppa_list[i] = addr_to_gen_ppa(pblk, paddr, line->id);
 
        ret = pblk_submit_io_sync(pblk, &rqd);
        if (ret) {
@@ -761,8 +761,10 @@ int pblk_line_smeta_read(struct pblk *pblk, struct pblk_line *line)
 
        atomic_dec(&pblk->inflight_io);
 
-       if (rqd.error)
+       if (rqd.error && rqd.error != NVM_RSP_WARN_HIGHECC) {
                pblk_log_read_err(pblk, &rqd);
+               ret = -EIO;
+       }
 
 clear_rqd:
        pblk_free_rqd_meta(pblk, &rqd);
@@ -775,6 +777,7 @@ static int pblk_line_smeta_write(struct pblk *pblk, struct pblk_line *line,
        struct nvm_tgt_dev *dev = pblk->dev;
        struct pblk_line_meta *lm = &pblk->lm;
        struct bio *bio;
+       struct ppa_addr *ppa_list;
        struct nvm_rq rqd;
        __le64 *lba_list = emeta_to_lbas(pblk, line->emeta->buf);
        __le64 addr_empty = cpu_to_le64(ADDR_EMPTY);
@@ -799,12 +802,13 @@ static int pblk_line_smeta_write(struct pblk *pblk, struct pblk_line *line,
        rqd.opcode = NVM_OP_PWRITE;
        rqd.nr_ppas = lm->smeta_sec;
        rqd.is_seq = 1;
+       ppa_list = nvm_rq_to_ppa_list(&rqd);
 
        for (i = 0; i < lm->smeta_sec; i++, paddr++) {
                struct pblk_sec_meta *meta = pblk_get_meta(pblk,
                                                           rqd.meta_list, i);
 
-               rqd.ppa_list[i] = addr_to_gen_ppa(pblk, paddr, line->id);
+               ppa_list[i] = addr_to_gen_ppa(pblk, paddr, line->id);
                meta->lba = lba_list[paddr] = addr_empty;
        }
 
@@ -834,8 +838,9 @@ int pblk_line_emeta_read(struct pblk *pblk, struct pblk_line *line,
        struct nvm_geo *geo = &dev->geo;
        struct pblk_line_mgmt *l_mg = &pblk->l_mg;
        struct pblk_line_meta *lm = &pblk->lm;
-       void *ppa_list, *meta_list;
+       void *ppa_list_buf, *meta_list;
        struct bio *bio;
+       struct ppa_addr *ppa_list;
        struct nvm_rq rqd;
        u64 paddr = line->emeta_ssec;
        dma_addr_t dma_ppa_list, dma_meta_list;
@@ -851,7 +856,7 @@ int pblk_line_emeta_read(struct pblk *pblk, struct pblk_line *line,
        if (!meta_list)
                return -ENOMEM;
 
-       ppa_list = meta_list + pblk_dma_meta_size(pblk);
+       ppa_list_buf = meta_list + pblk_dma_meta_size(pblk);
        dma_ppa_list = dma_meta_list + pblk_dma_meta_size(pblk);
 
 next_rq:
@@ -872,11 +877,12 @@ next_rq:
 
        rqd.bio = bio;
        rqd.meta_list = meta_list;
-       rqd.ppa_list = ppa_list;
+       rqd.ppa_list = ppa_list_buf;
        rqd.dma_meta_list = dma_meta_list;
        rqd.dma_ppa_list = dma_ppa_list;
        rqd.opcode = NVM_OP_PREAD;
        rqd.nr_ppas = rq_ppas;
+       ppa_list = nvm_rq_to_ppa_list(&rqd);
 
        for (i = 0; i < rqd.nr_ppas; ) {
                struct ppa_addr ppa = addr_to_gen_ppa(pblk, paddr, line_id);
@@ -904,7 +910,7 @@ next_rq:
                }
 
                for (j = 0; j < min; j++, i++, paddr++)
-                       rqd.ppa_list[i] = addr_to_gen_ppa(pblk, paddr, line_id);
+                       ppa_list[i] = addr_to_gen_ppa(pblk, paddr, line_id);
        }
 
        ret = pblk_submit_io_sync(pblk, &rqd);
@@ -916,8 +922,11 @@ next_rq:
 
        atomic_dec(&pblk->inflight_io);
 
-       if (rqd.error)
+       if (rqd.error && rqd.error != NVM_RSP_WARN_HIGHECC) {
                pblk_log_read_err(pblk, &rqd);
+               ret = -EIO;
+               goto free_rqd_dma;
+       }
 
        emeta_buf += rq_len;
        left_ppas -= rq_ppas;
@@ -1162,7 +1171,6 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
        off = bit * geo->ws_opt;
        bitmap_set(line->map_bitmap, off, lm->smeta_sec);
        line->sec_in_line -= lm->smeta_sec;
-       line->smeta_ssec = off;
        line->cur_sec = off + lm->smeta_sec;
 
        if (init && pblk_line_smeta_write(pblk, line, off)) {
@@ -1521,11 +1529,9 @@ void pblk_ppa_to_line_put(struct pblk *pblk, struct ppa_addr ppa)
 
 void pblk_rq_to_line_put(struct pblk *pblk, struct nvm_rq *rqd)
 {
-       struct ppa_addr *ppa_list;
+       struct ppa_addr *ppa_list = nvm_rq_to_ppa_list(rqd);
        int i;
 
-       ppa_list = (rqd->nr_ppas > 1) ? rqd->ppa_list : &rqd->ppa_addr;
-
        for (i = 0; i < rqd->nr_ppas; i++)
                pblk_ppa_to_line_put(pblk, ppa_list[i]);
 }
@@ -1699,6 +1705,14 @@ static void __pblk_line_put(struct pblk *pblk, struct pblk_line *line)
 
        spin_lock(&line->lock);
        WARN_ON(line->state != PBLK_LINESTATE_GC);
+       if (line->w_err_gc->has_gc_err) {
+               spin_unlock(&line->lock);
+               pblk_err(pblk, "line %d had errors during GC\n", line->id);
+               pblk_put_line_back(pblk, line);
+               line->w_err_gc->has_gc_err = 0;
+               return;
+       }
+
        line->state = PBLK_LINESTATE_FREE;
        trace_pblk_line_state(pblk_disk_name(pblk), line->id,
                                        line->state);
@@ -2023,7 +2037,7 @@ void pblk_update_map(struct pblk *pblk, sector_t lba, struct ppa_addr ppa)
        struct ppa_addr ppa_l2p;
 
        /* logic error: lba out-of-bounds. Ignore update */
-       if (!(lba < pblk->rl.nr_secs)) {
+       if (!(lba < pblk->capacity)) {
                WARN(1, "pblk: corrupted L2P map request\n");
                return;
        }
@@ -2063,7 +2077,7 @@ int pblk_update_map_gc(struct pblk *pblk, sector_t lba, struct ppa_addr ppa_new,
 #endif
 
        /* logic error: lba out-of-bounds. Ignore update */
-       if (!(lba < pblk->rl.nr_secs)) {
+       if (!(lba < pblk->capacity)) {
                WARN(1, "pblk: corrupted L2P map request\n");
                return 0;
        }
@@ -2109,7 +2123,7 @@ void pblk_update_map_dev(struct pblk *pblk, sector_t lba,
        }
 
        /* logic error: lba out-of-bounds. Ignore update */
-       if (!(lba < pblk->rl.nr_secs)) {
+       if (!(lba < pblk->capacity)) {
                WARN(1, "pblk: corrupted L2P map request\n");
                return;
        }
@@ -2135,8 +2149,8 @@ out:
        spin_unlock(&pblk->trans_lock);
 }
 
-void pblk_lookup_l2p_seq(struct pblk *pblk, struct ppa_addr *ppas,
-                        sector_t blba, int nr_secs)
+int pblk_lookup_l2p_seq(struct pblk *pblk, struct ppa_addr *ppas,
+                        sector_t blba, int nr_secs, bool *from_cache)
 {
        int i;
 
@@ -2150,10 +2164,19 @@ void pblk_lookup_l2p_seq(struct pblk *pblk, struct ppa_addr *ppas,
                if (!pblk_ppa_empty(ppa) && !pblk_addr_in_cache(ppa)) {
                        struct pblk_line *line = pblk_ppa_to_line(pblk, ppa);
 
+                       if (i > 0 && *from_cache)
+                               break;
+                       *from_cache = false;
+
                        kref_get(&line->ref);
+               } else {
+                       if (i > 0 && !*from_cache)
+                               break;
+                       *from_cache = true;
                }
        }
        spin_unlock(&pblk->trans_lock);
+       return i;
 }
 
 void pblk_lookup_l2p_rand(struct pblk *pblk, struct ppa_addr *ppas,
@@ -2167,7 +2190,7 @@ void pblk_lookup_l2p_rand(struct pblk *pblk, struct ppa_addr *ppas,
                lba = lba_list[i];
                if (lba != ADDR_EMPTY) {
                        /* logic error: lba out-of-bounds. Ignore update */
-                       if (!(lba < pblk->rl.nr_secs)) {
+                       if (!(lba < pblk->capacity)) {
                                WARN(1, "pblk: corrupted L2P map request\n");
                                continue;
                        }
index 26a52ea..63ee205 100644 (file)
@@ -59,24 +59,28 @@ static void pblk_gc_writer_kick(struct pblk_gc *gc)
        wake_up_process(gc->gc_writer_ts);
 }
 
-static void pblk_put_line_back(struct pblk *pblk, struct pblk_line *line)
+void pblk_put_line_back(struct pblk *pblk, struct pblk_line *line)
 {
        struct pblk_line_mgmt *l_mg = &pblk->l_mg;
        struct list_head *move_list;
 
+       spin_lock(&l_mg->gc_lock);
        spin_lock(&line->lock);
        WARN_ON(line->state != PBLK_LINESTATE_GC);
        line->state = PBLK_LINESTATE_CLOSED;
        trace_pblk_line_state(pblk_disk_name(pblk), line->id,
                                        line->state);
+
+       /* We need to reset gc_group in order to ensure that
+        * pblk_line_gc_list will return proper move_list
+        * since right now current line is not on any of the
+        * gc lists.
+        */
+       line->gc_group = PBLK_LINEGC_NONE;
        move_list = pblk_line_gc_list(pblk, line);
        spin_unlock(&line->lock);
-
-       if (move_list) {
-               spin_lock(&l_mg->gc_lock);
-               list_add_tail(&line->list, move_list);
-               spin_unlock(&l_mg->gc_lock);
-       }
+       list_add_tail(&line->list, move_list);
+       spin_unlock(&l_mg->gc_lock);
 }
 
 static void pblk_gc_line_ws(struct work_struct *work)
@@ -84,8 +88,6 @@ static void pblk_gc_line_ws(struct work_struct *work)
        struct pblk_line_ws *gc_rq_ws = container_of(work,
                                                struct pblk_line_ws, ws);
        struct pblk *pblk = gc_rq_ws->pblk;
-       struct nvm_tgt_dev *dev = pblk->dev;
-       struct nvm_geo *geo = &dev->geo;
        struct pblk_gc *gc = &pblk->gc;
        struct pblk_line *line = gc_rq_ws->line;
        struct pblk_gc_rq *gc_rq = gc_rq_ws->priv;
@@ -93,18 +95,10 @@ static void pblk_gc_line_ws(struct work_struct *work)
 
        up(&gc->gc_sem);
 
-       gc_rq->data = vmalloc(array_size(gc_rq->nr_secs, geo->csecs));
-       if (!gc_rq->data) {
-               pblk_err(pblk, "could not GC line:%d (%d/%d)\n",
-                                       line->id, *line->vsc, gc_rq->nr_secs);
-               goto out;
-       }
-
        /* Read from GC victim block */
        ret = pblk_submit_read_gc(pblk, gc_rq);
        if (ret) {
-               pblk_err(pblk, "failed GC read in line:%d (err:%d)\n",
-                                                               line->id, ret);
+               line->w_err_gc->has_gc_err = 1;
                goto out;
        }
 
@@ -189,6 +183,8 @@ static void pblk_gc_line_prepare_ws(struct work_struct *work)
        struct pblk_line *line = line_ws->line;
        struct pblk_line_mgmt *l_mg = &pblk->l_mg;
        struct pblk_line_meta *lm = &pblk->lm;
+       struct nvm_tgt_dev *dev = pblk->dev;
+       struct nvm_geo *geo = &dev->geo;
        struct pblk_gc *gc = &pblk->gc;
        struct pblk_line_ws *gc_rq_ws;
        struct pblk_gc_rq *gc_rq;
@@ -247,9 +243,13 @@ next_rq:
        gc_rq->nr_secs = nr_secs;
        gc_rq->line = line;
 
+       gc_rq->data = vmalloc(array_size(gc_rq->nr_secs, geo->csecs));
+       if (!gc_rq->data)
+               goto fail_free_gc_rq;
+
        gc_rq_ws = kmalloc(sizeof(struct pblk_line_ws), GFP_KERNEL);
        if (!gc_rq_ws)
-               goto fail_free_gc_rq;
+               goto fail_free_gc_data;
 
        gc_rq_ws->pblk = pblk;
        gc_rq_ws->line = line;
@@ -281,6 +281,8 @@ out:
 
        return;
 
+fail_free_gc_data:
+       vfree(gc_rq->data);
 fail_free_gc_rq:
        kfree(gc_rq);
 fail_free_lba_list:
@@ -290,8 +292,11 @@ fail_free_invalid_bitmap:
 fail_free_ws:
        kfree(line_ws);
 
+       /* Line goes back to closed state, so we cannot release additional
+        * reference for line, since we do that only when we want to do
+        * gc to free line state transition.
+        */
        pblk_put_line_back(pblk, line);
-       kref_put(&line->ref, pblk_line_put);
        atomic_dec(&gc->read_inflight_gc);
 
        pblk_err(pblk, "failed to GC line %d\n", line->id);
@@ -355,8 +360,13 @@ static int pblk_gc_read(struct pblk *pblk)
 
        pblk_gc_kick(pblk);
 
-       if (pblk_gc_line(pblk, line))
+       if (pblk_gc_line(pblk, line)) {
                pblk_err(pblk, "failed to GC line %d\n", line->id);
+               /* rollback */
+               spin_lock(&gc->r_lock);
+               list_add_tail(&line->list, &gc->r_list);
+               spin_unlock(&gc->r_lock);
+       }
 
        return 0;
 }
index 8b643d0..b351c7f 100644 (file)
@@ -47,33 +47,6 @@ static struct pblk_global_caches pblk_caches = {
 
 struct bio_set pblk_bio_set;
 
-static int pblk_rw_io(struct request_queue *q, struct pblk *pblk,
-                         struct bio *bio)
-{
-       int ret;
-
-       /* Read requests must be <= 256kb due to NVMe's 64 bit completion bitmap
-        * constraint. Writes can be of arbitrary size.
-        */
-       if (bio_data_dir(bio) == READ) {
-               blk_queue_split(q, &bio);
-               ret = pblk_submit_read(pblk, bio);
-               if (ret == NVM_IO_DONE && bio_flagged(bio, BIO_CLONED))
-                       bio_put(bio);
-
-               return ret;
-       }
-
-       /* Prevent deadlock in the case of a modest LUN configuration and large
-        * user I/Os. Unless stalled, the rate limiter leaves at least 256KB
-        * available for user I/O.
-        */
-       if (pblk_get_secs(bio) > pblk_rl_max_io(&pblk->rl))
-               blk_queue_split(q, &bio);
-
-       return pblk_write_to_cache(pblk, bio, PBLK_IOTYPE_USER);
-}
-
 static blk_qc_t pblk_make_rq(struct request_queue *q, struct bio *bio)
 {
        struct pblk *pblk = q->queuedata;
@@ -86,13 +59,21 @@ static blk_qc_t pblk_make_rq(struct request_queue *q, struct bio *bio)
                }
        }
 
-       switch (pblk_rw_io(q, pblk, bio)) {
-       case NVM_IO_ERR:
-               bio_io_error(bio);
-               break;
-       case NVM_IO_DONE:
-               bio_endio(bio);
-               break;
+       /* Read requests must be <= 256kb due to NVMe's 64 bit completion bitmap
+        * constraint. Writes can be of arbitrary size.
+        */
+       if (bio_data_dir(bio) == READ) {
+               blk_queue_split(q, &bio);
+               pblk_submit_read(pblk, bio);
+       } else {
+               /* Prevent deadlock in the case of a modest LUN configuration
+                * and large user I/Os. Unless stalled, the rate limiter
+                * leaves at least 256KB available for user I/O.
+                */
+               if (pblk_get_secs(bio) > pblk_rl_max_io(&pblk->rl))
+                       blk_queue_split(q, &bio);
+
+               pblk_write_to_cache(pblk, bio, PBLK_IOTYPE_USER);
        }
 
        return BLK_QC_T_NONE;
@@ -105,7 +86,7 @@ static size_t pblk_trans_map_size(struct pblk *pblk)
        if (pblk->addrf_len < 32)
                entry_size = 4;
 
-       return entry_size * pblk->rl.nr_secs;
+       return entry_size * pblk->capacity;
 }
 
 #ifdef CONFIG_NVM_PBLK_DEBUG
@@ -164,13 +145,18 @@ static int pblk_l2p_init(struct pblk *pblk, bool factory_init)
        int ret = 0;
 
        map_size = pblk_trans_map_size(pblk);
-       pblk->trans_map = vmalloc(map_size);
-       if (!pblk->trans_map)
+       pblk->trans_map = __vmalloc(map_size, GFP_KERNEL | __GFP_NOWARN
+                                       | __GFP_RETRY_MAYFAIL | __GFP_HIGHMEM,
+                                       PAGE_KERNEL);
+       if (!pblk->trans_map) {
+               pblk_err(pblk, "failed to allocate L2P (need %zu of memory)\n",
+                               map_size);
                return -ENOMEM;
+       }
 
        pblk_ppa_set_empty(&ppa);
 
-       for (i = 0; i < pblk->rl.nr_secs; i++)
+       for (i = 0; i < pblk->capacity; i++)
                pblk_trans_map_set(pblk, i, ppa);
 
        ret = pblk_l2p_recover(pblk, factory_init);
@@ -701,7 +687,6 @@ static int pblk_set_provision(struct pblk *pblk, int nr_free_chks)
         * on user capacity consider only provisioned blocks
         */
        pblk->rl.total_blocks = nr_free_chks;
-       pblk->rl.nr_secs = nr_free_chks * geo->clba;
 
        /* Consider sectors used for metadata */
        sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
@@ -1284,7 +1269,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
 
        pblk_info(pblk, "luns:%u, lines:%d, secs:%llu, buf entries:%u\n",
                        geo->all_luns, pblk->l_mg.nr_lines,
-                       (unsigned long long)pblk->rl.nr_secs,
+                       (unsigned long long)pblk->capacity,
                        pblk->rwb.nr_entries);
 
        wake_up_process(pblk->writer_ts);
index 7fbc99b..5408e32 100644 (file)
@@ -162,6 +162,7 @@ int pblk_map_erase_rq(struct pblk *pblk, struct nvm_rq *rqd,
 
                        *erase_ppa = ppa_list[i];
                        erase_ppa->a.blk = e_line->id;
+                       erase_ppa->a.reserved = 0;
 
                        spin_unlock(&e_line->lock);
 
index 03c241b..5abb170 100644 (file)
@@ -642,7 +642,7 @@ try:
  * be directed to disk.
  */
 int pblk_rb_copy_to_bio(struct pblk_rb *rb, struct bio *bio, sector_t lba,
-                       struct ppa_addr ppa, int bio_iter, bool advanced_bio)
+                       struct ppa_addr ppa)
 {
        struct pblk *pblk = container_of(rb, struct pblk, rwb);
        struct pblk_rb_entry *entry;
@@ -673,15 +673,6 @@ int pblk_rb_copy_to_bio(struct pblk_rb *rb, struct bio *bio, sector_t lba,
                ret = 0;
                goto out;
        }
-
-       /* Only advance the bio if it hasn't been advanced already. If advanced,
-        * this bio is at least a partial bio (i.e., it has partially been
-        * filled with data from the cache). If part of the data resides on the
-        * media, we will read later on
-        */
-       if (unlikely(!advanced_bio))
-               bio_advance(bio, bio_iter * PBLK_EXPOSED_PAGE_SIZE);
-
        data = bio_data(bio);
        memcpy(data, entry->data, rb->seg_size);
 
@@ -799,8 +790,8 @@ int pblk_rb_tear_down_check(struct pblk_rb *rb)
        }
 
 out:
-       spin_unlock(&rb->w_lock);
        spin_unlock_irq(&rb->s_lock);
+       spin_unlock(&rb->w_lock);
 
        return ret;
 }
index 0b7d5fb..d98ea39 100644 (file)
@@ -26,8 +26,7 @@
  * issued.
  */
 static int pblk_read_from_cache(struct pblk *pblk, struct bio *bio,
-                               sector_t lba, struct ppa_addr ppa,
-                               int bio_iter, bool advanced_bio)
+                               sector_t lba, struct ppa_addr ppa)
 {
 #ifdef CONFIG_NVM_PBLK_DEBUG
        /* Callers must ensure that the ppa points to a cache address */
@@ -35,73 +34,75 @@ static int pblk_read_from_cache(struct pblk *pblk, struct bio *bio,
        BUG_ON(!pblk_addr_in_cache(ppa));
 #endif
 
-       return pblk_rb_copy_to_bio(&pblk->rwb, bio, lba, ppa,
-                                               bio_iter, advanced_bio);
+       return pblk_rb_copy_to_bio(&pblk->rwb, bio, lba, ppa);
 }
 
-static void pblk_read_ppalist_rq(struct pblk *pblk, struct nvm_rq *rqd,
+static int pblk_read_ppalist_rq(struct pblk *pblk, struct nvm_rq *rqd,
                                 struct bio *bio, sector_t blba,
-                                unsigned long *read_bitmap)
+                                bool *from_cache)
 {
        void *meta_list = rqd->meta_list;
-       struct ppa_addr ppas[NVM_MAX_VLBA];
-       int nr_secs = rqd->nr_ppas;
-       bool advanced_bio = false;
-       int i, j = 0;
+       int nr_secs, i;
 
-       pblk_lookup_l2p_seq(pblk, ppas, blba, nr_secs);
+retry:
+       nr_secs = pblk_lookup_l2p_seq(pblk, rqd->ppa_list, blba, rqd->nr_ppas,
+                                       from_cache);
+
+       if (!*from_cache)
+               goto end;
 
        for (i = 0; i < nr_secs; i++) {
-               struct ppa_addr p = ppas[i];
                struct pblk_sec_meta *meta = pblk_get_meta(pblk, meta_list, i);
                sector_t lba = blba + i;
 
-retry:
-               if (pblk_ppa_empty(p)) {
+               if (pblk_ppa_empty(rqd->ppa_list[i])) {
                        __le64 addr_empty = cpu_to_le64(ADDR_EMPTY);
 
-                       WARN_ON(test_and_set_bit(i, read_bitmap));
                        meta->lba = addr_empty;
-
-                       if (unlikely(!advanced_bio)) {
-                               bio_advance(bio, (i) * PBLK_EXPOSED_PAGE_SIZE);
-                               advanced_bio = true;
+               } else if (pblk_addr_in_cache(rqd->ppa_list[i])) {
+                       /*
+                        * Try to read from write buffer. The address is later
+                        * checked on the write buffer to prevent retrieving
+                        * overwritten data.
+                        */
+                       if (!pblk_read_from_cache(pblk, bio, lba,
+                                                       rqd->ppa_list[i])) {
+                               if (i == 0) {
+                                       /*
+                                        * We didn't call with bio_advance()
+                                        * yet, so we can just retry.
+                                        */
+                                       goto retry;
+                               } else {
+                                       /*
+                                        * We already call bio_advance()
+                                        * so we cannot retry and we need
+                                        * to quit that function in order
+                                        * to allow caller to handle the bio
+                                        * splitting in the current sector
+                                        * position.
+                                        */
+                                       nr_secs = i;
+                                       goto end;
+                               }
                        }
-
-                       goto next;
-               }
-
-               /* Try to read from write buffer. The address is later checked
-                * on the write buffer to prevent retrieving overwritten data.
-                */
-               if (pblk_addr_in_cache(p)) {
-                       if (!pblk_read_from_cache(pblk, bio, lba, p, i,
-                                                               advanced_bio)) {
-                               pblk_lookup_l2p_seq(pblk, &p, lba, 1);
-                               goto retry;
-                       }
-                       WARN_ON(test_and_set_bit(i, read_bitmap));
                        meta->lba = cpu_to_le64(lba);
-                       advanced_bio = true;
 #ifdef CONFIG_NVM_PBLK_DEBUG
                        atomic_long_inc(&pblk->cache_reads);
 #endif
-               } else {
-                       /* Read from media non-cached sectors */
-                       rqd->ppa_list[j++] = p;
                }
-
-next:
-               if (advanced_bio)
-                       bio_advance(bio, PBLK_EXPOSED_PAGE_SIZE);
+               bio_advance(bio, PBLK_EXPOSED_PAGE_SIZE);
        }
 
+end:
        if (pblk_io_aligned(pblk, nr_secs))
                rqd->is_seq = 1;
 
 #ifdef CONFIG_NVM_PBLK_DEBUG
        atomic_long_add(nr_secs, &pblk->inflight_reads);
 #endif
+
+       return nr_secs;
 }
 
 
@@ -175,12 +176,12 @@ static void pblk_read_check_rand(struct pblk *pblk, struct nvm_rq *rqd,
        WARN_ONCE(j != rqd->nr_ppas, "pblk: corrupted random request\n");
 }
 
-static void pblk_end_user_read(struct bio *bio)
+static void pblk_end_user_read(struct bio *bio, int error)
 {
-#ifdef CONFIG_NVM_PBLK_DEBUG
-       WARN_ONCE(bio->bi_status, "pblk: corrupted read bio\n");
-#endif
-       bio_endio(bio);
+       if (error && error != NVM_RSP_WARN_HIGHECC)
+               bio_io_error(bio);
+       else
+               bio_endio(bio);
 }
 
 static void __pblk_end_io_read(struct pblk *pblk, struct nvm_rq *rqd,
@@ -197,9 +198,7 @@ static void __pblk_end_io_read(struct pblk *pblk, struct nvm_rq *rqd,
                pblk_log_read_err(pblk, rqd);
 
        pblk_read_check_seq(pblk, rqd, r_ctx->lba);
-
-       if (int_bio)
-               bio_put(int_bio);
+       bio_put(int_bio);
 
        if (put_line)
                pblk_rq_to_line_put(pblk, rqd);
@@ -219,188 +218,17 @@ static void pblk_end_io_read(struct nvm_rq *rqd)
        struct pblk_g_ctx *r_ctx = nvm_rq_to_pdu(rqd);
        struct bio *bio = (struct bio *)r_ctx->private;
 
-       pblk_end_user_read(bio);
+       pblk_end_user_read(bio, rqd->error);
        __pblk_end_io_read(pblk, rqd, true);
 }
 
-static void pblk_end_partial_read(struct nvm_rq *rqd)
-{
-       struct pblk *pblk = rqd->private;
-       struct pblk_g_ctx *r_ctx = nvm_rq_to_pdu(rqd);
-       struct pblk_pr_ctx *pr_ctx = r_ctx->private;
-       struct pblk_sec_meta *meta;
-       struct bio *new_bio = rqd->bio;
-       struct bio *bio = pr_ctx->orig_bio;
-       void *meta_list = rqd->meta_list;
-       unsigned long *read_bitmap = pr_ctx->bitmap;
-       struct bvec_iter orig_iter = BVEC_ITER_ALL_INIT;
-       struct bvec_iter new_iter = BVEC_ITER_ALL_INIT;
-       int nr_secs = pr_ctx->orig_nr_secs;
-       int nr_holes = nr_secs - bitmap_weight(read_bitmap, nr_secs);
-       void *src_p, *dst_p;
-       int bit, i;
-
-       if (unlikely(nr_holes == 1)) {
-               struct ppa_addr ppa;
-
-               ppa = rqd->ppa_addr;
-               rqd->ppa_list = pr_ctx->ppa_ptr;
-               rqd->dma_ppa_list = pr_ctx->dma_ppa_list;
-               rqd->ppa_list[0] = ppa;
-       }
-
-       for (i = 0; i < nr_secs; i++) {
-               meta = pblk_get_meta(pblk, meta_list, i);
-               pr_ctx->lba_list_media[i] = le64_to_cpu(meta->lba);
-               meta->lba = cpu_to_le64(pr_ctx->lba_list_mem[i]);
-       }
-
-       /* Fill the holes in the original bio */
-       i = 0;
-       for (bit = 0; bit < nr_secs; bit++) {
-               if (!test_bit(bit, read_bitmap)) {
-                       struct bio_vec dst_bv, src_bv;
-                       struct pblk_line *line;
-
-                       line = pblk_ppa_to_line(pblk, rqd->ppa_list[i]);
-                       kref_put(&line->ref, pblk_line_put);
-
-                       meta = pblk_get_meta(pblk, meta_list, bit);
-                       meta->lba = cpu_to_le64(pr_ctx->lba_list_media[i]);
-
-                       dst_bv = bio_iter_iovec(bio, orig_iter);
-                       src_bv = bio_iter_iovec(new_bio, new_iter);
-
-                       src_p = kmap_atomic(src_bv.bv_page);
-                       dst_p = kmap_atomic(dst_bv.bv_page);
-
-                       memcpy(dst_p + dst_bv.bv_offset,
-                               src_p + src_bv.bv_offset,
-                               PBLK_EXPOSED_PAGE_SIZE);
-
-                       kunmap_atomic(src_p);
-                       kunmap_atomic(dst_p);
-
-                       flush_dcache_page(dst_bv.bv_page);
-                       mempool_free(src_bv.bv_page, &pblk->page_bio_pool);
-
-                       bio_advance_iter(new_bio, &new_iter,
-                                       PBLK_EXPOSED_PAGE_SIZE);
-                       i++;
-               }
-               bio_advance_iter(bio, &orig_iter, PBLK_EXPOSED_PAGE_SIZE);
-       }
-
-       bio_put(new_bio);
-       kfree(pr_ctx);
-
-       /* restore original request */
-       rqd->bio = NULL;
-       rqd->nr_ppas = nr_secs;
-
-       bio_endio(bio);
-       __pblk_end_io_read(pblk, rqd, false);
-}
-
-static int pblk_setup_partial_read(struct pblk *pblk, struct nvm_rq *rqd,
-                           unsigned int bio_init_idx,
-                           unsigned long *read_bitmap,
-                           int nr_holes)
-{
-       void *meta_list = rqd->meta_list;
-       struct pblk_g_ctx *r_ctx = nvm_rq_to_pdu(rqd);
-       struct pblk_pr_ctx *pr_ctx;
-       struct bio *new_bio, *bio = r_ctx->private;
-       int nr_secs = rqd->nr_ppas;
-       int i;
-
-       new_bio = bio_alloc(GFP_KERNEL, nr_holes);
-
-       if (pblk_bio_add_pages(pblk, new_bio, GFP_KERNEL, nr_holes))
-               goto fail_bio_put;
-
-       if (nr_holes != new_bio->bi_vcnt) {
-               WARN_ONCE(1, "pblk: malformed bio\n");
-               goto fail_free_pages;
-       }
-
-       pr_ctx = kzalloc(sizeof(struct pblk_pr_ctx), GFP_KERNEL);
-       if (!pr_ctx)
-               goto fail_free_pages;
-
-       for (i = 0; i < nr_secs; i++) {
-               struct pblk_sec_meta *meta = pblk_get_meta(pblk, meta_list, i);
-
-               pr_ctx->lba_list_mem[i] = le64_to_cpu(meta->lba);
-       }
-
-       new_bio->bi_iter.bi_sector = 0; /* internal bio */
-       bio_set_op_attrs(new_bio, REQ_OP_READ, 0);
-
-       rqd->bio = new_bio;
-       rqd->nr_ppas = nr_holes;
-
-       pr_ctx->orig_bio = bio;
-       bitmap_copy(pr_ctx->bitmap, read_bitmap, NVM_MAX_VLBA);
-       pr_ctx->bio_init_idx = bio_init_idx;
-       pr_ctx->orig_nr_secs = nr_secs;
-       r_ctx->private = pr_ctx;
-
-       if (unlikely(nr_holes == 1)) {
-               pr_ctx->ppa_ptr = rqd->ppa_list;
-               pr_ctx->dma_ppa_list = rqd->dma_ppa_list;
-               rqd->ppa_addr = rqd->ppa_list[0];
-       }
-       return 0;
-
-fail_free_pages:
-       pblk_bio_free_pages(pblk, new_bio, 0, new_bio->bi_vcnt);
-fail_bio_put:
-       bio_put(new_bio);
-
-       return -ENOMEM;
-}
-
-static int pblk_partial_read_bio(struct pblk *pblk, struct nvm_rq *rqd,
-                                unsigned int bio_init_idx,
-                                unsigned long *read_bitmap, int nr_secs)
-{
-       int nr_holes;
-       int ret;
-
-       nr_holes = nr_secs - bitmap_weight(read_bitmap, nr_secs);
-
-       if (pblk_setup_partial_read(pblk, rqd, bio_init_idx, read_bitmap,
-                                   nr_holes))
-               return NVM_IO_ERR;
-
-       rqd->end_io = pblk_end_partial_read;
-
-       ret = pblk_submit_io(pblk, rqd);
-       if (ret) {
-               bio_put(rqd->bio);
-               pblk_err(pblk, "partial read IO submission failed\n");
-               goto err;
-       }
-
-       return NVM_IO_OK;
-
-err:
-       pblk_err(pblk, "failed to perform partial read\n");
-
-       /* Free allocated pages in new bio */
-       pblk_bio_free_pages(pblk, rqd->bio, 0, rqd->bio->bi_vcnt);
-       __pblk_end_io_read(pblk, rqd, false);
-       return NVM_IO_ERR;
-}
-
 static void pblk_read_rq(struct pblk *pblk, struct nvm_rq *rqd, struct bio *bio,
-                        sector_t lba, unsigned long *read_bitmap)
+                        sector_t lba, bool *from_cache)
 {
        struct pblk_sec_meta *meta = pblk_get_meta(pblk, rqd->meta_list, 0);
        struct ppa_addr ppa;
 
-       pblk_lookup_l2p_seq(pblk, &ppa, lba, 1);
+       pblk_lookup_l2p_seq(pblk, &ppa, lba, 1, from_cache);
 
 #ifdef CONFIG_NVM_PBLK_DEBUG
        atomic_long_inc(&pblk->inflight_reads);
@@ -410,7 +238,6 @@ retry:
        if (pblk_ppa_empty(ppa)) {
                __le64 addr_empty = cpu_to_le64(ADDR_EMPTY);
 
-               WARN_ON(test_and_set_bit(0, read_bitmap));
                meta->lba = addr_empty;
                return;
        }
@@ -419,12 +246,11 @@ retry:
         * write buffer to prevent retrieving overwritten data.
         */
        if (pblk_addr_in_cache(ppa)) {
-               if (!pblk_read_from_cache(pblk, bio, lba, ppa, 0, 1)) {
-                       pblk_lookup_l2p_seq(pblk, &ppa, lba, 1);
+               if (!pblk_read_from_cache(pblk, bio, lba, ppa)) {
+                       pblk_lookup_l2p_seq(pblk, &ppa, lba, 1, from_cache);
                        goto retry;
                }
 
-               WARN_ON(test_and_set_bit(0, read_bitmap));
                meta->lba = cpu_to_le64(lba);
 
 #ifdef CONFIG_NVM_PBLK_DEBUG
@@ -435,95 +261,92 @@ retry:
        }
 }
 
-int pblk_submit_read(struct pblk *pblk, struct bio *bio)
+void pblk_submit_read(struct pblk *pblk, struct bio *bio)
 {
        struct nvm_tgt_dev *dev = pblk->dev;
        struct request_queue *q = dev->q;
        sector_t blba = pblk_get_lba(bio);
        unsigned int nr_secs = pblk_get_secs(bio);
+       bool from_cache;
        struct pblk_g_ctx *r_ctx;
        struct nvm_rq *rqd;
-       unsigned int bio_init_idx;
-       DECLARE_BITMAP(read_bitmap, NVM_MAX_VLBA);
-       int ret = NVM_IO_ERR;
+       struct bio *int_bio, *split_bio;
 
        generic_start_io_acct(q, REQ_OP_READ, bio_sectors(bio),
                              &pblk->disk->part0);
 
-       bitmap_zero(read_bitmap, nr_secs);
-
        rqd = pblk_alloc_rqd(pblk, PBLK_READ);
 
        rqd->opcode = NVM_OP_PREAD;
        rqd->nr_ppas = nr_secs;
-       rqd->bio = NULL; /* cloned bio if needed */
        rqd->private = pblk;
        rqd->end_io = pblk_end_io_read;
 
        r_ctx = nvm_rq_to_pdu(rqd);
        r_ctx->start_time = jiffies;
        r_ctx->lba = blba;
-       r_ctx->private = bio; /* original bio */
 
-       /* Save the index for this bio's start. This is needed in case
-        * we need to fill a partial read.
-        */
-       bio_init_idx = pblk_get_bi_idx(bio);
+       if (pblk_alloc_rqd_meta(pblk, rqd)) {
+               bio_io_error(bio);
+               pblk_free_rqd(pblk, rqd, PBLK_READ);
+               return;
+       }
 
-       if (pblk_alloc_rqd_meta(pblk, rqd))
-               goto fail_rqd_free;
+       /* Clone read bio to deal internally with:
+        * -read errors when reading from drive
+        * -bio_advance() calls during cache reads
+        */
+       int_bio = bio_clone_fast(bio, GFP_KERNEL, &pblk_bio_set);
 
        if (nr_secs > 1)
-               pblk_read_ppalist_rq(pblk, rqd, bio, blba, read_bitmap);
+               nr_secs = pblk_read_ppalist_rq(pblk, rqd, int_bio, blba,
+                                               &from_cache);
        else
-               pblk_read_rq(pblk, rqd, bio, blba, read_bitmap);
+               pblk_read_rq(pblk, rqd, int_bio, blba, &from_cache);
 
-       if (bitmap_full(read_bitmap, nr_secs)) {
+split_retry:
+       r_ctx->private = bio; /* original bio */
+       rqd->bio = int_bio; /* internal bio */
+
+       if (from_cache && nr_secs == rqd->nr_ppas) {
+               /* All data was read from cache, we can complete the IO. */
+               pblk_end_user_read(bio, 0);
                atomic_inc(&pblk->inflight_io);
                __pblk_end_io_read(pblk, rqd, false);
-               return NVM_IO_DONE;
-       }
-
-       /* All sectors are to be read from the device */
-       if (bitmap_empty(read_bitmap, rqd->nr_ppas)) {
-               struct bio *int_bio = NULL;
+       } else if (nr_secs != rqd->nr_ppas) {
+               /* The read bio request could be partially filled by the write
+                * buffer, but there are some holes that need to be read from
+                * the drive. In order to handle this, we will use block layer
+                * mechanism to split this request in to smaller ones and make
+                * a chain of it.
+                */
+               split_bio = bio_split(bio, nr_secs * NR_PHY_IN_LOG, GFP_KERNEL,
+                                       &pblk_bio_set);
+               bio_chain(split_bio, bio);
+               generic_make_request(bio);
+
+               /* New bio contains first N sectors of the previous one, so
+                * we can continue to use existing rqd, but we need to shrink
+                * the number of PPAs in it. New bio is also guaranteed that
+                * it contains only either data from cache or from drive, newer
+                * mix of them.
+                */
+               bio = split_bio;
+               rqd->nr_ppas = nr_secs;
+               if (rqd->nr_ppas == 1)
+                       rqd->ppa_addr = rqd->ppa_list[0];
 
-               /* Clone read bio to deal with read errors internally */
+               /* Recreate int_bio - existing might have some needed internal
+                * fields modified already.
+                */
+               bio_put(int_bio);
                int_bio = bio_clone_fast(bio, GFP_KERNEL, &pblk_bio_set);
-               if (!int_bio) {
-                       pblk_err(pblk, "could not clone read bio\n");
-                       goto fail_end_io;
-               }
-
-               rqd->bio = int_bio;
-
-               if (pblk_submit_io(pblk, rqd)) {
-                       pblk_err(pblk, "read IO submission failed\n");
-                       ret = NVM_IO_ERR;
-                       goto fail_end_io;
-               }
-
-               return NVM_IO_OK;
+               goto split_retry;
+       } else if (pblk_submit_io(pblk, rqd)) {
+               /* Submitting IO to drive failed, let's report an error */
+               rqd->error = -ENODEV;
+               pblk_end_io_read(rqd);
        }
-
-       /* The read bio request could be partially filled by the write buffer,
-        * but there are some holes that need to be read from the drive.
-        */
-       ret = pblk_partial_read_bio(pblk, rqd, bio_init_idx, read_bitmap,
-                                   nr_secs);
-       if (ret)
-               goto fail_meta_free;
-
-       return NVM_IO_OK;
-
-fail_meta_free:
-       nvm_dev_dma_free(dev->parent, rqd->meta_list, rqd->dma_meta_list);
-fail_rqd_free:
-       pblk_free_rqd(pblk, rqd, PBLK_READ);
-       return ret;
-fail_end_io:
-       __pblk_end_io_read(pblk, rqd, false);
-       return ret;
 }
 
 static int read_ppalist_rq_gc(struct pblk *pblk, struct nvm_rq *rqd,
@@ -568,7 +391,7 @@ static int read_rq_gc(struct pblk *pblk, struct nvm_rq *rqd,
                goto out;
 
        /* logic error: lba out-of-bounds */
-       if (lba >= pblk->rl.nr_secs) {
+       if (lba >= pblk->capacity) {
                WARN(1, "pblk: read lba out of bounds\n");
                goto out;
        }
@@ -642,7 +465,6 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
 
        if (pblk_submit_io_sync(pblk, &rqd)) {
                ret = -EIO;
-               pblk_err(pblk, "GC read request failed\n");
                goto err_free_bio;
        }
 
index d86f580..e6dda04 100644 (file)
@@ -93,10 +93,24 @@ static int pblk_recov_l2p_from_emeta(struct pblk *pblk, struct pblk_line *line)
 static void pblk_update_line_wp(struct pblk *pblk, struct pblk_line *line,
                                u64 written_secs)
 {
+       struct pblk_line_mgmt *l_mg = &pblk->l_mg;
        int i;
 
        for (i = 0; i < written_secs; i += pblk->min_write_pgs)
-               pblk_alloc_page(pblk, line, pblk->min_write_pgs);
+               __pblk_alloc_page(pblk, line, pblk->min_write_pgs);
+
+       spin_lock(&l_mg->free_lock);
+       if (written_secs > line->left_msecs) {
+               /*
+                * We have all data sectors written
+                * and some emeta sectors written too.
+                */
+               line->left_msecs = 0;
+       } else {
+               /* We have only some data sectors written. */
+               line->left_msecs -= written_secs;
+       }
+       spin_unlock(&l_mg->free_lock);
 }
 
 static u64 pblk_sec_in_open_line(struct pblk *pblk, struct pblk_line *line)
@@ -165,6 +179,7 @@ static int pblk_recov_pad_line(struct pblk *pblk, struct pblk_line *line,
        struct pblk_pad_rq *pad_rq;
        struct nvm_rq *rqd;
        struct bio *bio;
+       struct ppa_addr *ppa_list;
        void *data;
        __le64 *lba_list = emeta_to_lbas(pblk, line->emeta->buf);
        u64 w_ptr = line->cur_sec;
@@ -194,7 +209,7 @@ next_pad_rq:
        rq_ppas = pblk_calc_secs(pblk, left_ppas, 0, false);
        if (rq_ppas < pblk->min_write_pgs) {
                pblk_err(pblk, "corrupted pad line %d\n", line->id);
-               goto fail_free_pad;
+               goto fail_complete;
        }
 
        rq_len = rq_ppas * geo->csecs;
@@ -203,7 +218,7 @@ next_pad_rq:
                                                PBLK_VMALLOC_META, GFP_KERNEL);
        if (IS_ERR(bio)) {
                ret = PTR_ERR(bio);
-               goto fail_free_pad;
+               goto fail_complete;
        }
 
        bio->bi_iter.bi_sector = 0; /* internal bio */
@@ -212,8 +227,11 @@ next_pad_rq:
        rqd = pblk_alloc_rqd(pblk, PBLK_WRITE_INT);
 
        ret = pblk_alloc_rqd_meta(pblk, rqd);
-       if (ret)
-               goto fail_free_rqd;
+       if (ret) {
+               pblk_free_rqd(pblk, rqd, PBLK_WRITE_INT);
+               bio_put(bio);
+               goto fail_complete;
+       }
 
        rqd->bio = bio;
        rqd->opcode = NVM_OP_PWRITE;
@@ -222,6 +240,7 @@ next_pad_rq:
        rqd->end_io = pblk_end_io_recov;
        rqd->private = pad_rq;
 
+       ppa_list = nvm_rq_to_ppa_list(rqd);
        meta_list = rqd->meta_list;
 
        for (i = 0; i < rqd->nr_ppas; ) {
@@ -249,18 +268,21 @@ next_pad_rq:
                        lba_list[w_ptr] = addr_empty;
                        meta = pblk_get_meta(pblk, meta_list, i);
                        meta->lba = addr_empty;
-                       rqd->ppa_list[i] = dev_ppa;
+                       ppa_list[i] = dev_ppa;
                }
        }
 
        kref_get(&pad_rq->ref);
-       pblk_down_chunk(pblk, rqd->ppa_list[0]);
+       pblk_down_chunk(pblk, ppa_list[0]);
 
        ret = pblk_submit_io(pblk, rqd);
        if (ret) {
                pblk_err(pblk, "I/O submission failed: %d\n", ret);
-               pblk_up_chunk(pblk, rqd->ppa_list[0]);
-               goto fail_free_rqd;
+               pblk_up_chunk(pblk, ppa_list[0]);
+               kref_put(&pad_rq->ref, pblk_recov_complete);
+               pblk_free_rqd(pblk, rqd, PBLK_WRITE_INT);
+               bio_put(bio);
+               goto fail_complete;
        }
 
        left_line_ppas -= rq_ppas;
@@ -268,13 +290,9 @@ next_pad_rq:
        if (left_ppas && left_line_ppas)
                goto next_pad_rq;
 
+fail_complete:
        kref_put(&pad_rq->ref, pblk_recov_complete);
-
-       if (!wait_for_completion_io_timeout(&pad_rq->wait,
-                               msecs_to_jiffies(PBLK_COMMAND_TIMEOUT_MS))) {
-               pblk_err(pblk, "pad write timed out\n");
-               ret = -ETIME;
-       }
+       wait_for_completion(&pad_rq->wait);
 
        if (!pblk_line_is_full(line))
                pblk_err(pblk, "corrupted padded line: %d\n", line->id);
@@ -283,14 +301,6 @@ next_pad_rq:
 free_rq:
        kfree(pad_rq);
        return ret;
-
-fail_free_rqd:
-       pblk_free_rqd(pblk, rqd, PBLK_WRITE_INT);
-       bio_put(bio);
-fail_free_pad:
-       kfree(pad_rq);
-       vfree(data);
-       return ret;
 }
 
 static int pblk_pad_distance(struct pblk *pblk, struct pblk_line *line)
@@ -412,6 +422,7 @@ retry_rq:
        rqd->ppa_list = ppa_list;
        rqd->dma_ppa_list = dma_ppa_list;
        rqd->dma_meta_list = dma_meta_list;
+       ppa_list = nvm_rq_to_ppa_list(rqd);
 
        if (pblk_io_aligned(pblk, rq_ppas))
                rqd->is_seq = 1;
@@ -430,7 +441,7 @@ retry_rq:
                }
 
                for (j = 0; j < pblk->min_write_pgs; j++, i++)
-                       rqd->ppa_list[i] =
+                       ppa_list[i] =
                                addr_to_gen_ppa(pblk, paddr + j, line->id);
        }
 
@@ -444,7 +455,7 @@ retry_rq:
        atomic_dec(&pblk->inflight_io);
 
        /* If a read fails, do a best effort by padding the line and retrying */
-       if (rqd->error) {
+       if (rqd->error && rqd->error != NVM_RSP_WARN_HIGHECC) {
                int pad_distance, ret;
 
                if (padded) {
@@ -474,11 +485,11 @@ retry_rq:
 
                lba_list[paddr++] = cpu_to_le64(lba);
 
-               if (lba == ADDR_EMPTY || lba > pblk->rl.nr_secs)
+               if (lba == ADDR_EMPTY || lba >= pblk->capacity)
                        continue;
 
                line->nr_valid_lbas++;
-               pblk_update_map(pblk, lba, rqd->ppa_list[i]);
+               pblk_update_map(pblk, lba, ppa_list[i]);
        }
 
        left_ppas -= rq_ppas;
@@ -647,10 +658,12 @@ static int pblk_line_was_written(struct pblk_line *line,
        bppa = pblk->luns[smeta_blk].bppa;
        chunk = &line->chks[pblk_ppa_to_pos(geo, bppa)];
 
-       if (chunk->state & NVM_CHK_ST_FREE)
-               return 0;
+       if (chunk->state & NVM_CHK_ST_CLOSED ||
+           (chunk->state & NVM_CHK_ST_OPEN
+            && chunk->wp >= lm->smeta_sec))
+               return 1;
 
-       return 1;
+       return 0;
 }
 
 static bool pblk_line_is_open(struct pblk *pblk, struct pblk_line *line)
@@ -844,6 +857,7 @@ next:
                spin_unlock(&l_mg->free_lock);
        } else {
                spin_lock(&l_mg->free_lock);
+               l_mg->data_line = data_line;
                /* Allocate next line for preparation */
                l_mg->data_next = pblk_line_get(pblk);
                if (l_mg->data_next) {
index 6593dea..4e63f9b 100644 (file)
@@ -228,6 +228,7 @@ static void pblk_submit_rec(struct work_struct *work)
        mempool_free(recovery, &pblk->rec_pool);
 
        atomic_dec(&pblk->inflight_io);
+       pblk_write_kick(pblk);
 }
 
 
index ac3ab77..a678553 100644 (file)
@@ -43,8 +43,6 @@
 
 #define PBLK_CACHE_NAME_LEN (DISK_NAME_LEN + 16)
 
-#define PBLK_COMMAND_TIMEOUT_MS 30000
-
 /* Max 512 LUNs per device */
 #define PBLK_MAX_LUNS_BITMAP (4)
 
@@ -123,18 +121,6 @@ struct pblk_g_ctx {
        u64 lba;
 };
 
-/* partial read context */
-struct pblk_pr_ctx {
-       struct bio *orig_bio;
-       DECLARE_BITMAP(bitmap, NVM_MAX_VLBA);
-       unsigned int orig_nr_secs;
-       unsigned int bio_init_idx;
-       void *ppa_ptr;
-       dma_addr_t dma_ppa_list;
-       u64 lba_list_mem[NVM_MAX_VLBA];
-       u64 lba_list_media[NVM_MAX_VLBA];
-};
-
 /* Pad context */
 struct pblk_pad_rq {
        struct pblk *pblk;
@@ -305,7 +291,6 @@ struct pblk_rl {
 
        struct timer_list u_timer;
 
-       unsigned long long nr_secs;
        unsigned long total_blocks;
 
        atomic_t free_blocks;           /* Total number of free blocks (+ OP) */
@@ -440,6 +425,7 @@ struct pblk_smeta {
 
 struct pblk_w_err_gc {
        int has_write_err;
+       int has_gc_err;
        __le64 *lba_list;
 };
 
@@ -465,7 +451,6 @@ struct pblk_line {
        int meta_line;                  /* Metadata line id */
        int meta_distance;              /* Distance between data and metadata */
 
-       u64 smeta_ssec;                 /* Sector where smeta starts */
        u64 emeta_ssec;                 /* Sector where emeta starts */
 
        unsigned int sec_in_line;       /* Number of usable secs in line */
@@ -762,7 +747,7 @@ unsigned int pblk_rb_read_to_bio(struct pblk_rb *rb, struct nvm_rq *rqd,
                                 unsigned int pos, unsigned int nr_entries,
                                 unsigned int count);
 int pblk_rb_copy_to_bio(struct pblk_rb *rb, struct bio *bio, sector_t lba,
-                       struct ppa_addr ppa, int bio_iter, bool advanced_bio);
+                       struct ppa_addr ppa);
 unsigned int pblk_rb_read_commit(struct pblk_rb *rb, unsigned int entries);
 
 unsigned int pblk_rb_sync_init(struct pblk_rb *rb, unsigned long *flags);
@@ -862,15 +847,15 @@ int pblk_update_map_gc(struct pblk *pblk, sector_t lba, struct ppa_addr ppa,
                       struct pblk_line *gc_line, u64 paddr);
 void pblk_lookup_l2p_rand(struct pblk *pblk, struct ppa_addr *ppas,
                          u64 *lba_list, int nr_secs);
-void pblk_lookup_l2p_seq(struct pblk *pblk, struct ppa_addr *ppas,
-                        sector_t blba, int nr_secs);
+int pblk_lookup_l2p_seq(struct pblk *pblk, struct ppa_addr *ppas,
+                        sector_t blba, int nr_secs, bool *from_cache);
 void *pblk_get_meta_for_writes(struct pblk *pblk, struct nvm_rq *rqd);
 void pblk_get_packed_meta(struct pblk *pblk, struct nvm_rq *rqd);
 
 /*
  * pblk user I/O write path
  */
-int pblk_write_to_cache(struct pblk *pblk, struct bio *bio,
+void pblk_write_to_cache(struct pblk *pblk, struct bio *bio,
                        unsigned long flags);
 int pblk_write_gc_to_cache(struct pblk *pblk, struct pblk_gc_rq *gc_rq);
 
@@ -896,7 +881,7 @@ void pblk_write_kick(struct pblk *pblk);
  * pblk read path
  */
 extern struct bio_set pblk_bio_set;
-int pblk_submit_read(struct pblk *pblk, struct bio *bio);
+void pblk_submit_read(struct pblk *pblk, struct bio *bio);
 int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq);
 /*
  * pblk recovery
@@ -921,6 +906,7 @@ void pblk_gc_free_full_lines(struct pblk *pblk);
 void pblk_gc_sysfs_state_show(struct pblk *pblk, int *gc_enabled,
                              int *gc_active);
 int pblk_gc_sysfs_force(struct pblk *pblk, int force);
+void pblk_put_line_back(struct pblk *pblk, struct pblk_line *line);
 
 /*
  * pblk rate limiter
index 2281178..00d5219 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
index 2557f19..db269a3 100644 (file)
@@ -436,6 +436,15 @@ config DM_DELAY
 
        If unsure, say N.
 
+config DM_DUST
+       tristate "Bad sector simulation target"
+       depends on BLK_DEV_DM
+       ---help---
+       A target that simulates bad sector behavior.
+       Useful for testing.
+
+       If unsure, say N.
+
 config DM_INIT
        bool "DM \"dm-mod.create=\" parameter support"
        depends on BLK_DEV_DM=y
index a52b703..be7a6eb 100644 (file)
@@ -48,6 +48,7 @@ obj-$(CONFIG_DM_BUFIO)                += dm-bufio.o
 obj-$(CONFIG_DM_BIO_PRISON)    += dm-bio-prison.o
 obj-$(CONFIG_DM_CRYPT)         += dm-crypt.o
 obj-$(CONFIG_DM_DELAY)         += dm-delay.o
+obj-$(CONFIG_DM_DUST)          += dm-dust.o
 obj-$(CONFIG_DM_FLAKEY)                += dm-flakey.o
 obj-$(CONFIG_DM_MULTIPATH)     += dm-multipath.o dm-round-robin.o
 obj-$(CONFIG_DM_MULTIPATH_QL)  += dm-queue-length.o
index 6fc9383..151aa95 100644 (file)
@@ -1167,11 +1167,18 @@ static int __load_discards(struct dm_cache_metadata *cmd,
                if (r)
                        return r;
 
-               for (b = 0; b < from_dblock(cmd->discard_nr_blocks); b++) {
+               for (b = 0; ; b++) {
                        r = fn(context, cmd->discard_block_size, to_dblock(b),
                               dm_bitset_cursor_get_value(&c));
                        if (r)
                                break;
+
+                       if (b >= (from_dblock(cmd->discard_nr_blocks) - 1))
+                               break;
+
+                       r = dm_bitset_cursor_next(&c);
+                       if (r)
+                               break;
                }
 
                dm_bitset_cursor_end(&c);
index 7f6462f..1b16d34 100644 (file)
@@ -946,6 +946,7 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti)
 {
 #ifdef CONFIG_BLK_DEV_INTEGRITY
        struct blk_integrity *bi = blk_get_integrity(cc->dev->bdev->bd_disk);
+       struct mapped_device *md = dm_table_get_md(ti->table);
 
        /* From now we require underlying device with our integrity profile */
        if (!bi || strcasecmp(bi->profile->name, "DM-DIF-EXT-TAG")) {
@@ -965,7 +966,7 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti)
 
        if (crypt_integrity_aead(cc)) {
                cc->integrity_tag_size = cc->on_disk_tag_size - cc->integrity_iv_size;
-               DMINFO("Integrity AEAD, tag size %u, IV size %u.",
+               DMDEBUG("%s: Integrity AEAD, tag size %u, IV size %u.", dm_device_name(md),
                       cc->integrity_tag_size, cc->integrity_iv_size);
 
                if (crypto_aead_setauthsize(any_tfm_aead(cc), cc->integrity_tag_size)) {
@@ -973,7 +974,7 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti)
                        return -EINVAL;
                }
        } else if (cc->integrity_iv_size)
-               DMINFO("Additional per-sector space %u bytes for IV.",
+               DMDEBUG("%s: Additional per-sector space %u bytes for IV.", dm_device_name(md),
                       cc->integrity_iv_size);
 
        if ((cc->integrity_tag_size + cc->integrity_iv_size) != bi->tag_size) {
@@ -1031,11 +1032,11 @@ static u8 *org_iv_of_dmreq(struct crypt_config *cc,
        return iv_of_dmreq(cc, dmreq) + cc->iv_size;
 }
 
-static uint64_t *org_sector_of_dmreq(struct crypt_config *cc,
+static __le64 *org_sector_of_dmreq(struct crypt_config *cc,
                       struct dm_crypt_request *dmreq)
 {
        u8 *ptr = iv_of_dmreq(cc, dmreq) + cc->iv_size + cc->iv_size;
-       return (uint64_t*) ptr;
+       return (__le64 *) ptr;
 }
 
 static unsigned int *org_tag_of_dmreq(struct crypt_config *cc,
@@ -1071,7 +1072,7 @@ static int crypt_convert_block_aead(struct crypt_config *cc,
        struct bio_vec bv_out = bio_iter_iovec(ctx->bio_out, ctx->iter_out);
        struct dm_crypt_request *dmreq;
        u8 *iv, *org_iv, *tag_iv, *tag;
-       uint64_t *sector;
+       __le64 *sector;
        int r = 0;
 
        BUG_ON(cc->integrity_iv_size && cc->integrity_iv_size != cc->iv_size);
@@ -1143,9 +1144,11 @@ static int crypt_convert_block_aead(struct crypt_config *cc,
                r = crypto_aead_decrypt(req);
        }
 
-       if (r == -EBADMSG)
-               DMERR_LIMIT("INTEGRITY AEAD ERROR, sector %llu",
+       if (r == -EBADMSG) {
+               char b[BDEVNAME_SIZE];
+               DMERR_LIMIT("%s: INTEGRITY AEAD ERROR, sector %llu", bio_devname(ctx->bio_in, b),
                            (unsigned long long)le64_to_cpu(*sector));
+       }
 
        if (!r && cc->iv_gen_ops && cc->iv_gen_ops->post)
                r = cc->iv_gen_ops->post(cc, org_iv, dmreq);
@@ -1166,7 +1169,7 @@ static int crypt_convert_block_skcipher(struct crypt_config *cc,
        struct scatterlist *sg_in, *sg_out;
        struct dm_crypt_request *dmreq;
        u8 *iv, *org_iv, *tag_iv;
-       uint64_t *sector;
+       __le64 *sector;
        int r = 0;
 
        /* Reject unexpected unaligned bio. */
@@ -1788,7 +1791,8 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
                error = cc->iv_gen_ops->post(cc, org_iv_of_dmreq(cc, dmreq), dmreq);
 
        if (error == -EBADMSG) {
-               DMERR_LIMIT("INTEGRITY AEAD ERROR, sector %llu",
+               char b[BDEVNAME_SIZE];
+               DMERR_LIMIT("%s: INTEGRITY AEAD ERROR, sector %llu", bio_devname(ctx->bio_in, b),
                            (unsigned long long)le64_to_cpu(*org_sector_of_dmreq(cc, dmreq)));
                io->error = BLK_STS_PROTECTION;
        } else if (error < 0)
@@ -1887,7 +1891,7 @@ static int crypt_alloc_tfms_skcipher(struct crypt_config *cc, char *ciphermode)
         * algorithm implementation is used.  Help people debug performance
         * problems by logging the ->cra_driver_name.
         */
-       DMINFO("%s using implementation \"%s\"", ciphermode,
+       DMDEBUG_LIMIT("%s using implementation \"%s\"", ciphermode,
               crypto_skcipher_alg(any_tfm(cc))->base.cra_driver_name);
        return 0;
 }
@@ -1907,7 +1911,7 @@ static int crypt_alloc_tfms_aead(struct crypt_config *cc, char *ciphermode)
                return err;
        }
 
-       DMINFO("%s using implementation \"%s\"", ciphermode,
+       DMDEBUG_LIMIT("%s using implementation \"%s\"", ciphermode,
               crypto_aead_alg(any_tfm_aead(cc))->base.cra_driver_name);
        return 0;
 }
index fddffe2..f496213 100644 (file)
@@ -121,7 +121,8 @@ static void delay_dtr(struct dm_target *ti)
 {
        struct delay_c *dc = ti->private;
 
-       destroy_workqueue(dc->kdelayd_wq);
+       if (dc->kdelayd_wq)
+               destroy_workqueue(dc->kdelayd_wq);
 
        if (dc->read.dev)
                dm_put_device(ti, dc->read.dev);
diff --git a/drivers/md/dm-dust.c b/drivers/md/dm-dust.c
new file mode 100644 (file)
index 0000000..845f376
--- /dev/null
@@ -0,0 +1,515 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This is a test "dust" device, which fails reads on specified
+ * sectors, emulating the behavior of a hard disk drive sending
+ * a "Read Medium Error" sense.
+ *
+ */
+
+#include <linux/device-mapper.h>
+#include <linux/module.h>
+#include <linux/rbtree.h>
+
+#define DM_MSG_PREFIX "dust"
+
+struct badblock {
+       struct rb_node node;
+       sector_t bb;
+};
+
+struct dust_device {
+       struct dm_dev *dev;
+       struct rb_root badblocklist;
+       unsigned long long badblock_count;
+       spinlock_t dust_lock;
+       unsigned int blksz;
+       unsigned int sect_per_block;
+       sector_t start;
+       bool fail_read_on_bb:1;
+       bool quiet_mode:1;
+};
+
+static struct badblock *dust_rb_search(struct rb_root *root, sector_t blk)
+{
+       struct rb_node *node = root->rb_node;
+
+       while (node) {
+               struct badblock *bblk = rb_entry(node, struct badblock, node);
+
+               if (bblk->bb > blk)
+                       node = node->rb_left;
+               else if (bblk->bb < blk)
+                       node = node->rb_right;
+               else
+                       return bblk;
+       }
+
+       return NULL;
+}
+
+static bool dust_rb_insert(struct rb_root *root, struct badblock *new)
+{
+       struct badblock *bblk;
+       struct rb_node **link = &root->rb_node, *parent = NULL;
+       sector_t value = new->bb;
+
+       while (*link) {
+               parent = *link;
+               bblk = rb_entry(parent, struct badblock, node);
+
+               if (bblk->bb > value)
+                       link = &(*link)->rb_left;
+               else if (bblk->bb < value)
+                       link = &(*link)->rb_right;
+               else
+                       return false;
+       }
+
+       rb_link_node(&new->node, parent, link);
+       rb_insert_color(&new->node, root);
+
+       return true;
+}
+
+static int dust_remove_block(struct dust_device *dd, unsigned long long block)
+{
+       struct badblock *bblock;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dd->dust_lock, flags);
+       bblock = dust_rb_search(&dd->badblocklist, block * dd->sect_per_block);
+
+       if (bblock == NULL) {
+               if (!dd->quiet_mode) {
+                       DMERR("%s: block %llu not found in badblocklist",
+                             __func__, block);
+               }
+               spin_unlock_irqrestore(&dd->dust_lock, flags);
+               return -EINVAL;
+       }
+
+       rb_erase(&bblock->node, &dd->badblocklist);
+       dd->badblock_count--;
+       if (!dd->quiet_mode)
+               DMINFO("%s: badblock removed at block %llu", __func__, block);
+       kfree(bblock);
+       spin_unlock_irqrestore(&dd->dust_lock, flags);
+
+       return 0;
+}
+
+static int dust_add_block(struct dust_device *dd, unsigned long long block)
+{
+       struct badblock *bblock;
+       unsigned long flags;
+
+       bblock = kmalloc(sizeof(*bblock), GFP_KERNEL);
+       if (bblock == NULL) {
+               if (!dd->quiet_mode)
+                       DMERR("%s: badblock allocation failed", __func__);
+               return -ENOMEM;
+       }
+
+       spin_lock_irqsave(&dd->dust_lock, flags);
+       bblock->bb = block * dd->sect_per_block;
+       if (!dust_rb_insert(&dd->badblocklist, bblock)) {
+               if (!dd->quiet_mode) {
+                       DMERR("%s: block %llu already in badblocklist",
+                             __func__, block);
+               }
+               spin_unlock_irqrestore(&dd->dust_lock, flags);
+               kfree(bblock);
+               return -EINVAL;
+       }
+
+       dd->badblock_count++;
+       if (!dd->quiet_mode)
+               DMINFO("%s: badblock added at block %llu", __func__, block);
+       spin_unlock_irqrestore(&dd->dust_lock, flags);
+
+       return 0;
+}
+
+static int dust_query_block(struct dust_device *dd, unsigned long long block)
+{
+       struct badblock *bblock;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dd->dust_lock, flags);
+       bblock = dust_rb_search(&dd->badblocklist, block * dd->sect_per_block);
+       if (bblock != NULL)
+               DMINFO("%s: block %llu found in badblocklist", __func__, block);
+       else
+               DMINFO("%s: block %llu not found in badblocklist", __func__, block);
+       spin_unlock_irqrestore(&dd->dust_lock, flags);
+
+       return 0;
+}
+
+static int __dust_map_read(struct dust_device *dd, sector_t thisblock)
+{
+       struct badblock *bblk = dust_rb_search(&dd->badblocklist, thisblock);
+
+       if (bblk)
+               return DM_MAPIO_KILL;
+
+       return DM_MAPIO_REMAPPED;
+}
+
+static int dust_map_read(struct dust_device *dd, sector_t thisblock,
+                        bool fail_read_on_bb)
+{
+       unsigned long flags;
+       int ret = DM_MAPIO_REMAPPED;
+
+       if (fail_read_on_bb) {
+               spin_lock_irqsave(&dd->dust_lock, flags);
+               ret = __dust_map_read(dd, thisblock);
+               spin_unlock_irqrestore(&dd->dust_lock, flags);
+       }
+
+       return ret;
+}
+
+static void __dust_map_write(struct dust_device *dd, sector_t thisblock)
+{
+       struct badblock *bblk = dust_rb_search(&dd->badblocklist, thisblock);
+
+       if (bblk) {
+               rb_erase(&bblk->node, &dd->badblocklist);
+               dd->badblock_count--;
+               kfree(bblk);
+               if (!dd->quiet_mode) {
+                       sector_div(thisblock, dd->sect_per_block);
+                       DMINFO("block %llu removed from badblocklist by write",
+                              (unsigned long long)thisblock);
+               }
+       }
+}
+
+static int dust_map_write(struct dust_device *dd, sector_t thisblock,
+                         bool fail_read_on_bb)
+{
+       unsigned long flags;
+
+       if (fail_read_on_bb) {
+               spin_lock_irqsave(&dd->dust_lock, flags);
+               __dust_map_write(dd, thisblock);
+               spin_unlock_irqrestore(&dd->dust_lock, flags);
+       }
+
+       return DM_MAPIO_REMAPPED;
+}
+
+static int dust_map(struct dm_target *ti, struct bio *bio)
+{
+       struct dust_device *dd = ti->private;
+       int ret;
+
+       bio_set_dev(bio, dd->dev->bdev);
+       bio->bi_iter.bi_sector = dd->start + dm_target_offset(ti, bio->bi_iter.bi_sector);
+
+       if (bio_data_dir(bio) == READ)
+               ret = dust_map_read(dd, bio->bi_iter.bi_sector, dd->fail_read_on_bb);
+       else
+               ret = dust_map_write(dd, bio->bi_iter.bi_sector, dd->fail_read_on_bb);
+
+       return ret;
+}
+
+static bool __dust_clear_badblocks(struct rb_root *tree,
+                                  unsigned long long count)
+{
+       struct rb_node *node = NULL, *nnode = NULL;
+
+       nnode = rb_first(tree);
+       if (nnode == NULL) {
+               BUG_ON(count != 0);
+               return false;
+       }
+
+       while (nnode) {
+               node = nnode;
+               nnode = rb_next(node);
+               rb_erase(node, tree);
+               count--;
+               kfree(node);
+       }
+       BUG_ON(count != 0);
+       BUG_ON(tree->rb_node != NULL);
+
+       return true;
+}
+
+static int dust_clear_badblocks(struct dust_device *dd)
+{
+       unsigned long flags;
+       struct rb_root badblocklist;
+       unsigned long long badblock_count;
+
+       spin_lock_irqsave(&dd->dust_lock, flags);
+       badblocklist = dd->badblocklist;
+       badblock_count = dd->badblock_count;
+       dd->badblocklist = RB_ROOT;
+       dd->badblock_count = 0;
+       spin_unlock_irqrestore(&dd->dust_lock, flags);
+
+       if (!__dust_clear_badblocks(&badblocklist, badblock_count))
+               DMINFO("%s: no badblocks found", __func__);
+       else
+               DMINFO("%s: badblocks cleared", __func__);
+
+       return 0;
+}
+
+/*
+ * Target parameters:
+ *
+ * <device_path> <offset> <blksz>
+ *
+ * device_path: path to the block device
+ * offset: offset to data area from start of device_path
+ * blksz: block size (minimum 512, maximum 1073741824, must be a power of 2)
+ */
+static int dust_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+{
+       struct dust_device *dd;
+       unsigned long long tmp;
+       char dummy;
+       unsigned int blksz;
+       unsigned int sect_per_block;
+       sector_t DUST_MAX_BLKSZ_SECTORS = 2097152;
+       sector_t max_block_sectors = min(ti->len, DUST_MAX_BLKSZ_SECTORS);
+
+       if (argc != 3) {
+               ti->error = "Invalid argument count";
+               return -EINVAL;
+       }
+
+       if (kstrtouint(argv[2], 10, &blksz) || !blksz) {
+               ti->error = "Invalid block size parameter";
+               return -EINVAL;
+       }
+
+       if (blksz < 512) {
+               ti->error = "Block size must be at least 512";
+               return -EINVAL;
+       }
+
+       if (!is_power_of_2(blksz)) {
+               ti->error = "Block size must be a power of 2";
+               return -EINVAL;
+       }
+
+       if (to_sector(blksz) > max_block_sectors) {
+               ti->error = "Block size is too large";
+               return -EINVAL;
+       }
+
+       sect_per_block = (blksz >> SECTOR_SHIFT);
+
+       if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1 || tmp != (sector_t)tmp) {
+               ti->error = "Invalid device offset sector";
+               return -EINVAL;
+       }
+
+       dd = kzalloc(sizeof(struct dust_device), GFP_KERNEL);
+       if (dd == NULL) {
+               ti->error = "Cannot allocate context";
+               return -ENOMEM;
+       }
+
+       if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &dd->dev)) {
+               ti->error = "Device lookup failed";
+               kfree(dd);
+               return -EINVAL;
+       }
+
+       dd->sect_per_block = sect_per_block;
+       dd->blksz = blksz;
+       dd->start = tmp;
+
+       /*
+        * Whether to fail a read on a "bad" block.
+        * Defaults to false; enabled later by message.
+        */
+       dd->fail_read_on_bb = false;
+
+       /*
+        * Initialize bad block list rbtree.
+        */
+       dd->badblocklist = RB_ROOT;
+       dd->badblock_count = 0;
+       spin_lock_init(&dd->dust_lock);
+
+       dd->quiet_mode = false;
+
+       BUG_ON(dm_set_target_max_io_len(ti, dd->sect_per_block) != 0);
+
+       ti->num_discard_bios = 1;
+       ti->num_flush_bios = 1;
+       ti->private = dd;
+
+       return 0;
+}
+
+static void dust_dtr(struct dm_target *ti)
+{
+       struct dust_device *dd = ti->private;
+
+       __dust_clear_badblocks(&dd->badblocklist, dd->badblock_count);
+       dm_put_device(ti, dd->dev);
+       kfree(dd);
+}
+
+static int dust_message(struct dm_target *ti, unsigned int argc, char **argv,
+                       char *result_buf, unsigned int maxlen)
+{
+       struct dust_device *dd = ti->private;
+       sector_t size = i_size_read(dd->dev->bdev->bd_inode) >> SECTOR_SHIFT;
+       bool invalid_msg = false;
+       int result = -EINVAL;
+       unsigned long long tmp, block;
+       unsigned long flags;
+       char dummy;
+
+       if (argc == 1) {
+               if (!strcasecmp(argv[0], "addbadblock") ||
+                   !strcasecmp(argv[0], "removebadblock") ||
+                   !strcasecmp(argv[0], "queryblock")) {
+                       DMERR("%s requires an additional argument", argv[0]);
+               } else if (!strcasecmp(argv[0], "disable")) {
+                       DMINFO("disabling read failures on bad sectors");
+                       dd->fail_read_on_bb = false;
+                       result = 0;
+               } else if (!strcasecmp(argv[0], "enable")) {
+                       DMINFO("enabling read failures on bad sectors");
+                       dd->fail_read_on_bb = true;
+                       result = 0;
+               } else if (!strcasecmp(argv[0], "countbadblocks")) {
+                       spin_lock_irqsave(&dd->dust_lock, flags);
+                       DMINFO("countbadblocks: %llu badblock(s) found",
+                              dd->badblock_count);
+                       spin_unlock_irqrestore(&dd->dust_lock, flags);
+                       result = 0;
+               } else if (!strcasecmp(argv[0], "clearbadblocks")) {
+                       result = dust_clear_badblocks(dd);
+               } else if (!strcasecmp(argv[0], "quiet")) {
+                       if (!dd->quiet_mode)
+                               dd->quiet_mode = true;
+                       else
+                               dd->quiet_mode = false;
+                       result = 0;
+               } else {
+                       invalid_msg = true;
+               }
+       } else if (argc == 2) {
+               if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1)
+                       return result;
+
+               block = tmp;
+               sector_div(size, dd->sect_per_block);
+               if (block > size) {
+                       DMERR("selected block value out of range");
+                       return result;
+               }
+
+               if (!strcasecmp(argv[0], "addbadblock"))
+                       result = dust_add_block(dd, block);
+               else if (!strcasecmp(argv[0], "removebadblock"))
+                       result = dust_remove_block(dd, block);
+               else if (!strcasecmp(argv[0], "queryblock"))
+                       result = dust_query_block(dd, block);
+               else
+                       invalid_msg = true;
+
+       } else
+               DMERR("invalid number of arguments '%d'", argc);
+
+       if (invalid_msg)
+               DMERR("unrecognized message '%s' received", argv[0]);
+
+       return result;
+}
+
+static void dust_status(struct dm_target *ti, status_type_t type,
+                       unsigned int status_flags, char *result, unsigned int maxlen)
+{
+       struct dust_device *dd = ti->private;
+       unsigned int sz = 0;
+
+       switch (type) {
+       case STATUSTYPE_INFO:
+               DMEMIT("%s %s %s", dd->dev->name,
+                      dd->fail_read_on_bb ? "fail_read_on_bad_block" : "bypass",
+                      dd->quiet_mode ? "quiet" : "verbose");
+               break;
+
+       case STATUSTYPE_TABLE:
+               DMEMIT("%s %llu %u", dd->dev->name,
+                      (unsigned long long)dd->start, dd->blksz);
+               break;
+       }
+}
+
+static int dust_prepare_ioctl(struct dm_target *ti, struct block_device **bdev)
+{
+       struct dust_device *dd = ti->private;
+       struct dm_dev *dev = dd->dev;
+
+       *bdev = dev->bdev;
+
+       /*
+        * Only pass ioctls through if the device sizes match exactly.
+        */
+       if (dd->start ||
+           ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
+               return 1;
+
+       return 0;
+}
+
+static int dust_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn,
+                               void *data)
+{
+       struct dust_device *dd = ti->private;
+
+       return fn(ti, dd->dev, dd->start, ti->len, data);
+}
+
+static struct target_type dust_target = {
+       .name = "dust",
+       .version = {1, 0, 0},
+       .module = THIS_MODULE,
+       .ctr = dust_ctr,
+       .dtr = dust_dtr,
+       .iterate_devices = dust_iterate_devices,
+       .map = dust_map,
+       .message = dust_message,
+       .status = dust_status,
+       .prepare_ioctl = dust_prepare_ioctl,
+};
+
+static int __init dm_dust_init(void)
+{
+       int result = dm_register_target(&dust_target);
+
+       if (result < 0)
+               DMERR("dm_register_target failed %d", result);
+
+       return result;
+}
+
+static void __exit dm_dust_exit(void)
+{
+       dm_unregister_target(&dust_target);
+}
+
+module_init(dm_dust_init);
+module_exit(dm_dust_exit);
+
+MODULE_DESCRIPTION(DM_NAME " dust test target");
+MODULE_AUTHOR("Bryan Gurney <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
index 721efc4..3f4139a 100644 (file)
@@ -11,6 +11,7 @@
 #define _LINUX_DM_EXCEPTION_STORE
 
 #include <linux/blkdev.h>
+#include <linux/list_bl.h>
 #include <linux/device-mapper.h>
 
 /*
@@ -27,7 +28,7 @@ typedef sector_t chunk_t;
  * chunk within the device.
  */
 struct dm_exception {
-       struct list_head hash_list;
+       struct hlist_bl_node hash_list;
 
        chunk_t old_chunk;
        chunk_t new_chunk;
index 4b76f84..352e803 100644 (file)
@@ -160,7 +160,7 @@ static int __init dm_parse_table(struct dm_device *dev, char *str)
 
        while (table_entry) {
                DMDEBUG("parsing table \"%s\"", str);
-               if (++dev->dmi.target_count >= DM_MAX_TARGETS) {
+               if (++dev->dmi.target_count > DM_MAX_TARGETS) {
                        DMERR("too many targets %u > %d",
                              dev->dmi.target_count, DM_MAX_TARGETS);
                        return -EINVAL;
@@ -242,9 +242,9 @@ static int __init dm_parse_devices(struct list_head *devices, char *str)
                        return -ENOMEM;
                list_add_tail(&dev->list, devices);
 
-               if (++ndev >= DM_MAX_DEVICES) {
-                       DMERR("too many targets %u > %d",
-                             dev->dmi.target_count, DM_MAX_TARGETS);
+               if (++ndev > DM_MAX_DEVICES) {
+                       DMERR("too many devices %lu > %d",
+                             ndev, DM_MAX_DEVICES);
                        return -EINVAL;
                }
 
index c27c32c..44e76cd 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/rbtree.h>
 #include <linux/delay.h>
 #include <linux/random.h>
+#include <linux/reboot.h>
 #include <crypto/hash.h>
 #include <crypto/skcipher.h>
 #include <linux/async_tx.h>
@@ -24,6 +25,7 @@
 
 #define DEFAULT_INTERLEAVE_SECTORS     32768
 #define DEFAULT_JOURNAL_SIZE_FACTOR    7
+#define DEFAULT_SECTORS_PER_BITMAP_BIT 32768
 #define DEFAULT_BUFFER_SECTORS         128
 #define DEFAULT_JOURNAL_WATERMARK      50
 #define DEFAULT_SYNC_MSEC              10000
@@ -33,6 +35,8 @@
 #define METADATA_WORKQUEUE_MAX_ACTIVE  16
 #define RECALC_SECTORS                 8192
 #define RECALC_WRITE_SUPER             16
+#define BITMAP_BLOCK_SIZE              4096    /* don't change it */
+#define BITMAP_FLUSH_INTERVAL          (10 * HZ)
 
 /*
  * Warning - DEBUG_PRINT prints security-sensitive data to the log,
@@ -48,6 +52,7 @@
 #define SB_MAGIC                       "integrt"
 #define SB_VERSION_1                   1
 #define SB_VERSION_2                   2
+#define SB_VERSION_3                   3
 #define SB_SECTORS                     8
 #define MAX_SECTORS_PER_BLOCK          8
 
@@ -60,12 +65,14 @@ struct superblock {
        __u64 provided_data_sectors;    /* userspace uses this value */
        __u32 flags;
        __u8 log2_sectors_per_block;
-       __u8 pad[3];
+       __u8 log2_blocks_per_bitmap_bit;
+       __u8 pad[2];
        __u64 recalc_sector;
 };
 
 #define SB_FLAG_HAVE_JOURNAL_MAC       0x1
 #define SB_FLAG_RECALCULATING          0x2
+#define SB_FLAG_DIRTY_BITMAP           0x4
 
 #define        JOURNAL_ENTRY_ROUNDUP           8
 
@@ -151,9 +158,18 @@ struct dm_integrity_c {
        struct workqueue_struct *metadata_wq;
        struct superblock *sb;
        unsigned journal_pages;
+       unsigned n_bitmap_blocks;
+
        struct page_list *journal;
        struct page_list *journal_io;
        struct page_list *journal_xor;
+       struct page_list *recalc_bitmap;
+       struct page_list *may_write_bitmap;
+       struct bitmap_block_status *bbs;
+       unsigned bitmap_flush_interval;
+       int synchronous_mode;
+       struct bio_list synchronous_bios;
+       struct delayed_work bitmap_flush_work;
 
        struct crypto_skcipher *journal_crypt;
        struct scatterlist **journal_scatterlist;
@@ -180,6 +196,7 @@ struct dm_integrity_c {
        __s8 log2_metadata_run;
        __u8 log2_buffer_sectors;
        __u8 sectors_per_block;
+       __u8 log2_blocks_per_bitmap_bit;
 
        unsigned char mode;
        int suspending;
@@ -232,17 +249,20 @@ struct dm_integrity_c {
 
        bool journal_uptodate;
        bool just_formatted;
+       bool recalculate_flag;
 
        struct alg_spec internal_hash_alg;
        struct alg_spec journal_crypt_alg;
        struct alg_spec journal_mac_alg;
 
        atomic64_t number_of_mismatches;
+
+       struct notifier_block reboot_notifier;
 };
 
 struct dm_integrity_range {
        sector_t logical_sector;
-       unsigned n_sectors;
+       sector_t n_sectors;
        bool waiting;
        union {
                struct rb_node node;
@@ -288,6 +308,16 @@ struct journal_io {
        struct journal_completion *comp;
 };
 
+struct bitmap_block_status {
+       struct work_struct work;
+       struct dm_integrity_c *ic;
+       unsigned idx;
+       unsigned long *bitmap;
+       struct bio_list bio_queue;
+       spinlock_t bio_queue_lock;
+
+};
+
 static struct kmem_cache *journal_io_cache;
 
 #define JOURNAL_IO_MEMPOOL     32
@@ -423,7 +453,9 @@ static void wraparound_section(struct dm_integrity_c *ic, unsigned *sec_ptr)
 
 static void sb_set_version(struct dm_integrity_c *ic)
 {
-       if (ic->meta_dev || ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING))
+       if (ic->mode == 'B' || ic->sb->flags & cpu_to_le32(SB_FLAG_DIRTY_BITMAP))
+               ic->sb->version = SB_VERSION_3;
+       else if (ic->meta_dev || ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING))
                ic->sb->version = SB_VERSION_2;
        else
                ic->sb->version = SB_VERSION_1;
@@ -447,6 +479,137 @@ static int sync_rw_sb(struct dm_integrity_c *ic, int op, int op_flags)
        return dm_io(&io_req, 1, &io_loc, NULL);
 }
 
+#define BITMAP_OP_TEST_ALL_SET         0
+#define BITMAP_OP_TEST_ALL_CLEAR       1
+#define BITMAP_OP_SET                  2
+#define BITMAP_OP_CLEAR                        3
+
+static bool block_bitmap_op(struct dm_integrity_c *ic, struct page_list *bitmap,
+                           sector_t sector, sector_t n_sectors, int mode)
+{
+       unsigned long bit, end_bit, this_end_bit, page, end_page;
+       unsigned long *data;
+
+       if (unlikely(((sector | n_sectors) & ((1 << ic->sb->log2_sectors_per_block) - 1)) != 0)) {
+               DMCRIT("invalid bitmap access (%llx,%llx,%d,%d,%d)",
+                       (unsigned long long)sector,
+                       (unsigned long long)n_sectors,
+                       ic->sb->log2_sectors_per_block,
+                       ic->log2_blocks_per_bitmap_bit,
+                       mode);
+               BUG();
+       }
+
+       if (unlikely(!n_sectors))
+               return true;
+
+       bit = sector >> (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
+       end_bit = (sector + n_sectors - 1) >>
+               (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
+
+       page = bit / (PAGE_SIZE * 8);
+       bit %= PAGE_SIZE * 8;
+
+       end_page = end_bit / (PAGE_SIZE * 8);
+       end_bit %= PAGE_SIZE * 8;
+
+repeat:
+       if (page < end_page) {
+               this_end_bit = PAGE_SIZE * 8 - 1;
+       } else {
+               this_end_bit = end_bit;
+       }
+
+       data = lowmem_page_address(bitmap[page].page);
+
+       if (mode == BITMAP_OP_TEST_ALL_SET) {
+               while (bit <= this_end_bit) {
+                       if (!(bit % BITS_PER_LONG) && this_end_bit >= bit + BITS_PER_LONG - 1) {
+                               do {
+                                       if (data[bit / BITS_PER_LONG] != -1)
+                                               return false;
+                                       bit += BITS_PER_LONG;
+                               } while (this_end_bit >= bit + BITS_PER_LONG - 1);
+                               continue;
+                       }
+                       if (!test_bit(bit, data))
+                               return false;
+                       bit++;
+               }
+       } else if (mode == BITMAP_OP_TEST_ALL_CLEAR) {
+               while (bit <= this_end_bit) {
+                       if (!(bit % BITS_PER_LONG) && this_end_bit >= bit + BITS_PER_LONG - 1) {
+                               do {
+                                       if (data[bit / BITS_PER_LONG] != 0)
+                                               return false;
+                                       bit += BITS_PER_LONG;
+                               } while (this_end_bit >= bit + BITS_PER_LONG - 1);
+                               continue;
+                       }
+                       if (test_bit(bit, data))
+                               return false;
+                       bit++;
+               }
+       } else if (mode == BITMAP_OP_SET) {
+               while (bit <= this_end_bit) {
+                       if (!(bit % BITS_PER_LONG) && this_end_bit >= bit + BITS_PER_LONG - 1) {
+                               do {
+                                       data[bit / BITS_PER_LONG] = -1;
+                                       bit += BITS_PER_LONG;
+                               } while (this_end_bit >= bit + BITS_PER_LONG - 1);
+                               continue;
+                       }
+                       __set_bit(bit, data);
+                       bit++;
+               }
+       } else if (mode == BITMAP_OP_CLEAR) {
+               if (!bit && this_end_bit == PAGE_SIZE * 8 - 1)
+                       clear_page(data);
+               else while (bit <= this_end_bit) {
+                       if (!(bit % BITS_PER_LONG) && this_end_bit >= bit + BITS_PER_LONG - 1) {
+                               do {
+                                       data[bit / BITS_PER_LONG] = 0;
+                                       bit += BITS_PER_LONG;
+                               } while (this_end_bit >= bit + BITS_PER_LONG - 1);
+                               continue;
+                       }
+                       __clear_bit(bit, data);
+                       bit++;
+               }
+       } else {
+               BUG();
+       }
+
+       if (unlikely(page < end_page)) {
+               bit = 0;
+               page++;
+               goto repeat;
+       }
+
+       return true;
+}
+
+static void block_bitmap_copy(struct dm_integrity_c *ic, struct page_list *dst, struct page_list *src)
+{
+       unsigned n_bitmap_pages = DIV_ROUND_UP(ic->n_bitmap_blocks, PAGE_SIZE / BITMAP_BLOCK_SIZE);
+       unsigned i;
+
+       for (i = 0; i < n_bitmap_pages; i++) {
+               unsigned long *dst_data = lowmem_page_address(dst[i].page);
+               unsigned long *src_data = lowmem_page_address(src[i].page);
+               copy_page(dst_data, src_data);
+       }
+}
+
+static struct bitmap_block_status *sector_to_bitmap_block(struct dm_integrity_c *ic, sector_t sector)
+{
+       unsigned bit = sector >> (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
+       unsigned bitmap_block = bit / (BITMAP_BLOCK_SIZE * 8);
+
+       BUG_ON(bitmap_block >= ic->n_bitmap_blocks);
+       return &ic->bbs[bitmap_block];
+}
+
 static void access_journal_check(struct dm_integrity_c *ic, unsigned section, unsigned offset,
                                 bool e, const char *function)
 {
@@ -455,8 +618,8 @@ static void access_journal_check(struct dm_integrity_c *ic, unsigned section, un
 
        if (unlikely(section >= ic->journal_sections) ||
            unlikely(offset >= limit)) {
-               printk(KERN_CRIT "%s: invalid access at (%u,%u), limit (%u,%u)\n",
-                       function, section, offset, ic->journal_sections, limit);
+               DMCRIT("%s: invalid access at (%u,%u), limit (%u,%u)",
+                      function, section, offset, ic->journal_sections, limit);
                BUG();
        }
 #endif
@@ -756,12 +919,12 @@ static void complete_journal_io(unsigned long error, void *context)
        complete_journal_op(comp);
 }
 
-static void rw_journal(struct dm_integrity_c *ic, int op, int op_flags, unsigned section,
-                      unsigned n_sections, struct journal_completion *comp)
+static void rw_journal_sectors(struct dm_integrity_c *ic, int op, int op_flags,
+                              unsigned sector, unsigned n_sectors, struct journal_completion *comp)
 {
        struct dm_io_request io_req;
        struct dm_io_region io_loc;
-       unsigned sector, n_sectors, pl_index, pl_offset;
+       unsigned pl_index, pl_offset;
        int r;
 
        if (unlikely(dm_integrity_failed(ic))) {
@@ -770,9 +933,6 @@ static void rw_journal(struct dm_integrity_c *ic, int op, int op_flags, unsigned
                return;
        }
 
-       sector = section * ic->journal_section_sectors;
-       n_sectors = n_sections * ic->journal_section_sectors;
-
        pl_index = sector >> (PAGE_SHIFT - SECTOR_SHIFT);
        pl_offset = (sector << SECTOR_SHIFT) & (PAGE_SIZE - 1);
 
@@ -805,6 +965,17 @@ static void rw_journal(struct dm_integrity_c *ic, int op, int op_flags, unsigned
        }
 }
 
+static void rw_journal(struct dm_integrity_c *ic, int op, int op_flags, unsigned section,
+                      unsigned n_sections, struct journal_completion *comp)
+{
+       unsigned sector, n_sectors;
+
+       sector = section * ic->journal_section_sectors;
+       n_sectors = n_sections * ic->journal_section_sectors;
+
+       rw_journal_sectors(ic, op, op_flags, sector, n_sectors, comp);
+}
+
 static void write_journal(struct dm_integrity_c *ic, unsigned commit_start, unsigned commit_sections)
 {
        struct journal_completion io_comp;
@@ -988,6 +1159,12 @@ static void wait_and_add_new_range(struct dm_integrity_c *ic, struct dm_integrit
        } while (unlikely(new_range->waiting));
 }
 
+static void add_new_range_and_wait(struct dm_integrity_c *ic, struct dm_integrity_range *new_range)
+{
+       if (unlikely(!add_new_range(ic, new_range, true)))
+               wait_and_add_new_range(ic, new_range);
+}
+
 static void init_journal_node(struct journal_node *node)
 {
        RB_CLEAR_NODE(&node->node);
@@ -1204,6 +1381,14 @@ static void do_endio(struct dm_integrity_c *ic, struct bio *bio)
        int r = dm_integrity_failed(ic);
        if (unlikely(r) && !bio->bi_status)
                bio->bi_status = errno_to_blk_status(r);
+       if (unlikely(ic->synchronous_mode) && bio_op(bio) == REQ_OP_WRITE) {
+               unsigned long flags;
+               spin_lock_irqsave(&ic->endio_wait.lock, flags);
+               bio_list_add(&ic->synchronous_bios, bio);
+               queue_delayed_work(ic->commit_wq, &ic->bitmap_flush_work, 0);
+               spin_unlock_irqrestore(&ic->endio_wait.lock, flags);
+               return;
+       }
        bio_endio(bio);
 }
 
@@ -1477,7 +1662,8 @@ static int dm_integrity_map(struct dm_target *ti, struct bio *bio)
                        else
                                wanted_tag_size *= ic->tag_size;
                        if (unlikely(wanted_tag_size != bip->bip_iter.bi_size)) {
-                               DMERR("Invalid integrity data size %u, expected %u", bip->bip_iter.bi_size, wanted_tag_size);
+                               DMERR("Invalid integrity data size %u, expected %u",
+                                     bip->bip_iter.bi_size, wanted_tag_size);
                                return DM_MAPIO_KILL;
                        }
                }
@@ -1681,7 +1867,7 @@ retry:
                        unsigned ws, we, range_sectors;
 
                        dio->range.n_sectors = min(dio->range.n_sectors,
-                                                  ic->free_sectors << ic->sb->log2_sectors_per_block);
+                                                  (sector_t)ic->free_sectors << ic->sb->log2_sectors_per_block);
                        if (unlikely(!dio->range.n_sectors)) {
                                if (from_map)
                                        goto offload_to_thread;
@@ -1764,6 +1950,20 @@ offload_to_thread:
                goto journal_read_write;
        }
 
+       if (ic->mode == 'B' && dio->write) {
+               if (!block_bitmap_op(ic, ic->may_write_bitmap, dio->range.logical_sector,
+                                    dio->range.n_sectors, BITMAP_OP_TEST_ALL_SET)) {
+                       struct bitmap_block_status *bbs;
+
+                       bbs = sector_to_bitmap_block(ic, dio->range.logical_sector);
+                       spin_lock(&bbs->bio_queue_lock);
+                       bio_list_add(&bbs->bio_queue, bio);
+                       spin_unlock(&bbs->bio_queue_lock);
+                       queue_work(ic->writer_wq, &bbs->work);
+                       return;
+               }
+       }
+
        dio->in_flight = (atomic_t)ATOMIC_INIT(2);
 
        if (need_sync_io) {
@@ -1790,10 +1990,15 @@ offload_to_thread:
 
        if (need_sync_io) {
                wait_for_completion_io(&read_comp);
-               if (unlikely(ic->recalc_wq != NULL) &&
-                   ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING) &&
+               if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING) &&
                    dio->range.logical_sector + dio->range.n_sectors > le64_to_cpu(ic->sb->recalc_sector))
                        goto skip_check;
+               if (ic->mode == 'B') {
+                       if (!block_bitmap_op(ic, ic->recalc_bitmap, dio->range.logical_sector,
+                                            dio->range.n_sectors, BITMAP_OP_TEST_ALL_CLEAR))
+                               goto skip_check;
+               }
+
                if (likely(!bio->bi_status))
                        integrity_metadata(&dio->work);
                else
@@ -1831,8 +2036,16 @@ static void pad_uncommitted(struct dm_integrity_c *ic)
                wraparound_section(ic, &ic->free_section);
                ic->n_uncommitted_sections++;
        }
-       WARN_ON(ic->journal_sections * ic->journal_section_entries !=
-               (ic->n_uncommitted_sections + ic->n_committed_sections) * ic->journal_section_entries + ic->free_sectors);
+       if (WARN_ON(ic->journal_sections * ic->journal_section_entries !=
+                   (ic->n_uncommitted_sections + ic->n_committed_sections) *
+                   ic->journal_section_entries + ic->free_sectors)) {
+               DMCRIT("journal_sections %u, journal_section_entries %u, "
+                      "n_uncommitted_sections %u, n_committed_sections %u, "
+                      "journal_section_entries %u, free_sectors %u",
+                      ic->journal_sections, ic->journal_section_entries,
+                      ic->n_uncommitted_sections, ic->n_committed_sections,
+                      ic->journal_section_entries, ic->free_sectors);
+       }
 }
 
 static void integrity_commit(struct work_struct *w)
@@ -1981,8 +2194,7 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
                        io->range.n_sectors = (k - j) << ic->sb->log2_sectors_per_block;
 
                        spin_lock_irq(&ic->endio_wait.lock);
-                       if (unlikely(!add_new_range(ic, &io->range, true)))
-                               wait_and_add_new_range(ic, &io->range);
+                       add_new_range_and_wait(ic, &io->range);
 
                        if (likely(!from_replay)) {
                                struct journal_node *section_node = &ic->journal_tree[i * ic->journal_section_entries];
@@ -2120,11 +2332,14 @@ static void integrity_recalc(struct work_struct *w)
        sector_t area, offset;
        sector_t metadata_block;
        unsigned metadata_offset;
+       sector_t logical_sector, n_sectors;
        __u8 *t;
        unsigned i;
        int r;
        unsigned super_counter = 0;
 
+       DEBUG_print("start recalculation... (position %llx)\n", le64_to_cpu(ic->sb->recalc_sector));
+
        spin_lock_irq(&ic->endio_wait.lock);
 
 next_chunk:
@@ -2133,21 +2348,49 @@ next_chunk:
                goto unlock_ret;
 
        range.logical_sector = le64_to_cpu(ic->sb->recalc_sector);
-       if (unlikely(range.logical_sector >= ic->provided_data_sectors))
+       if (unlikely(range.logical_sector >= ic->provided_data_sectors)) {
+               if (ic->mode == 'B') {
+                       DEBUG_print("queue_delayed_work: bitmap_flush_work\n");
+                       queue_delayed_work(ic->commit_wq, &ic->bitmap_flush_work, 0);
+               }
                goto unlock_ret;
+       }
 
        get_area_and_offset(ic, range.logical_sector, &area, &offset);
        range.n_sectors = min((sector_t)RECALC_SECTORS, ic->provided_data_sectors - range.logical_sector);
        if (!ic->meta_dev)
-               range.n_sectors = min(range.n_sectors, (1U << ic->sb->log2_interleave_sectors) - (unsigned)offset);
-
-       if (unlikely(!add_new_range(ic, &range, true)))
-               wait_and_add_new_range(ic, &range);
+               range.n_sectors = min(range.n_sectors, ((sector_t)1U << ic->sb->log2_interleave_sectors) - (unsigned)offset);
 
+       add_new_range_and_wait(ic, &range);
        spin_unlock_irq(&ic->endio_wait.lock);
+       logical_sector = range.logical_sector;
+       n_sectors = range.n_sectors;
+
+       if (ic->mode == 'B') {
+               if (block_bitmap_op(ic, ic->recalc_bitmap, logical_sector, n_sectors, BITMAP_OP_TEST_ALL_CLEAR)) {
+                       goto advance_and_next;
+               }
+               while (block_bitmap_op(ic, ic->recalc_bitmap, logical_sector,
+                                      ic->sectors_per_block, BITMAP_OP_TEST_ALL_CLEAR)) {
+                       logical_sector += ic->sectors_per_block;
+                       n_sectors -= ic->sectors_per_block;
+                       cond_resched();
+               }
+               while (block_bitmap_op(ic, ic->recalc_bitmap, logical_sector + n_sectors - ic->sectors_per_block,
+                                      ic->sectors_per_block, BITMAP_OP_TEST_ALL_CLEAR)) {
+                       n_sectors -= ic->sectors_per_block;
+                       cond_resched();
+               }
+               get_area_and_offset(ic, logical_sector, &area, &offset);
+       }
+
+       DEBUG_print("recalculating: %lx, %lx\n", logical_sector, n_sectors);
 
        if (unlikely(++super_counter == RECALC_WRITE_SUPER)) {
                recalc_write_super(ic);
+               if (ic->mode == 'B') {
+                       queue_delayed_work(ic->commit_wq, &ic->bitmap_flush_work, ic->bitmap_flush_interval);
+               }
                super_counter = 0;
        }
 
@@ -2162,7 +2405,7 @@ next_chunk:
        io_req.client = ic->io;
        io_loc.bdev = ic->dev->bdev;
        io_loc.sector = get_data_sector(ic, area, offset);
-       io_loc.count = range.n_sectors;
+       io_loc.count = n_sectors;
 
        r = dm_io(&io_req, 1, &io_loc, NULL);
        if (unlikely(r)) {
@@ -2171,8 +2414,8 @@ next_chunk:
        }
 
        t = ic->recalc_tags;
-       for (i = 0; i < range.n_sectors; i += ic->sectors_per_block) {
-               integrity_sector_checksum(ic, range.logical_sector + i, ic->recalc_buffer + (i << SECTOR_SHIFT), t);
+       for (i = 0; i < n_sectors; i += ic->sectors_per_block) {
+               integrity_sector_checksum(ic, logical_sector + i, ic->recalc_buffer + (i << SECTOR_SHIFT), t);
                t += ic->tag_size;
        }
 
@@ -2184,6 +2427,9 @@ next_chunk:
                goto err;
        }
 
+advance_and_next:
+       cond_resched();
+
        spin_lock_irq(&ic->endio_wait.lock);
        remove_range_unlocked(ic, &range);
        ic->sb->recalc_sector = cpu_to_le64(range.logical_sector + range.n_sectors);
@@ -2199,6 +2445,103 @@ unlock_ret:
        recalc_write_super(ic);
 }
 
+static void bitmap_block_work(struct work_struct *w)
+{
+       struct bitmap_block_status *bbs = container_of(w, struct bitmap_block_status, work);
+       struct dm_integrity_c *ic = bbs->ic;
+       struct bio *bio;
+       struct bio_list bio_queue;
+       struct bio_list waiting;
+
+       bio_list_init(&waiting);
+
+       spin_lock(&bbs->bio_queue_lock);
+       bio_queue = bbs->bio_queue;
+       bio_list_init(&bbs->bio_queue);
+       spin_unlock(&bbs->bio_queue_lock);
+
+       while ((bio = bio_list_pop(&bio_queue))) {
+               struct dm_integrity_io *dio;
+
+               dio = dm_per_bio_data(bio, sizeof(struct dm_integrity_io));
+
+               if (block_bitmap_op(ic, ic->may_write_bitmap, dio->range.logical_sector,
+                                   dio->range.n_sectors, BITMAP_OP_TEST_ALL_SET)) {
+                       remove_range(ic, &dio->range);
+                       INIT_WORK(&dio->work, integrity_bio_wait);
+                       queue_work(ic->wait_wq, &dio->work);
+               } else {
+                       block_bitmap_op(ic, ic->journal, dio->range.logical_sector,
+                                       dio->range.n_sectors, BITMAP_OP_SET);
+                       bio_list_add(&waiting, bio);
+               }
+       }
+
+       if (bio_list_empty(&waiting))
+               return;
+
+       rw_journal_sectors(ic, REQ_OP_WRITE, REQ_FUA | REQ_SYNC,
+                          bbs->idx * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT),
+                          BITMAP_BLOCK_SIZE >> SECTOR_SHIFT, NULL);
+
+       while ((bio = bio_list_pop(&waiting))) {
+               struct dm_integrity_io *dio = dm_per_bio_data(bio, sizeof(struct dm_integrity_io));
+
+               block_bitmap_op(ic, ic->may_write_bitmap, dio->range.logical_sector,
+                               dio->range.n_sectors, BITMAP_OP_SET);
+
+               remove_range(ic, &dio->range);
+               INIT_WORK(&dio->work, integrity_bio_wait);
+               queue_work(ic->wait_wq, &dio->work);
+       }
+
+       queue_delayed_work(ic->commit_wq, &ic->bitmap_flush_work, ic->bitmap_flush_interval);
+}
+
+static void bitmap_flush_work(struct work_struct *work)
+{
+       struct dm_integrity_c *ic = container_of(work, struct dm_integrity_c, bitmap_flush_work.work);
+       struct dm_integrity_range range;
+       unsigned long limit;
+       struct bio *bio;
+
+       dm_integrity_flush_buffers(ic);
+
+       range.logical_sector = 0;
+       range.n_sectors = ic->provided_data_sectors;
+
+       spin_lock_irq(&ic->endio_wait.lock);
+       add_new_range_and_wait(ic, &range);
+       spin_unlock_irq(&ic->endio_wait.lock);
+
+       dm_integrity_flush_buffers(ic);
+       if (ic->meta_dev)
+               blkdev_issue_flush(ic->dev->bdev, GFP_NOIO, NULL);
+
+       limit = ic->provided_data_sectors;
+       if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) {
+               limit = le64_to_cpu(ic->sb->recalc_sector)
+                       >> (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit)
+                       << (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
+       }
+       /*DEBUG_print("zeroing journal\n");*/
+       block_bitmap_op(ic, ic->journal, 0, limit, BITMAP_OP_CLEAR);
+       block_bitmap_op(ic, ic->may_write_bitmap, 0, limit, BITMAP_OP_CLEAR);
+
+       rw_journal_sectors(ic, REQ_OP_WRITE, REQ_FUA | REQ_SYNC, 0,
+                          ic->n_bitmap_blocks * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT), NULL);
+
+       spin_lock_irq(&ic->endio_wait.lock);
+       remove_range_unlocked(ic, &range);
+       while (unlikely((bio = bio_list_pop(&ic->synchronous_bios)) != NULL)) {
+               bio_endio(bio);
+               spin_unlock_irq(&ic->endio_wait.lock);
+               spin_lock_irq(&ic->endio_wait.lock);
+       }
+       spin_unlock_irq(&ic->endio_wait.lock);
+}
+
+
 static void init_journal(struct dm_integrity_c *ic, unsigned start_section,
                         unsigned n_sections, unsigned char commit_seq)
 {
@@ -2395,9 +2738,37 @@ clear_journal:
                init_journal_node(&ic->journal_tree[i]);
 }
 
+static void dm_integrity_enter_synchronous_mode(struct dm_integrity_c *ic)
+{
+       DEBUG_print("dm_integrity_enter_synchronous_mode\n");
+
+       if (ic->mode == 'B') {
+               ic->bitmap_flush_interval = msecs_to_jiffies(10) + 1;
+               ic->synchronous_mode = 1;
+
+               cancel_delayed_work_sync(&ic->bitmap_flush_work);
+               queue_delayed_work(ic->commit_wq, &ic->bitmap_flush_work, 0);
+               flush_workqueue(ic->commit_wq);
+       }
+}
+
+static int dm_integrity_reboot(struct notifier_block *n, unsigned long code, void *x)
+{
+       struct dm_integrity_c *ic = container_of(n, struct dm_integrity_c, reboot_notifier);
+
+       DEBUG_print("dm_integrity_reboot\n");
+
+       dm_integrity_enter_synchronous_mode(ic);
+
+       return NOTIFY_DONE;
+}
+
 static void dm_integrity_postsuspend(struct dm_target *ti)
 {
        struct dm_integrity_c *ic = (struct dm_integrity_c *)ti->private;
+       int r;
+
+       WARN_ON(unregister_reboot_notifier(&ic->reboot_notifier));
 
        del_timer_sync(&ic->autocommit_timer);
 
@@ -2406,6 +2777,9 @@ static void dm_integrity_postsuspend(struct dm_target *ti)
        if (ic->recalc_wq)
                drain_workqueue(ic->recalc_wq);
 
+       if (ic->mode == 'B')
+               cancel_delayed_work_sync(&ic->bitmap_flush_work);
+
        queue_work(ic->commit_wq, &ic->commit_work);
        drain_workqueue(ic->commit_wq);
 
@@ -2416,6 +2790,18 @@ static void dm_integrity_postsuspend(struct dm_target *ti)
                dm_integrity_flush_buffers(ic);
        }
 
+       if (ic->mode == 'B') {
+               dm_integrity_flush_buffers(ic);
+#if 1
+               /* set to 0 to test bitmap replay code */
+               init_journal(ic, 0, ic->journal_sections, 0);
+               ic->sb->flags &= ~cpu_to_le32(SB_FLAG_DIRTY_BITMAP);
+               r = sync_rw_sb(ic, REQ_OP_WRITE, REQ_FUA);
+               if (unlikely(r))
+                       dm_integrity_io_error(ic, "writing superblock", r);
+#endif
+       }
+
        WRITE_ONCE(ic->suspending, 0);
 
        BUG_ON(!RB_EMPTY_ROOT(&ic->in_progress));
@@ -2426,11 +2812,70 @@ static void dm_integrity_postsuspend(struct dm_target *ti)
 static void dm_integrity_resume(struct dm_target *ti)
 {
        struct dm_integrity_c *ic = (struct dm_integrity_c *)ti->private;
+       int r;
+       DEBUG_print("resume\n");
+
+       if (ic->sb->flags & cpu_to_le32(SB_FLAG_DIRTY_BITMAP)) {
+               DEBUG_print("resume dirty_bitmap\n");
+               rw_journal_sectors(ic, REQ_OP_READ, 0, 0,
+                                  ic->n_bitmap_blocks * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT), NULL);
+               if (ic->mode == 'B') {
+                       if (ic->sb->log2_blocks_per_bitmap_bit == ic->log2_blocks_per_bitmap_bit) {
+                               block_bitmap_copy(ic, ic->recalc_bitmap, ic->journal);
+                               block_bitmap_copy(ic, ic->may_write_bitmap, ic->journal);
+                               if (!block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors,
+                                                    BITMAP_OP_TEST_ALL_CLEAR)) {
+                                       ic->sb->flags |= cpu_to_le32(SB_FLAG_RECALCULATING);
+                                       ic->sb->recalc_sector = cpu_to_le64(0);
+                               }
+                       } else {
+                               DEBUG_print("non-matching blocks_per_bitmap_bit: %u, %u\n",
+                                           ic->sb->log2_blocks_per_bitmap_bit, ic->log2_blocks_per_bitmap_bit);
+                               ic->sb->log2_blocks_per_bitmap_bit = ic->log2_blocks_per_bitmap_bit;
+                               block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_SET);
+                               block_bitmap_op(ic, ic->may_write_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_SET);
+                               block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors, BITMAP_OP_SET);
+                               rw_journal_sectors(ic, REQ_OP_WRITE, REQ_FUA | REQ_SYNC, 0,
+                                                  ic->n_bitmap_blocks * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT), NULL);
+                               ic->sb->flags |= cpu_to_le32(SB_FLAG_RECALCULATING);
+                               ic->sb->recalc_sector = cpu_to_le64(0);
+                       }
+               } else {
+                       if (!(ic->sb->log2_blocks_per_bitmap_bit == ic->log2_blocks_per_bitmap_bit &&
+                             block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors, BITMAP_OP_TEST_ALL_CLEAR))) {
+                               ic->sb->flags |= cpu_to_le32(SB_FLAG_RECALCULATING);
+                               ic->sb->recalc_sector = cpu_to_le64(0);
+                       }
+                       init_journal(ic, 0, ic->journal_sections, 0);
+                       replay_journal(ic);
+                       ic->sb->flags &= ~cpu_to_le32(SB_FLAG_DIRTY_BITMAP);
+               }
+               r = sync_rw_sb(ic, REQ_OP_WRITE, REQ_FUA);
+               if (unlikely(r))
+                       dm_integrity_io_error(ic, "writing superblock", r);
+       } else {
+               replay_journal(ic);
+               if (ic->mode == 'B') {
+                       int mode;
+                       ic->sb->flags |= cpu_to_le32(SB_FLAG_DIRTY_BITMAP);
+                       ic->sb->log2_blocks_per_bitmap_bit = ic->log2_blocks_per_bitmap_bit;
+                       r = sync_rw_sb(ic, REQ_OP_WRITE, REQ_FUA);
+                       if (unlikely(r))
+                               dm_integrity_io_error(ic, "writing superblock", r);
+
+                       mode = ic->recalculate_flag ? BITMAP_OP_SET : BITMAP_OP_CLEAR;
+                       block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors, mode);
+                       block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, mode);
+                       block_bitmap_op(ic, ic->may_write_bitmap, 0, ic->provided_data_sectors, mode);
+                       rw_journal_sectors(ic, REQ_OP_WRITE, REQ_FUA | REQ_SYNC, 0,
+                                          ic->n_bitmap_blocks * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT), NULL);
+               }
+       }
 
-       replay_journal(ic);
-
-       if (ic->recalc_wq && ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) {
+       DEBUG_print("testing recalc: %x\n", ic->sb->flags);
+       if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) {
                __u64 recalc_pos = le64_to_cpu(ic->sb->recalc_sector);
+               DEBUG_print("recalc pos: %lx / %lx\n", (long)recalc_pos, ic->provided_data_sectors);
                if (recalc_pos < ic->provided_data_sectors) {
                        queue_work(ic->recalc_wq, &ic->recalc_work);
                } else if (recalc_pos > ic->provided_data_sectors) {
@@ -2438,6 +2883,16 @@ static void dm_integrity_resume(struct dm_target *ti)
                        recalc_write_super(ic);
                }
        }
+
+       ic->reboot_notifier.notifier_call = dm_integrity_reboot;
+       ic->reboot_notifier.next = NULL;
+       ic->reboot_notifier.priority = INT_MAX - 1;     /* be notified after md and before hardware drivers */
+       WARN_ON(register_reboot_notifier(&ic->reboot_notifier));
+
+#if 0
+       /* set to 1 to stress test synchronous mode */
+       dm_integrity_enter_synchronous_mode(ic);
+#endif
 }
 
 static void dm_integrity_status(struct dm_target *ti, status_type_t type,
@@ -2462,10 +2917,14 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
                __u64 watermark_percentage = (__u64)(ic->journal_entries - ic->free_sectors_threshold) * 100;
                watermark_percentage += ic->journal_entries / 2;
                do_div(watermark_percentage, ic->journal_entries);
-               arg_count = 5;
+               arg_count = 3;
                arg_count += !!ic->meta_dev;
                arg_count += ic->sectors_per_block != 1;
                arg_count += !!(ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING));
+               arg_count += ic->mode == 'J';
+               arg_count += ic->mode == 'J';
+               arg_count += ic->mode == 'B';
+               arg_count += ic->mode == 'B';
                arg_count += !!ic->internal_hash_alg.alg_string;
                arg_count += !!ic->journal_crypt_alg.alg_string;
                arg_count += !!ic->journal_mac_alg.alg_string;
@@ -2475,13 +2934,19 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
                        DMEMIT(" meta_device:%s", ic->meta_dev->name);
                if (ic->sectors_per_block != 1)
                        DMEMIT(" block_size:%u", ic->sectors_per_block << SECTOR_SHIFT);
-               if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING))
+               if (ic->recalculate_flag)
                        DMEMIT(" recalculate");
                DMEMIT(" journal_sectors:%u", ic->initial_sectors - SB_SECTORS);
                DMEMIT(" interleave_sectors:%u", 1U << ic->sb->log2_interleave_sectors);
                DMEMIT(" buffer_sectors:%u", 1U << ic->log2_buffer_sectors);
-               DMEMIT(" journal_watermark:%u", (unsigned)watermark_percentage);
-               DMEMIT(" commit_time:%u", ic->autocommit_msec);
+               if (ic->mode == 'J') {
+                       DMEMIT(" journal_watermark:%u", (unsigned)watermark_percentage);
+                       DMEMIT(" commit_time:%u", ic->autocommit_msec);
+               }
+               if (ic->mode == 'B') {
+                       DMEMIT(" sectors_per_bit:%llu", (unsigned long long)ic->sectors_per_block << ic->log2_blocks_per_bitmap_bit);
+                       DMEMIT(" bitmap_flush_interval:%u", jiffies_to_msecs(ic->bitmap_flush_interval));
+               }
 
 #define EMIT_ALG(a, n)                                                 \
                do {                                                    \
@@ -2562,7 +3027,7 @@ static int calculate_device_limits(struct dm_integrity_c *ic)
                if (last_sector < ic->start || last_sector >= ic->meta_device_sectors)
                        return -EINVAL;
        } else {
-               __u64 meta_size = ic->provided_data_sectors * ic->tag_size;
+               __u64 meta_size = (ic->provided_data_sectors >> ic->sb->log2_sectors_per_block) * ic->tag_size;
                meta_size = (meta_size + ((1U << (ic->log2_buffer_sectors + SECTOR_SHIFT)) - 1))
                                >> (ic->log2_buffer_sectors + SECTOR_SHIFT);
                meta_size <<= ic->log2_buffer_sectors;
@@ -2659,37 +3124,37 @@ static void dm_integrity_set(struct dm_target *ti, struct dm_integrity_c *ic)
        blk_queue_max_integrity_segments(disk->queue, UINT_MAX);
 }
 
-static void dm_integrity_free_page_list(struct dm_integrity_c *ic, struct page_list *pl)
+static void dm_integrity_free_page_list(struct page_list *pl)
 {
        unsigned i;
 
        if (!pl)
                return;
-       for (i = 0; i < ic->journal_pages; i++)
-               if (pl[i].page)
-                       __free_page(pl[i].page);
+       for (i = 0; pl[i].page; i++)
+               __free_page(pl[i].page);
        kvfree(pl);
 }
 
-static struct page_list *dm_integrity_alloc_page_list(struct dm_integrity_c *ic)
+static struct page_list *dm_integrity_alloc_page_list(unsigned n_pages)
 {
-       size_t page_list_desc_size = ic->journal_pages * sizeof(struct page_list);
        struct page_list *pl;
        unsigned i;
 
-       pl = kvmalloc(page_list_desc_size, GFP_KERNEL | __GFP_ZERO);
+       pl = kvmalloc_array(n_pages + 1, sizeof(struct page_list), GFP_KERNEL | __GFP_ZERO);
        if (!pl)
                return NULL;
 
-       for (i = 0; i < ic->journal_pages; i++) {
+       for (i = 0; i < n_pages; i++) {
                pl[i].page = alloc_page(GFP_KERNEL);
                if (!pl[i].page) {
-                       dm_integrity_free_page_list(ic, pl);
+                       dm_integrity_free_page_list(pl);
                        return NULL;
                }
                if (i)
                        pl[i - 1].next = &pl[i];
        }
+       pl[i].page = NULL;
+       pl[i].next = NULL;
 
        return pl;
 }
@@ -2702,7 +3167,8 @@ static void dm_integrity_free_journal_scatterlist(struct dm_integrity_c *ic, str
        kvfree(sl);
 }
 
-static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_integrity_c *ic, struct page_list *pl)
+static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_integrity_c *ic,
+                                                                  struct page_list *pl)
 {
        struct scatterlist **sl;
        unsigned i;
@@ -2721,7 +3187,8 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int
                unsigned idx;
 
                page_list_location(ic, i, 0, &start_index, &start_offset);
-               page_list_location(ic, i, ic->journal_section_sectors - 1, &end_index, &end_offset);
+               page_list_location(ic, i, ic->journal_section_sectors - 1,
+                                  &end_index, &end_offset);
 
                n_pages = (end_index - start_index + 1);
 
@@ -2842,7 +3309,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
        }
        ic->journal_pages = journal_pages;
 
-       ic->journal = dm_integrity_alloc_page_list(ic);
+       ic->journal = dm_integrity_alloc_page_list(ic->journal_pages);
        if (!ic->journal) {
                *error = "Could not allocate memory for journal";
                r = -ENOMEM;
@@ -2874,7 +3341,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
                DEBUG_print("cipher %s, block size %u iv size %u\n",
                            ic->journal_crypt_alg.alg_string, blocksize, ivsize);
 
-               ic->journal_io = dm_integrity_alloc_page_list(ic);
+               ic->journal_io = dm_integrity_alloc_page_list(ic->journal_pages);
                if (!ic->journal_io) {
                        *error = "Could not allocate memory for journal io";
                        r = -ENOMEM;
@@ -2898,7 +3365,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
                                goto bad;
                        }
 
-                       ic->journal_xor = dm_integrity_alloc_page_list(ic);
+                       ic->journal_xor = dm_integrity_alloc_page_list(ic->journal_pages);
                        if (!ic->journal_xor) {
                                *error = "Could not allocate memory for journal xor";
                                r = -ENOMEM;
@@ -2922,7 +3389,8 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
                        sg_set_buf(&sg[i], &ic->commit_ids, sizeof ic->commit_ids);
                        memset(crypt_iv, 0x00, ivsize);
 
-                       skcipher_request_set_crypt(req, sg, sg, PAGE_SIZE * ic->journal_pages + sizeof ic->commit_ids, crypt_iv);
+                       skcipher_request_set_crypt(req, sg, sg,
+                                                  PAGE_SIZE * ic->journal_pages + sizeof ic->commit_ids, crypt_iv);
                        init_completion(&comp.comp);
                        comp.in_flight = (atomic_t)ATOMIC_INIT(1);
                        if (do_crypt(true, req, &comp))
@@ -3063,7 +3531,7 @@ bad:
  *     device
  *     offset from the start of the device
  *     tag size
- *     D - direct writes, J - journal writes, R - recovery mode
+ *     D - direct writes, J - journal writes, B - bitmap mode, R - recovery mode
  *     number of optional arguments
  *     optional arguments:
  *             journal_sectors
@@ -3071,10 +3539,14 @@ bad:
  *             buffer_sectors
  *             journal_watermark
  *             commit_time
+ *             meta_device
+ *             block_size
+ *             sectors_per_bit
+ *             bitmap_flush_interval
  *             internal_hash
  *             journal_crypt
  *             journal_mac
- *             block_size
+ *             recalculate
  */
 static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
 {
@@ -3087,10 +3559,13 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
                {0, 9, "Invalid number of feature args"},
        };
        unsigned journal_sectors, interleave_sectors, buffer_sectors, journal_watermark, sync_msec;
-       bool recalculate;
        bool should_write_sb;
        __u64 threshold;
        unsigned long long start;
+       __s8 log2_sectors_per_bitmap_bit = -1;
+       __s8 log2_blocks_per_bitmap_bit;
+       __u64 bits_in_journal;
+       __u64 n_bitmap_bits;
 
 #define DIRECT_ARGUMENTS       4
 
@@ -3114,6 +3589,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
        init_waitqueue_head(&ic->copy_to_journal_wait);
        init_completion(&ic->crypto_backoff);
        atomic64_set(&ic->number_of_mismatches, 0);
+       ic->bitmap_flush_interval = BITMAP_FLUSH_INTERVAL;
 
        r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &ic->dev);
        if (r) {
@@ -3136,10 +3612,11 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
                }
        }
 
-       if (!strcmp(argv[3], "J") || !strcmp(argv[3], "D") || !strcmp(argv[3], "R"))
+       if (!strcmp(argv[3], "J") || !strcmp(argv[3], "B") ||
+           !strcmp(argv[3], "D") || !strcmp(argv[3], "R")) {
                ic->mode = argv[3][0];
-       else {
-               ti->error = "Invalid mode (expecting J, D, R)";
+       else {
+               ti->error = "Invalid mode (expecting J, B, D, R)";
                r = -EINVAL;
                goto bad;
        }
@@ -3149,7 +3626,6 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
        buffer_sectors = DEFAULT_BUFFER_SECTORS;
        journal_watermark = DEFAULT_JOURNAL_WATERMARK;
        sync_msec = DEFAULT_SYNC_MSEC;
-       recalculate = false;
        ic->sectors_per_block = 1;
 
        as.argc = argc - DIRECT_ARGUMENTS;
@@ -3161,6 +3637,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
        while (extra_args--) {
                const char *opt_string;
                unsigned val;
+               unsigned long long llval;
                opt_string = dm_shift_arg(&as);
                if (!opt_string) {
                        r = -EINVAL;
@@ -3182,7 +3659,8 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
                                dm_put_device(ti, ic->meta_dev);
                                ic->meta_dev = NULL;
                        }
-                       r = dm_get_device(ti, strchr(opt_string, ':') + 1, dm_table_get_mode(ti->table), &ic->meta_dev);
+                       r = dm_get_device(ti, strchr(opt_string, ':') + 1,
+                                         dm_table_get_mode(ti->table), &ic->meta_dev);
                        if (r) {
                                ti->error = "Device lookup failed";
                                goto bad;
@@ -3196,6 +3674,14 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
                                goto bad;
                        }
                        ic->sectors_per_block = val >> SECTOR_SHIFT;
+               } else if (sscanf(opt_string, "sectors_per_bit:%llu%c", &llval, &dummy) == 1) {
+                       log2_sectors_per_bitmap_bit = !llval ? 0 : __ilog2_u64(llval);
+               } else if (sscanf(opt_string, "bitmap_flush_interval:%u%c", &val, &dummy) == 1) {
+                       if (val >= (uint64_t)UINT_MAX * 1000 / HZ) {
+                               r = -EINVAL;
+                               ti->error = "Invalid bitmap_flush_interval argument";
+                       }
+                       ic->bitmap_flush_interval = msecs_to_jiffies(val);
                } else if (!strncmp(opt_string, "internal_hash:", strlen("internal_hash:"))) {
                        r = get_alg_and_key(opt_string, &ic->internal_hash_alg, &ti->error,
                                            "Invalid internal_hash argument");
@@ -3212,7 +3698,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
                        if (r)
                                goto bad;
                } else if (!strcmp(opt_string, "recalculate")) {
-                       recalculate = true;
+                       ic->recalculate_flag = true;
                } else {
                        r = -EINVAL;
                        ti->error = "Invalid argument";
@@ -3228,7 +3714,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        if (!journal_sectors) {
                journal_sectors = min((sector_t)DEFAULT_MAX_JOURNAL_SECTORS,
-                       ic->data_device_sectors >> DEFAULT_JOURNAL_SIZE_FACTOR);
+                                     ic->data_device_sectors >> DEFAULT_JOURNAL_SIZE_FACTOR);
        }
 
        if (!buffer_sectors)
@@ -3263,6 +3749,12 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
        else
                ic->log2_tag_size = -1;
 
+       if (ic->mode == 'B' && !ic->internal_hash) {
+               r = -EINVAL;
+               ti->error = "Bitmap mode can be only used with internal hash";
+               goto bad;
+       }
+
        ic->autocommit_jiffies = msecs_to_jiffies(sync_msec);
        ic->autocommit_msec = sync_msec;
        timer_setup(&ic->autocommit_timer, autocommit_fn, 0);
@@ -3308,7 +3800,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
        }
        INIT_WORK(&ic->commit_work, integrity_commit);
 
-       if (ic->mode == 'J') {
+       if (ic->mode == 'J' || ic->mode == 'B') {
                ic->writer_wq = alloc_workqueue("dm-integrity-writer", WQ_MEM_RECLAIM, 1);
                if (!ic->writer_wq) {
                        ti->error = "Cannot allocate workqueue";
@@ -3349,7 +3841,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
                        should_write_sb = true;
        }
 
-       if (!ic->sb->version || ic->sb->version > SB_VERSION_2) {
+       if (!ic->sb->version || ic->sb->version > SB_VERSION_3) {
                r = -EINVAL;
                ti->error = "Unknown version";
                goto bad;
@@ -3409,6 +3901,27 @@ try_smaller_buffer:
                ti->error = "The device is too small";
                goto bad;
        }
+
+       if (log2_sectors_per_bitmap_bit < 0)
+               log2_sectors_per_bitmap_bit = __fls(DEFAULT_SECTORS_PER_BITMAP_BIT);
+       if (log2_sectors_per_bitmap_bit < ic->sb->log2_sectors_per_block)
+               log2_sectors_per_bitmap_bit = ic->sb->log2_sectors_per_block;
+
+       bits_in_journal = ((__u64)ic->journal_section_sectors * ic->journal_sections) << (SECTOR_SHIFT + 3);
+       if (bits_in_journal > UINT_MAX)
+               bits_in_journal = UINT_MAX;
+       while (bits_in_journal < (ic->provided_data_sectors + ((sector_t)1 << log2_sectors_per_bitmap_bit) - 1) >> log2_sectors_per_bitmap_bit)
+               log2_sectors_per_bitmap_bit++;
+
+       log2_blocks_per_bitmap_bit = log2_sectors_per_bitmap_bit - ic->sb->log2_sectors_per_block;
+       ic->log2_blocks_per_bitmap_bit = log2_blocks_per_bitmap_bit;
+       if (should_write_sb) {
+               ic->sb->log2_blocks_per_bitmap_bit = log2_blocks_per_bitmap_bit;
+       }
+       n_bitmap_bits = ((ic->provided_data_sectors >> ic->sb->log2_sectors_per_block)
+                               + (((sector_t)1 << log2_blocks_per_bitmap_bit) - 1)) >> log2_blocks_per_bitmap_bit;
+       ic->n_bitmap_blocks = DIV_ROUND_UP(n_bitmap_bits, BITMAP_BLOCK_SIZE * 8);
+
        if (!ic->meta_dev)
                ic->log2_buffer_sectors = min(ic->log2_buffer_sectors, (__u8)__ffs(ic->metadata_run));
 
@@ -3433,25 +3946,21 @@ try_smaller_buffer:
        DEBUG_print("   journal_sections %u\n", (unsigned)le32_to_cpu(ic->sb->journal_sections));
        DEBUG_print("   journal_entries %u\n", ic->journal_entries);
        DEBUG_print("   log2_interleave_sectors %d\n", ic->sb->log2_interleave_sectors);
-       DEBUG_print("   device_sectors 0x%llx\n", (unsigned long long)ic->device_sectors);
+       DEBUG_print("   data_device_sectors 0x%llx\n", i_size_read(ic->dev->bdev->bd_inode) >> SECTOR_SHIFT);
        DEBUG_print("   initial_sectors 0x%x\n", ic->initial_sectors);
        DEBUG_print("   metadata_run 0x%x\n", ic->metadata_run);
        DEBUG_print("   log2_metadata_run %d\n", ic->log2_metadata_run);
        DEBUG_print("   provided_data_sectors 0x%llx (%llu)\n", (unsigned long long)ic->provided_data_sectors,
                    (unsigned long long)ic->provided_data_sectors);
        DEBUG_print("   log2_buffer_sectors %u\n", ic->log2_buffer_sectors);
+       DEBUG_print("   bits_in_journal %llu\n", (unsigned long long)bits_in_journal);
 
-       if (recalculate && !(ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING))) {
+       if (ic->recalculate_flag && !(ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING))) {
                ic->sb->flags |= cpu_to_le32(SB_FLAG_RECALCULATING);
                ic->sb->recalc_sector = cpu_to_le64(0);
        }
 
-       if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) {
-               if (!ic->internal_hash) {
-                       r = -EINVAL;
-                       ti->error = "Recalculate is only valid with internal hash";
-                       goto bad;
-               }
+       if (ic->internal_hash) {
                ic->recalc_wq = alloc_workqueue("dm-integrity-recalc", WQ_MEM_RECLAIM, 1);
                if (!ic->recalc_wq ) {
                        ti->error = "Cannot allocate workqueue";
@@ -3488,6 +3997,45 @@ try_smaller_buffer:
                r = create_journal(ic, &ti->error);
                if (r)
                        goto bad;
+
+       }
+
+       if (ic->mode == 'B') {
+               unsigned i;
+               unsigned n_bitmap_pages = DIV_ROUND_UP(ic->n_bitmap_blocks, PAGE_SIZE / BITMAP_BLOCK_SIZE);
+
+               ic->recalc_bitmap = dm_integrity_alloc_page_list(n_bitmap_pages);
+               if (!ic->recalc_bitmap) {
+                       r = -ENOMEM;
+                       goto bad;
+               }
+               ic->may_write_bitmap = dm_integrity_alloc_page_list(n_bitmap_pages);
+               if (!ic->may_write_bitmap) {
+                       r = -ENOMEM;
+                       goto bad;
+               }
+               ic->bbs = kvmalloc_array(ic->n_bitmap_blocks, sizeof(struct bitmap_block_status), GFP_KERNEL);
+               if (!ic->bbs) {
+                       r = -ENOMEM;
+                       goto bad;
+               }
+               INIT_DELAYED_WORK(&ic->bitmap_flush_work, bitmap_flush_work);
+               for (i = 0; i < ic->n_bitmap_blocks; i++) {
+                       struct bitmap_block_status *bbs = &ic->bbs[i];
+                       unsigned sector, pl_index, pl_offset;
+
+                       INIT_WORK(&bbs->work, bitmap_block_work);
+                       bbs->ic = ic;
+                       bbs->idx = i;
+                       bio_list_init(&bbs->bio_queue);
+                       spin_lock_init(&bbs->bio_queue_lock);
+
+                       sector = i * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT);
+                       pl_index = sector >> (PAGE_SHIFT - SECTOR_SHIFT);
+                       pl_offset = (sector << SECTOR_SHIFT) & (PAGE_SIZE - 1);
+
+                       bbs->bitmap = lowmem_page_address(ic->journal[pl_index].page) + pl_offset;
+               }
        }
 
        if (should_write_sb) {
@@ -3512,6 +4060,17 @@ try_smaller_buffer:
                if (r)
                        goto bad;
        }
+       if (ic->mode == 'B') {
+               unsigned max_io_len = ((sector_t)ic->sectors_per_block << ic->log2_blocks_per_bitmap_bit) * (BITMAP_BLOCK_SIZE * 8);
+               if (!max_io_len)
+                       max_io_len = 1U << 31;
+               DEBUG_print("max_io_len: old %u, new %u\n", ti->max_io_len, max_io_len);
+               if (!ti->max_io_len || ti->max_io_len > max_io_len) {
+                       r = dm_set_target_max_io_len(ti, max_io_len);
+                       if (r)
+                               goto bad;
+               }
+       }
 
        if (!ic->internal_hash)
                dm_integrity_set(ti, ic);
@@ -3520,6 +4079,7 @@ try_smaller_buffer:
        ti->flush_supported = true;
 
        return 0;
+
 bad:
        dm_integrity_dtr(ti);
        return r;
@@ -3542,10 +4102,9 @@ static void dm_integrity_dtr(struct dm_target *ti)
                destroy_workqueue(ic->writer_wq);
        if (ic->recalc_wq)
                destroy_workqueue(ic->recalc_wq);
-       if (ic->recalc_buffer)
-               vfree(ic->recalc_buffer);
-       if (ic->recalc_tags)
-               kvfree(ic->recalc_tags);
+       vfree(ic->recalc_buffer);
+       kvfree(ic->recalc_tags);
+       kvfree(ic->bbs);
        if (ic->bufio)
                dm_bufio_client_destroy(ic->bufio);
        mempool_exit(&ic->journal_io_mempool);
@@ -3555,9 +4114,11 @@ static void dm_integrity_dtr(struct dm_target *ti)
                dm_put_device(ti, ic->dev);
        if (ic->meta_dev)
                dm_put_device(ti, ic->meta_dev);
-       dm_integrity_free_page_list(ic, ic->journal);
-       dm_integrity_free_page_list(ic, ic->journal_io);
-       dm_integrity_free_page_list(ic, ic->journal_xor);
+       dm_integrity_free_page_list(ic->journal);
+       dm_integrity_free_page_list(ic->journal_io);
+       dm_integrity_free_page_list(ic->journal_xor);
+       dm_integrity_free_page_list(ic->recalc_bitmap);
+       dm_integrity_free_page_list(ic->may_write_bitmap);
        if (ic->journal_scatterlist)
                dm_integrity_free_journal_scatterlist(ic, ic->journal_scatterlist);
        if (ic->journal_io_scatterlist)
@@ -3595,7 +4156,7 @@ static void dm_integrity_dtr(struct dm_target *ti)
 
 static struct target_type integrity_target = {
        .name                   = "integrity",
-       .version                = {1, 2, 0},
+       .version                = {1, 3, 0},
        .module                 = THIS_MODULE,
        .features               = DM_TARGET_SINGLETON | DM_TARGET_INTEGRITY,
        .ctr                    = dm_integrity_ctr,
index c740153..1e03bc8 100644 (file)
@@ -2069,7 +2069,7 @@ int __init dm_early_create(struct dm_ioctl *dmi,
        /* alloc table */
        r = dm_table_create(&t, get_mode(dmi), dmi->target_count, md);
        if (r)
-               goto err_destroy_dm;
+               goto err_hash_remove;
 
        /* add targets */
        for (i = 0; i < dmi->target_count; i++) {
@@ -2116,6 +2116,10 @@ int __init dm_early_create(struct dm_ioctl *dmi,
 
 err_destroy_table:
        dm_table_destroy(t);
+err_hash_remove:
+       (void) __hash_remove(__get_name_cell(dmi->name));
+       /* release reference from __get_name_cell */
+       dm_put(md);
 err_destroy_dm:
        dm_put(md);
        dm_destroy(md);
index 2ee5e35..dbcc1e4 100644 (file)
@@ -544,8 +544,23 @@ static int multipath_clone_and_map(struct dm_target *ti, struct request *rq,
        return DM_MAPIO_REMAPPED;
 }
 
-static void multipath_release_clone(struct request *clone)
+static void multipath_release_clone(struct request *clone,
+                                   union map_info *map_context)
 {
+       if (unlikely(map_context)) {
+               /*
+                * non-NULL map_context means caller is still map
+                * method; must undo multipath_clone_and_map()
+                */
+               struct dm_mpath_io *mpio = get_mpio(map_context);
+               struct pgpath *pgpath = mpio->pgpath;
+
+               if (pgpath && pgpath->pg->ps.type->end_io)
+                       pgpath->pg->ps.type->end_io(&pgpath->pg->ps,
+                                                   &pgpath->path,
+                                                   mpio->nr_bytes);
+       }
+
        blk_put_request(clone);
 }
 
@@ -882,6 +897,7 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps
        if (attached_handler_name || m->hw_handler_name) {
                INIT_DELAYED_WORK(&p->activate_path, activate_path_work);
                r = setup_scsi_dh(p->path.dev->bdev, m, &attached_handler_name, &ti->error);
+               kfree(attached_handler_name);
                if (r) {
                        dm_put_device(ti, p->path.dev);
                        goto bad;
@@ -896,7 +912,6 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps
 
        return p;
  bad:
-       kfree(attached_handler_name);
        free_pgpath(p);
        return ERR_PTR(r);
 }
index b66745b..5f7063f 100644 (file)
@@ -168,7 +168,7 @@ static void dm_end_request(struct request *clone, blk_status_t error)
        struct request *rq = tio->orig;
 
        blk_rq_unprep_clone(clone);
-       tio->ti->type->release_clone_rq(clone);
+       tio->ti->type->release_clone_rq(clone, NULL);
 
        rq_end_stats(md, rq);
        blk_mq_end_request(rq, error);
@@ -201,7 +201,7 @@ static void dm_requeue_original_request(struct dm_rq_target_io *tio, bool delay_
        rq_end_stats(md, rq);
        if (tio->clone) {
                blk_rq_unprep_clone(tio->clone);
-               tio->ti->type->release_clone_rq(tio->clone);
+               tio->ti->type->release_clone_rq(tio->clone, NULL);
        }
 
        dm_mq_delay_requeue_request(rq, delay_ms);
@@ -398,7 +398,7 @@ static int map_request(struct dm_rq_target_io *tio)
        case DM_MAPIO_REMAPPED:
                if (setup_clone(clone, rq, tio, GFP_ATOMIC)) {
                        /* -ENOMEM */
-                       ti->type->release_clone_rq(clone);
+                       ti->type->release_clone_rq(clone, &tio->info);
                        return DM_MAPIO_REQUEUE;
                }
 
@@ -408,7 +408,7 @@ static int map_request(struct dm_rq_target_io *tio)
                ret = dm_dispatch_clone_request(clone, rq);
                if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE) {
                        blk_rq_unprep_clone(clone);
-                       tio->ti->type->release_clone_rq(clone);
+                       tio->ti->type->release_clone_rq(clone, &tio->info);
                        tio->clone = NULL;
                        return DM_MAPIO_REQUEUE;
                }
index a168963..3107f2b 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/kdev_t.h>
 #include <linux/list.h>
+#include <linux/list_bl.h>
 #include <linux/mempool.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -44,11 +45,11 @@ static const char dm_snapshot_merge_target_name[] = "snapshot-merge";
 struct dm_exception_table {
        uint32_t hash_mask;
        unsigned hash_shift;
-       struct list_head *table;
+       struct hlist_bl_head *table;
 };
 
 struct dm_snapshot {
-       struct mutex lock;
+       struct rw_semaphore lock;
 
        struct dm_dev *origin;
        struct dm_dev *cow;
@@ -76,7 +77,9 @@ struct dm_snapshot {
 
        atomic_t pending_exceptions_count;
 
-       /* Protected by "lock" */
+       spinlock_t pe_allocation_lock;
+
+       /* Protected by "pe_allocation_lock" */
        sector_t exception_start_sequence;
 
        /* Protected by kcopyd single-threaded callback */
@@ -457,9 +460,9 @@ static int __find_snapshots_sharing_cow(struct dm_snapshot *snap,
                if (!bdev_equal(s->cow->bdev, snap->cow->bdev))
                        continue;
 
-               mutex_lock(&s->lock);
+               down_read(&s->lock);
                active = s->active;
-               mutex_unlock(&s->lock);
+               up_read(&s->lock);
 
                if (active) {
                        if (snap_src)
@@ -618,6 +621,36 @@ static void unregister_snapshot(struct dm_snapshot *s)
  * The lowest hash_shift bits of the chunk number are ignored, allowing
  * some consecutive chunks to be grouped together.
  */
+static uint32_t exception_hash(struct dm_exception_table *et, chunk_t chunk);
+
+/* Lock to protect access to the completed and pending exception hash tables. */
+struct dm_exception_table_lock {
+       struct hlist_bl_head *complete_slot;
+       struct hlist_bl_head *pending_slot;
+};
+
+static void dm_exception_table_lock_init(struct dm_snapshot *s, chunk_t chunk,
+                                        struct dm_exception_table_lock *lock)
+{
+       struct dm_exception_table *complete = &s->complete;
+       struct dm_exception_table *pending = &s->pending;
+
+       lock->complete_slot = &complete->table[exception_hash(complete, chunk)];
+       lock->pending_slot = &pending->table[exception_hash(pending, chunk)];
+}
+
+static void dm_exception_table_lock(struct dm_exception_table_lock *lock)
+{
+       hlist_bl_lock(lock->complete_slot);
+       hlist_bl_lock(lock->pending_slot);
+}
+
+static void dm_exception_table_unlock(struct dm_exception_table_lock *lock)
+{
+       hlist_bl_unlock(lock->pending_slot);
+       hlist_bl_unlock(lock->complete_slot);
+}
+
 static int dm_exception_table_init(struct dm_exception_table *et,
                                   uint32_t size, unsigned hash_shift)
 {
@@ -625,12 +658,12 @@ static int dm_exception_table_init(struct dm_exception_table *et,
 
        et->hash_shift = hash_shift;
        et->hash_mask = size - 1;
-       et->table = dm_vcalloc(size, sizeof(struct list_head));
+       et->table = dm_vcalloc(size, sizeof(struct hlist_bl_head));
        if (!et->table)
                return -ENOMEM;
 
        for (i = 0; i < size; i++)
-               INIT_LIST_HEAD(et->table + i);
+               INIT_HLIST_BL_HEAD(et->table + i);
 
        return 0;
 }
@@ -638,15 +671,16 @@ static int dm_exception_table_init(struct dm_exception_table *et,
 static void dm_exception_table_exit(struct dm_exception_table *et,
                                    struct kmem_cache *mem)
 {
-       struct list_head *slot;
-       struct dm_exception *ex, *next;
+       struct hlist_bl_head *slot;
+       struct dm_exception *ex;
+       struct hlist_bl_node *pos, *n;
        int i, size;
 
        size = et->hash_mask + 1;
        for (i = 0; i < size; i++) {
                slot = et->table + i;
 
-               list_for_each_entry_safe (ex, next, slot, hash_list)
+               hlist_bl_for_each_entry_safe(ex, pos, n, slot, hash_list)
                        kmem_cache_free(mem, ex);
        }
 
@@ -660,7 +694,7 @@ static uint32_t exception_hash(struct dm_exception_table *et, chunk_t chunk)
 
 static void dm_remove_exception(struct dm_exception *e)
 {
-       list_del(&e->hash_list);
+       hlist_bl_del(&e->hash_list);
 }
 
 /*
@@ -670,11 +704,12 @@ static void dm_remove_exception(struct dm_exception *e)
 static struct dm_exception *dm_lookup_exception(struct dm_exception_table *et,
                                                chunk_t chunk)
 {
-       struct list_head *slot;
+       struct hlist_bl_head *slot;
+       struct hlist_bl_node *pos;
        struct dm_exception *e;
 
        slot = &et->table[exception_hash(et, chunk)];
-       list_for_each_entry (e, slot, hash_list)
+       hlist_bl_for_each_entry(e, pos, slot, hash_list)
                if (chunk >= e->old_chunk &&
                    chunk <= e->old_chunk + dm_consecutive_chunk_count(e))
                        return e;
@@ -721,7 +756,8 @@ static void free_pending_exception(struct dm_snap_pending_exception *pe)
 static void dm_insert_exception(struct dm_exception_table *eh,
                                struct dm_exception *new_e)
 {
-       struct list_head *l;
+       struct hlist_bl_head *l;
+       struct hlist_bl_node *pos;
        struct dm_exception *e = NULL;
 
        l = &eh->table[exception_hash(eh, new_e->old_chunk)];
@@ -731,7 +767,7 @@ static void dm_insert_exception(struct dm_exception_table *eh,
                goto out;
 
        /* List is ordered by old_chunk */
-       list_for_each_entry_reverse(e, l, hash_list) {
+       hlist_bl_for_each_entry(e, pos, l, hash_list) {
                /* Insert after an existing chunk? */
                if (new_e->old_chunk == (e->old_chunk +
                                         dm_consecutive_chunk_count(e) + 1) &&
@@ -752,12 +788,24 @@ static void dm_insert_exception(struct dm_exception_table *eh,
                        return;
                }
 
-               if (new_e->old_chunk > e->old_chunk)
+               if (new_e->old_chunk < e->old_chunk)
                        break;
        }
 
 out:
-       list_add(&new_e->hash_list, e ? &e->hash_list : l);
+       if (!e) {
+               /*
+                * Either the table doesn't support consecutive chunks or slot
+                * l is empty.
+                */
+               hlist_bl_add_head(&new_e->hash_list, l);
+       } else if (new_e->old_chunk < e->old_chunk) {
+               /* Add before an existing exception */
+               hlist_bl_add_before(&new_e->hash_list, &e->hash_list);
+       } else {
+               /* Add to l's tail: e is the last exception in this slot */
+               hlist_bl_add_behind(&new_e->hash_list, &e->hash_list);
+       }
 }
 
 /*
@@ -766,6 +814,7 @@ out:
  */
 static int dm_add_exception(void *context, chunk_t old, chunk_t new)
 {
+       struct dm_exception_table_lock lock;
        struct dm_snapshot *s = context;
        struct dm_exception *e;
 
@@ -778,7 +827,17 @@ static int dm_add_exception(void *context, chunk_t old, chunk_t new)
        /* Consecutive_count is implicitly initialised to zero */
        e->new_chunk = new;
 
+       /*
+        * Although there is no need to lock access to the exception tables
+        * here, if we don't then hlist_bl_add_head(), called by
+        * dm_insert_exception(), will complain about accessing the
+        * corresponding list without locking it first.
+        */
+       dm_exception_table_lock_init(s, old, &lock);
+
+       dm_exception_table_lock(&lock);
        dm_insert_exception(&s->complete, e);
+       dm_exception_table_unlock(&lock);
 
        return 0;
 }
@@ -807,7 +866,7 @@ static int calc_max_buckets(void)
 {
        /* use a fixed size of 2MB */
        unsigned long mem = 2 * 1024 * 1024;
-       mem /= sizeof(struct list_head);
+       mem /= sizeof(struct hlist_bl_head);
 
        return mem;
 }
@@ -927,7 +986,7 @@ static int remove_single_exception_chunk(struct dm_snapshot *s)
        int r;
        chunk_t old_chunk = s->first_merging_chunk + s->num_merging_chunks - 1;
 
-       mutex_lock(&s->lock);
+       down_write(&s->lock);
 
        /*
         * Process chunks (and associated exceptions) in reverse order
@@ -942,7 +1001,7 @@ static int remove_single_exception_chunk(struct dm_snapshot *s)
        b = __release_queued_bios_after_merge(s);
 
 out:
-       mutex_unlock(&s->lock);
+       up_write(&s->lock);
        if (b)
                flush_bios(b);
 
@@ -1001,9 +1060,9 @@ static void snapshot_merge_next_chunks(struct dm_snapshot *s)
                if (linear_chunks < 0) {
                        DMERR("Read error in exception store: "
                              "shutting down merge");
-                       mutex_lock(&s->lock);
+                       down_write(&s->lock);
                        s->merge_failed = 1;
-                       mutex_unlock(&s->lock);
+                       up_write(&s->lock);
                }
                goto shut;
        }
@@ -1044,10 +1103,10 @@ static void snapshot_merge_next_chunks(struct dm_snapshot *s)
                previous_count = read_pending_exceptions_done_count();
        }
 
-       mutex_lock(&s->lock);
+       down_write(&s->lock);
        s->first_merging_chunk = old_chunk;
        s->num_merging_chunks = linear_chunks;
-       mutex_unlock(&s->lock);
+       up_write(&s->lock);
 
        /* Wait until writes to all 'linear_chunks' drain */
        for (i = 0; i < linear_chunks; i++)
@@ -1089,10 +1148,10 @@ static void merge_callback(int read_err, unsigned long write_err, void *context)
        return;
 
 shut:
-       mutex_lock(&s->lock);
+       down_write(&s->lock);
        s->merge_failed = 1;
        b = __release_queued_bios_after_merge(s);
-       mutex_unlock(&s->lock);
+       up_write(&s->lock);
        error_bios(b);
 
        merge_shutdown(s);
@@ -1188,10 +1247,11 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        s->snapshot_overflowed = 0;
        s->active = 0;
        atomic_set(&s->pending_exceptions_count, 0);
+       spin_lock_init(&s->pe_allocation_lock);
        s->exception_start_sequence = 0;
        s->exception_complete_sequence = 0;
        s->out_of_order_tree = RB_ROOT;
-       mutex_init(&s->lock);
+       init_rwsem(&s->lock);
        INIT_LIST_HEAD(&s->list);
        spin_lock_init(&s->pe_lock);
        s->state_bits = 0;
@@ -1357,9 +1417,9 @@ static void snapshot_dtr(struct dm_target *ti)
        /* Check whether exception handover must be cancelled */
        (void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL);
        if (snap_src && snap_dest && (s == snap_src)) {
-               mutex_lock(&snap_dest->lock);
+               down_write(&snap_dest->lock);
                snap_dest->valid = 0;
-               mutex_unlock(&snap_dest->lock);
+               up_write(&snap_dest->lock);
                DMERR("Cancelling snapshot handover.");
        }
        up_read(&_origins_lock);
@@ -1390,8 +1450,6 @@ static void snapshot_dtr(struct dm_target *ti)
 
        dm_exception_store_destroy(s->store);
 
-       mutex_destroy(&s->lock);
-
        dm_put_device(ti, s->cow);
 
        dm_put_device(ti, s->origin);
@@ -1467,6 +1525,13 @@ static void __invalidate_snapshot(struct dm_snapshot *s, int err)
        dm_table_event(s->ti->table);
 }
 
+static void invalidate_snapshot(struct dm_snapshot *s, int err)
+{
+       down_write(&s->lock);
+       __invalidate_snapshot(s, err);
+       up_write(&s->lock);
+}
+
 static void pending_complete(void *context, int success)
 {
        struct dm_snap_pending_exception *pe = context;
@@ -1475,43 +1540,63 @@ static void pending_complete(void *context, int success)
        struct bio *origin_bios = NULL;
        struct bio *snapshot_bios = NULL;
        struct bio *full_bio = NULL;
+       struct dm_exception_table_lock lock;
        int error = 0;
 
+       dm_exception_table_lock_init(s, pe->e.old_chunk, &lock);
+
        if (!success) {
                /* Read/write error - snapshot is unusable */
-               mutex_lock(&s->lock);
-               __invalidate_snapshot(s, -EIO);
+               invalidate_snapshot(s, -EIO);
                error = 1;
+
+               dm_exception_table_lock(&lock);
                goto out;
        }
 
        e = alloc_completed_exception(GFP_NOIO);
        if (!e) {
-               mutex_lock(&s->lock);
-               __invalidate_snapshot(s, -ENOMEM);
+               invalidate_snapshot(s, -ENOMEM);
                error = 1;
+
+               dm_exception_table_lock(&lock);
                goto out;
        }
        *e = pe->e;
 
-       mutex_lock(&s->lock);
+       down_read(&s->lock);
+       dm_exception_table_lock(&lock);
        if (!s->valid) {
+               up_read(&s->lock);
                free_completed_exception(e);
                error = 1;
+
                goto out;
        }
 
-       /* Check for conflicting reads */
-       __check_for_conflicting_io(s, pe->e.old_chunk);
-
        /*
-        * Add a proper exception, and remove the
-        * in-flight exception from the list.
+        * Add a proper exception. After inserting the completed exception all
+        * subsequent snapshot reads to this chunk will be redirected to the
+        * COW device.  This ensures that we do not starve. Moreover, as long
+        * as the pending exception exists, neither origin writes nor snapshot
+        * merging can overwrite the chunk in origin.
         */
        dm_insert_exception(&s->complete, e);
+       up_read(&s->lock);
+
+       /* Wait for conflicting reads to drain */
+       if (__chunk_is_tracked(s, pe->e.old_chunk)) {
+               dm_exception_table_unlock(&lock);
+               __check_for_conflicting_io(s, pe->e.old_chunk);
+               dm_exception_table_lock(&lock);
+       }
 
 out:
+       /* Remove the in-flight exception from the list */
        dm_remove_exception(&pe->e);
+
+       dm_exception_table_unlock(&lock);
+
        snapshot_bios = bio_list_get(&pe->snapshot_bios);
        origin_bios = bio_list_get(&pe->origin_bios);
        full_bio = pe->full_bio;
@@ -1519,8 +1604,6 @@ out:
                full_bio->bi_end_io = pe->full_bio_end_io;
        increment_pending_exceptions_done_count();
 
-       mutex_unlock(&s->lock);
-
        /* Submit any pending write bios */
        if (error) {
                if (full_bio)
@@ -1660,43 +1743,59 @@ __lookup_pending_exception(struct dm_snapshot *s, chunk_t chunk)
 }
 
 /*
- * Looks to see if this snapshot already has a pending exception
- * for this chunk, otherwise it allocates a new one and inserts
- * it into the pending table.
+ * Inserts a pending exception into the pending table.
  *
- * NOTE: a write lock must be held on snap->lock before calling
- * this.
+ * NOTE: a write lock must be held on the chunk's pending exception table slot
+ * before calling this.
  */
 static struct dm_snap_pending_exception *
-__find_pending_exception(struct dm_snapshot *s,
-                        struct dm_snap_pending_exception *pe, chunk_t chunk)
+__insert_pending_exception(struct dm_snapshot *s,
+                          struct dm_snap_pending_exception *pe, chunk_t chunk)
 {
-       struct dm_snap_pending_exception *pe2;
-
-       pe2 = __lookup_pending_exception(s, chunk);
-       if (pe2) {
-               free_pending_exception(pe);
-               return pe2;
-       }
-
        pe->e.old_chunk = chunk;
        bio_list_init(&pe->origin_bios);
        bio_list_init(&pe->snapshot_bios);
        pe->started = 0;
        pe->full_bio = NULL;
 
+       spin_lock(&s->pe_allocation_lock);
        if (s->store->type->prepare_exception(s->store, &pe->e)) {
+               spin_unlock(&s->pe_allocation_lock);
                free_pending_exception(pe);
                return NULL;
        }
 
        pe->exception_sequence = s->exception_start_sequence++;
+       spin_unlock(&s->pe_allocation_lock);
 
        dm_insert_exception(&s->pending, &pe->e);
 
        return pe;
 }
 
+/*
+ * Looks to see if this snapshot already has a pending exception
+ * for this chunk, otherwise it allocates a new one and inserts
+ * it into the pending table.
+ *
+ * NOTE: a write lock must be held on the chunk's pending exception table slot
+ * before calling this.
+ */
+static struct dm_snap_pending_exception *
+__find_pending_exception(struct dm_snapshot *s,
+                        struct dm_snap_pending_exception *pe, chunk_t chunk)
+{
+       struct dm_snap_pending_exception *pe2;
+
+       pe2 = __lookup_pending_exception(s, chunk);
+       if (pe2) {
+               free_pending_exception(pe);
+               return pe2;
+       }
+
+       return __insert_pending_exception(s, pe, chunk);
+}
+
 static void remap_exception(struct dm_snapshot *s, struct dm_exception *e,
                            struct bio *bio, chunk_t chunk)
 {
@@ -1714,6 +1813,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
        int r = DM_MAPIO_REMAPPED;
        chunk_t chunk;
        struct dm_snap_pending_exception *pe = NULL;
+       struct dm_exception_table_lock lock;
 
        init_tracked_chunk(bio);
 
@@ -1723,13 +1823,15 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
        }
 
        chunk = sector_to_chunk(s->store, bio->bi_iter.bi_sector);
+       dm_exception_table_lock_init(s, chunk, &lock);
 
        /* Full snapshots are not usable */
        /* To get here the table must be live so s->active is always set. */
        if (!s->valid)
                return DM_MAPIO_KILL;
 
-       mutex_lock(&s->lock);
+       down_read(&s->lock);
+       dm_exception_table_lock(&lock);
 
        if (!s->valid || (unlikely(s->snapshot_overflowed) &&
            bio_data_dir(bio) == WRITE)) {
@@ -1752,15 +1854,9 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
        if (bio_data_dir(bio) == WRITE) {
                pe = __lookup_pending_exception(s, chunk);
                if (!pe) {
-                       mutex_unlock(&s->lock);
+                       dm_exception_table_unlock(&lock);
                        pe = alloc_pending_exception(s);
-                       mutex_lock(&s->lock);
-
-                       if (!s->valid || s->snapshot_overflowed) {
-                               free_pending_exception(pe);
-                               r = DM_MAPIO_KILL;
-                               goto out_unlock;
-                       }
+                       dm_exception_table_lock(&lock);
 
                        e = dm_lookup_exception(&s->complete, chunk);
                        if (e) {
@@ -1771,13 +1867,22 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
 
                        pe = __find_pending_exception(s, pe, chunk);
                        if (!pe) {
+                               dm_exception_table_unlock(&lock);
+                               up_read(&s->lock);
+
+                               down_write(&s->lock);
+
                                if (s->store->userspace_supports_overflow) {
-                                       s->snapshot_overflowed = 1;
-                                       DMERR("Snapshot overflowed: Unable to allocate exception.");
+                                       if (s->valid && !s->snapshot_overflowed) {
+                                               s->snapshot_overflowed = 1;
+                                               DMERR("Snapshot overflowed: Unable to allocate exception.");
+                                       }
                                } else
                                        __invalidate_snapshot(s, -ENOMEM);
+                               up_write(&s->lock);
+
                                r = DM_MAPIO_KILL;
-                               goto out_unlock;
+                               goto out;
                        }
                }
 
@@ -1789,7 +1894,10 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
                    bio->bi_iter.bi_size ==
                    (s->store->chunk_size << SECTOR_SHIFT)) {
                        pe->started = 1;
-                       mutex_unlock(&s->lock);
+
+                       dm_exception_table_unlock(&lock);
+                       up_read(&s->lock);
+
                        start_full_bio(pe, bio);
                        goto out;
                }
@@ -1797,9 +1905,12 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
                bio_list_add(&pe->snapshot_bios, bio);
 
                if (!pe->started) {
-                       /* this is protected by snap->lock */
+                       /* this is protected by the exception table lock */
                        pe->started = 1;
-                       mutex_unlock(&s->lock);
+
+                       dm_exception_table_unlock(&lock);
+                       up_read(&s->lock);
+
                        start_copy(pe);
                        goto out;
                }
@@ -1809,7 +1920,8 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
        }
 
 out_unlock:
-       mutex_unlock(&s->lock);
+       dm_exception_table_unlock(&lock);
+       up_read(&s->lock);
 out:
        return r;
 }
@@ -1845,7 +1957,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio)
 
        chunk = sector_to_chunk(s->store, bio->bi_iter.bi_sector);
 
-       mutex_lock(&s->lock);
+       down_write(&s->lock);
 
        /* Full merging snapshots are redirected to the origin */
        if (!s->valid)
@@ -1876,12 +1988,12 @@ redirect_to_origin:
        bio_set_dev(bio, s->origin->bdev);
 
        if (bio_data_dir(bio) == WRITE) {
-               mutex_unlock(&s->lock);
+               up_write(&s->lock);
                return do_origin(s->origin, bio);
        }
 
 out_unlock:
-       mutex_unlock(&s->lock);
+       up_write(&s->lock);
 
        return r;
 }
@@ -1913,7 +2025,7 @@ static int snapshot_preresume(struct dm_target *ti)
        down_read(&_origins_lock);
        (void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL);
        if (snap_src && snap_dest) {
-               mutex_lock(&snap_src->lock);
+               down_read(&snap_src->lock);
                if (s == snap_src) {
                        DMERR("Unable to resume snapshot source until "
                              "handover completes.");
@@ -1923,7 +2035,7 @@ static int snapshot_preresume(struct dm_target *ti)
                              "source is suspended.");
                        r = -EINVAL;
                }
-               mutex_unlock(&snap_src->lock);
+               up_read(&snap_src->lock);
        }
        up_read(&_origins_lock);
 
@@ -1969,11 +2081,11 @@ static void snapshot_resume(struct dm_target *ti)
 
        (void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL);
        if (snap_src && snap_dest) {
-               mutex_lock(&snap_src->lock);
-               mutex_lock_nested(&snap_dest->lock, SINGLE_DEPTH_NESTING);
+               down_write(&snap_src->lock);
+               down_write_nested(&snap_dest->lock, SINGLE_DEPTH_NESTING);
                __handover_exceptions(snap_src, snap_dest);
-               mutex_unlock(&snap_dest->lock);
-               mutex_unlock(&snap_src->lock);
+               up_write(&snap_dest->lock);
+               up_write(&snap_src->lock);
        }
 
        up_read(&_origins_lock);
@@ -1988,9 +2100,9 @@ static void snapshot_resume(struct dm_target *ti)
        /* Now we have correct chunk size, reregister */
        reregister_snapshot(s);
 
-       mutex_lock(&s->lock);
+       down_write(&s->lock);
        s->active = 1;
-       mutex_unlock(&s->lock);
+       up_write(&s->lock);
 }
 
 static uint32_t get_origin_minimum_chunksize(struct block_device *bdev)
@@ -2030,7 +2142,7 @@ static void snapshot_status(struct dm_target *ti, status_type_t type,
        switch (type) {
        case STATUSTYPE_INFO:
 
-               mutex_lock(&snap->lock);
+               down_write(&snap->lock);
 
                if (!snap->valid)
                        DMEMIT("Invalid");
@@ -2055,7 +2167,7 @@ static void snapshot_status(struct dm_target *ti, status_type_t type,
                                DMEMIT("Unknown");
                }
 
-               mutex_unlock(&snap->lock);
+               up_write(&snap->lock);
 
                break;
 
@@ -2107,9 +2219,10 @@ static int __origin_write(struct list_head *snapshots, sector_t sector,
        int r = DM_MAPIO_REMAPPED;
        struct dm_snapshot *snap;
        struct dm_exception *e;
-       struct dm_snap_pending_exception *pe;
+       struct dm_snap_pending_exception *pe, *pe2;
        struct dm_snap_pending_exception *pe_to_start_now = NULL;
        struct dm_snap_pending_exception *pe_to_start_last = NULL;
+       struct dm_exception_table_lock lock;
        chunk_t chunk;
 
        /* Do all the snapshots on this origin */
@@ -2121,52 +2234,59 @@ static int __origin_write(struct list_head *snapshots, sector_t sector,
                if (dm_target_is_snapshot_merge(snap->ti))
                        continue;
 
-               mutex_lock(&snap->lock);
-
-               /* Only deal with valid and active snapshots */
-               if (!snap->valid || !snap->active)
-                       goto next_snapshot;
-
                /* Nothing to do if writing beyond end of snapshot */
                if (sector >= dm_table_get_size(snap->ti->table))
-                       goto next_snapshot;
+                       continue;
 
                /*
                 * Remember, different snapshots can have
                 * different chunk sizes.
                 */
                chunk = sector_to_chunk(snap->store, sector);
+               dm_exception_table_lock_init(snap, chunk, &lock);
 
-               /*
-                * Check exception table to see if block
-                * is already remapped in this snapshot
-                * and trigger an exception if not.
-                */
-               e = dm_lookup_exception(&snap->complete, chunk);
-               if (e)
+               down_read(&snap->lock);
+               dm_exception_table_lock(&lock);
+
+               /* Only deal with valid and active snapshots */
+               if (!snap->valid || !snap->active)
                        goto next_snapshot;
 
                pe = __lookup_pending_exception(snap, chunk);
                if (!pe) {
-                       mutex_unlock(&snap->lock);
-                       pe = alloc_pending_exception(snap);
-                       mutex_lock(&snap->lock);
-
-                       if (!snap->valid) {
-                               free_pending_exception(pe);
-                               goto next_snapshot;
-                       }
-
+                       /*
+                        * Check exception table to see if block is already
+                        * remapped in this snapshot and trigger an exception
+                        * if not.
+                        */
                        e = dm_lookup_exception(&snap->complete, chunk);
-                       if (e) {
-                               free_pending_exception(pe);
+                       if (e)
                                goto next_snapshot;
-                       }
 
-                       pe = __find_pending_exception(snap, pe, chunk);
-                       if (!pe) {
-                               __invalidate_snapshot(snap, -ENOMEM);
-                               goto next_snapshot;
+                       dm_exception_table_unlock(&lock);
+                       pe = alloc_pending_exception(snap);
+                       dm_exception_table_lock(&lock);
+
+                       pe2 = __lookup_pending_exception(snap, chunk);
+
+                       if (!pe2) {
+                               e = dm_lookup_exception(&snap->complete, chunk);
+                               if (e) {
+                                       free_pending_exception(pe);
+                                       goto next_snapshot;
+                               }
+
+                               pe = __insert_pending_exception(snap, pe, chunk);
+                               if (!pe) {
+                                       dm_exception_table_unlock(&lock);
+                                       up_read(&snap->lock);
+
+                                       invalidate_snapshot(snap, -ENOMEM);
+                                       continue;
+                               }
+                       } else {
+                               free_pending_exception(pe);
+                               pe = pe2;
                        }
                }
 
@@ -2193,7 +2313,8 @@ static int __origin_write(struct list_head *snapshots, sector_t sector,
                }
 
 next_snapshot:
-               mutex_unlock(&snap->lock);
+               dm_exception_table_unlock(&lock);
+               up_read(&snap->lock);
 
                if (pe_to_start_now) {
                        start_copy(pe_to_start_now);
index 314d17c..64dd0b3 100644 (file)
@@ -136,7 +136,8 @@ static int io_err_clone_and_map_rq(struct dm_target *ti, struct request *rq,
        return DM_MAPIO_KILL;
 }
 
-static void io_err_release_clone_rq(struct request *clone)
+static void io_err_release_clone_rq(struct request *clone,
+                                   union map_info *map_context)
 {
 }
 
index ed3cace..7f08406 100644 (file)
@@ -201,6 +201,13 @@ struct dm_pool_metadata {
         */
        bool fail_io:1;
 
+       /*
+        * Set once a thin-pool has been accessed through one of the interfaces
+        * that imply the pool is in-service (e.g. thin devices created/deleted,
+        * thin-pool message, metadata snapshots, etc).
+        */
+       bool in_service:1;
+
        /*
         * Reading the space map roots can fail, so we read it into these
         * buffers before the superblock is locked and updated.
@@ -367,6 +374,32 @@ static int subtree_equal(void *context, const void *value1_le, const void *value
 
 /*----------------------------------------------------------------*/
 
+/*
+ * Variant that is used for in-core only changes or code that
+ * shouldn't put the pool in service on its own (e.g. commit).
+ */
+static inline void __pmd_write_lock(struct dm_pool_metadata *pmd)
+       __acquires(pmd->root_lock)
+{
+       down_write(&pmd->root_lock);
+}
+#define pmd_write_lock_in_core(pmd) __pmd_write_lock((pmd))
+
+static inline void pmd_write_lock(struct dm_pool_metadata *pmd)
+{
+       __pmd_write_lock(pmd);
+       if (unlikely(!pmd->in_service))
+               pmd->in_service = true;
+}
+
+static inline void pmd_write_unlock(struct dm_pool_metadata *pmd)
+       __releases(pmd->root_lock)
+{
+       up_write(&pmd->root_lock);
+}
+
+/*----------------------------------------------------------------*/
+
 static int superblock_lock_zero(struct dm_pool_metadata *pmd,
                                struct dm_block **sblock)
 {
@@ -790,6 +823,9 @@ static int __commit_transaction(struct dm_pool_metadata *pmd)
         */
        BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512);
 
+       if (unlikely(!pmd->in_service))
+               return 0;
+
        r = __write_changed_details(pmd);
        if (r < 0)
                return r;
@@ -853,6 +889,7 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
        pmd->time = 0;
        INIT_LIST_HEAD(&pmd->thin_devices);
        pmd->fail_io = false;
+       pmd->in_service = false;
        pmd->bdev = bdev;
        pmd->data_block_size = data_block_size;
 
@@ -903,7 +940,6 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
                        DMWARN("%s: __commit_transaction() failed, error = %d",
                               __func__, r);
        }
-
        if (!pmd->fail_io)
                __destroy_persistent_data_objects(pmd);
 
@@ -1032,10 +1068,10 @@ int dm_pool_create_thin(struct dm_pool_metadata *pmd, dm_thin_id dev)
 {
        int r = -EINVAL;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock(pmd);
        if (!pmd->fail_io)
                r = __create_thin(pmd, dev);
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
@@ -1123,10 +1159,10 @@ int dm_pool_create_snap(struct dm_pool_metadata *pmd,
 {
        int r = -EINVAL;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock(pmd);
        if (!pmd->fail_io)
                r = __create_snap(pmd, dev, origin);
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
@@ -1166,10 +1202,10 @@ int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd,
 {
        int r = -EINVAL;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock(pmd);
        if (!pmd->fail_io)
                r = __delete_device(pmd, dev);
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
@@ -1180,7 +1216,7 @@ int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd,
 {
        int r = -EINVAL;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock(pmd);
 
        if (pmd->fail_io)
                goto out;
@@ -1194,7 +1230,7 @@ int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd,
        r = 0;
 
 out:
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
@@ -1225,7 +1261,12 @@ static int __reserve_metadata_snap(struct dm_pool_metadata *pmd)
         * We commit to ensure the btree roots which we increment in a
         * moment are up to date.
         */
-       __commit_transaction(pmd);
+       r = __commit_transaction(pmd);
+       if (r < 0) {
+               DMWARN("%s: __commit_transaction() failed, error = %d",
+                      __func__, r);
+               return r;
+       }
 
        /*
         * Copy the superblock.
@@ -1283,10 +1324,10 @@ int dm_pool_reserve_metadata_snap(struct dm_pool_metadata *pmd)
 {
        int r = -EINVAL;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock(pmd);
        if (!pmd->fail_io)
                r = __reserve_metadata_snap(pmd);
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
@@ -1331,10 +1372,10 @@ int dm_pool_release_metadata_snap(struct dm_pool_metadata *pmd)
 {
        int r = -EINVAL;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock(pmd);
        if (!pmd->fail_io)
                r = __release_metadata_snap(pmd);
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
@@ -1377,19 +1418,19 @@ int dm_pool_open_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev,
 {
        int r = -EINVAL;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock_in_core(pmd);
        if (!pmd->fail_io)
                r = __open_device(pmd, dev, 0, td);
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
 
 int dm_pool_close_thin_device(struct dm_thin_device *td)
 {
-       down_write(&td->pmd->root_lock);
+       pmd_write_lock_in_core(td->pmd);
        __close_device(td);
-       up_write(&td->pmd->root_lock);
+       pmd_write_unlock(td->pmd);
 
        return 0;
 }
@@ -1570,10 +1611,10 @@ int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block,
 {
        int r = -EINVAL;
 
-       down_write(&td->pmd->root_lock);
+       pmd_write_lock(td->pmd);
        if (!td->pmd->fail_io)
                r = __insert(td, block, data_block);
-       up_write(&td->pmd->root_lock);
+       pmd_write_unlock(td->pmd);
 
        return r;
 }
@@ -1657,10 +1698,10 @@ int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block)
 {
        int r = -EINVAL;
 
-       down_write(&td->pmd->root_lock);
+       pmd_write_lock(td->pmd);
        if (!td->pmd->fail_io)
                r = __remove(td, block);
-       up_write(&td->pmd->root_lock);
+       pmd_write_unlock(td->pmd);
 
        return r;
 }
@@ -1670,10 +1711,10 @@ int dm_thin_remove_range(struct dm_thin_device *td,
 {
        int r = -EINVAL;
 
-       down_write(&td->pmd->root_lock);
+       pmd_write_lock(td->pmd);
        if (!td->pmd->fail_io)
                r = __remove_range(td, begin, end);
-       up_write(&td->pmd->root_lock);
+       pmd_write_unlock(td->pmd);
 
        return r;
 }
@@ -1696,13 +1737,13 @@ int dm_pool_inc_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_
 {
        int r = 0;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock(pmd);
        for (; b != e; b++) {
                r = dm_sm_inc_block(pmd->data_sm, b);
                if (r)
                        break;
        }
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
@@ -1711,13 +1752,13 @@ int dm_pool_dec_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_
 {
        int r = 0;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock(pmd);
        for (; b != e; b++) {
                r = dm_sm_dec_block(pmd->data_sm, b);
                if (r)
                        break;
        }
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
@@ -1765,10 +1806,10 @@ int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result)
 {
        int r = -EINVAL;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock(pmd);
        if (!pmd->fail_io)
                r = dm_sm_new_block(pmd->data_sm, result);
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
@@ -1777,12 +1818,16 @@ int dm_pool_commit_metadata(struct dm_pool_metadata *pmd)
 {
        int r = -EINVAL;
 
-       down_write(&pmd->root_lock);
+       /*
+        * Care is taken to not have commit be what
+        * triggers putting the thin-pool in-service.
+        */
+       __pmd_write_lock(pmd);
        if (pmd->fail_io)
                goto out;
 
        r = __commit_transaction(pmd);
-       if (r <= 0)
+       if (r < 0)
                goto out;
 
        /*
@@ -1790,7 +1835,7 @@ int dm_pool_commit_metadata(struct dm_pool_metadata *pmd)
         */
        r = __begin_transaction(pmd);
 out:
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
        return r;
 }
 
@@ -1806,7 +1851,7 @@ int dm_pool_abort_metadata(struct dm_pool_metadata *pmd)
 {
        int r = -EINVAL;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock(pmd);
        if (pmd->fail_io)
                goto out;
 
@@ -1817,7 +1862,7 @@ int dm_pool_abort_metadata(struct dm_pool_metadata *pmd)
                pmd->fail_io = true;
 
 out:
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
@@ -1948,10 +1993,10 @@ int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
 {
        int r = -EINVAL;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock(pmd);
        if (!pmd->fail_io)
                r = __resize_space_map(pmd->data_sm, new_count);
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
@@ -1960,29 +2005,29 @@ int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_cou
 {
        int r = -EINVAL;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock(pmd);
        if (!pmd->fail_io) {
                r = __resize_space_map(pmd->metadata_sm, new_count);
                if (!r)
                        __set_metadata_reserve(pmd);
        }
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
 
 void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd)
 {
-       down_write(&pmd->root_lock);
+       pmd_write_lock_in_core(pmd);
        dm_bm_set_read_only(pmd->bm);
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 }
 
 void dm_pool_metadata_read_write(struct dm_pool_metadata *pmd)
 {
-       down_write(&pmd->root_lock);
+       pmd_write_lock_in_core(pmd);
        dm_bm_set_read_write(pmd->bm);
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 }
 
 int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
@@ -1992,9 +2037,9 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
 {
        int r;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock_in_core(pmd);
        r = dm_sm_register_threshold_callback(pmd->metadata_sm, threshold, fn, context);
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
 
        return r;
 }
@@ -2005,7 +2050,7 @@ int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd)
        struct dm_block *sblock;
        struct thin_disk_superblock *disk_super;
 
-       down_write(&pmd->root_lock);
+       pmd_write_lock(pmd);
        pmd->flags |= THIN_METADATA_NEEDS_CHECK_FLAG;
 
        r = superblock_lock(pmd, &sblock);
@@ -2019,7 +2064,7 @@ int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd)
 
        dm_bm_unlock(sblock);
 out:
-       up_write(&pmd->root_lock);
+       pmd_write_unlock(pmd);
        return r;
 }
 
index f782287..1cb137f 100644 (file)
@@ -190,7 +190,6 @@ struct writeback_struct {
        struct dm_writecache *wc;
        struct wc_entry **wc_list;
        unsigned wc_list_n;
-       unsigned page_offset;
        struct page *page;
        struct wc_entry *wc_list_inline[WB_LIST_INLINE];
        struct bio bio;
@@ -546,21 +545,20 @@ static struct wc_entry *writecache_find_entry(struct dm_writecache *wc,
                e = container_of(node, struct wc_entry, rb_node);
                if (read_original_sector(wc, e) == block)
                        break;
+
                node = (read_original_sector(wc, e) >= block ?
                        e->rb_node.rb_left : e->rb_node.rb_right);
                if (unlikely(!node)) {
-                       if (!(flags & WFE_RETURN_FOLLOWING)) {
+                       if (!(flags & WFE_RETURN_FOLLOWING))
                                return NULL;
-                       }
                        if (read_original_sector(wc, e) >= block) {
-                               break;
+                               return e;
                        } else {
                                node = rb_next(&e->rb_node);
-                               if (unlikely(!node)) {
+                               if (unlikely(!node))
                                        return NULL;
-                               }
                                e = container_of(node, struct wc_entry, rb_node);
-                               break;
+                               return e;
                        }
                }
        }
@@ -571,7 +569,7 @@ static struct wc_entry *writecache_find_entry(struct dm_writecache *wc,
                        node = rb_prev(&e->rb_node);
                else
                        node = rb_next(&e->rb_node);
-               if (!node)
+               if (unlikely(!node))
                        return e;
                e2 = container_of(node, struct wc_entry, rb_node);
                if (read_original_sector(wc, e2) != block)
@@ -804,7 +802,7 @@ static void writecache_discard(struct dm_writecache *wc, sector_t start, sector_
                        writecache_free_entry(wc, e);
                }
 
-               if (!node)
+               if (unlikely(!node))
                        break;
 
                e = container_of(node, struct wc_entry, rb_node);
@@ -1478,10 +1476,9 @@ static void __writecache_writeback_pmem(struct dm_writecache *wc, struct writeba
                bio = bio_alloc_bioset(GFP_NOIO, max_pages, &wc->bio_set);
                wb = container_of(bio, struct writeback_struct, bio);
                wb->wc = wc;
-               wb->bio.bi_end_io = writecache_writeback_endio;
-               bio_set_dev(&wb->bio, wc->dev->bdev);
-               wb->bio.bi_iter.bi_sector = read_original_sector(wc, e);
-               wb->page_offset = PAGE_SIZE;
+               bio->bi_end_io = writecache_writeback_endio;
+               bio_set_dev(bio, wc->dev->bdev);
+               bio->bi_iter.bi_sector = read_original_sector(wc, e);
                if (max_pages <= WB_LIST_INLINE ||
                    unlikely(!(wb->wc_list = kmalloc_array(max_pages, sizeof(struct wc_entry *),
                                                           GFP_NOIO | __GFP_NORETRY |
@@ -1507,12 +1504,12 @@ static void __writecache_writeback_pmem(struct dm_writecache *wc, struct writeba
                        wb->wc_list[wb->wc_list_n++] = f;
                        e = f;
                }
-               bio_set_op_attrs(&wb->bio, REQ_OP_WRITE, WC_MODE_FUA(wc) * REQ_FUA);
+               bio_set_op_attrs(bio, REQ_OP_WRITE, WC_MODE_FUA(wc) * REQ_FUA);
                if (writecache_has_error(wc)) {
                        bio->bi_status = BLK_STS_IOERR;
-                       bio_endio(&wb->bio);
+                       bio_endio(bio);
                } else {
-                       submit_bio(&wb->bio);
+                       submit_bio(bio);
                }
 
                __writeback_throttle(wc, wbl);
index fa68336..d8334cd 100644 (file)
@@ -1169,6 +1169,9 @@ static int dmz_init_zones(struct dmz_metadata *zmd)
                        goto out;
                }
 
+               if (!nr_blkz)
+                       break;
+
                /* Process report */
                for (i = 0; i < nr_blkz; i++) {
                        ret = dmz_init_zone(zmd, zone, &blkz[i]);
@@ -1204,6 +1207,8 @@ static int dmz_update_zone(struct dmz_metadata *zmd, struct dm_zone *zone)
        /* Get zone information from disk */
        ret = blkdev_report_zones(zmd->dev->bdev, dmz_start_sect(zmd, zone),
                                  &blkz, &nr_blkz, GFP_NOIO);
+       if (!nr_blkz)
+               ret = -EIO;
        if (ret) {
                dmz_dev_err(zmd->dev, "Get zone %u report failed",
                            dmz_id(zmd, zone));
index 8865c17..51d029b 100644 (file)
@@ -643,7 +643,8 @@ static int dmz_get_zoned_device(struct dm_target *ti, char *path)
 
        q = bdev_get_queue(dev->bdev);
        dev->capacity = i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT;
-       aligned_capacity = dev->capacity & ~(blk_queue_zone_sectors(q) - 1);
+       aligned_capacity = dev->capacity &
+                               ~((sector_t)blk_queue_zone_sectors(q) - 1);
        if (ti->begin ||
            ((ti->len != dev->capacity) && (ti->len != aligned_capacity))) {
                ti->error = "Partial mapping not supported";
index 043f076..1fb1333 100644 (file)
@@ -781,7 +781,8 @@ static void close_table_device(struct table_device *td, struct mapped_device *md
 }
 
 static struct table_device *find_table_device(struct list_head *l, dev_t dev,
-                                             fmode_t mode) {
+                                             fmode_t mode)
+{
        struct table_device *td;
 
        list_for_each_entry(td, l, list)
@@ -792,7 +793,8 @@ static struct table_device *find_table_device(struct list_head *l, dev_t dev,
 }
 
 int dm_get_table_device(struct mapped_device *md, dev_t dev, fmode_t mode,
-                       struct dm_dev **result) {
+                       struct dm_dev **result)
+{
        int r;
        struct table_device *td;
 
@@ -1906,7 +1908,6 @@ static void cleanup_mapped_device(struct mapped_device *md)
 static struct mapped_device *alloc_dev(int minor)
 {
        int r, numa_node_id = dm_get_numa_node();
-       struct dax_device *dax_dev = NULL;
        struct mapped_device *md;
        void *old_md;
 
@@ -1969,11 +1970,10 @@ static struct mapped_device *alloc_dev(int minor)
        sprintf(md->disk->disk_name, "dm-%d", minor);
 
        if (IS_ENABLED(CONFIG_DAX_DRIVER)) {
-               dax_dev = alloc_dax(md, md->disk->disk_name, &dm_dax_ops);
-               if (!dax_dev)
+               md->dax_dev = alloc_dax(md, md->disk->disk_name, &dm_dax_ops);
+               if (!md->dax_dev)
                        goto bad;
        }
-       md->dax_dev = dax_dev;
 
        add_disk_no_queue_reg(md->disk);
        format_dev_t(md->name, MKDEV(_major, minor));
index 0a3b8ae..b8a6218 100644 (file)
@@ -190,6 +190,8 @@ static int sm_find_free(void *addr, unsigned begin, unsigned end,
 
 static int sm_ll_init(struct ll_disk *ll, struct dm_transaction_manager *tm)
 {
+       memset(ll, 0, sizeof(struct ll_disk));
+
        ll->tm = tm;
 
        ll->bitmap_info.tm = tm;
index 7ebd58a..3cf25ab 100644 (file)
@@ -2201,6 +2201,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
                goto unlock;
        }
 
+       /*
+        * vm_pgoff is treated in V4L2 API as a 'cookie' to select a buffer,
+        * not as a in-buffer offset. We always want to mmap a whole buffer
+        * from its beginning.
+        */
+       vma->vm_pgoff = 0;
+
        ret = call_memop(vb, mmap, vb->planes[plane].mem_priv, vma);
 
 unlock:
index 82389ae..ecbef26 100644 (file)
@@ -186,12 +186,6 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
                return -EINVAL;
        }
 
-       /*
-        * dma_mmap_* uses vm_pgoff as in-buffer offset, but we want to
-        * map whole buffer
-        */
-       vma->vm_pgoff = 0;
-
        ret = dma_mmap_attrs(buf->dev, vma, buf->cookie,
                buf->dma_addr, buf->size, buf->attrs);
 
index 270c316..4a4c49d 100644 (file)
@@ -328,28 +328,18 @@ static unsigned int vb2_dma_sg_num_users(void *buf_priv)
 static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma)
 {
        struct vb2_dma_sg_buf *buf = buf_priv;
-       unsigned long uaddr = vma->vm_start;
-       unsigned long usize = vma->vm_end - vma->vm_start;
-       int i = 0;
+       int err;
 
        if (!buf) {
                printk(KERN_ERR "No memory to map\n");
                return -EINVAL;
        }
 
-       do {
-               int ret;
-
-               ret = vm_insert_page(vma, uaddr, buf->pages[i++]);
-               if (ret) {
-                       printk(KERN_ERR "Remapping memory, error: %d\n", ret);
-                       return ret;
-               }
-
-               uaddr += PAGE_SIZE;
-               usize -= PAGE_SIZE;
-       } while (usize > 0);
-
+       err = vm_map_pages(vma, buf->pages, buf->num_pages);
+       if (err) {
+               printk(KERN_ERR "Remapping memory, error: %d\n", err);
+               return err;
+       }
 
        /*
         * Use common vm_area operations to track buffer refcount.
index d730693..8f7f8ef 100644 (file)
 #define ISC_PFG_CFG0_BPS_TWELVE (0x0 << 28)
 #define ISC_PFE_CFG0_BPS_MASK   GENMASK(30, 28)
 
+#define ISC_PFE_CFG0_COLEN     BIT(12)
+#define ISC_PFE_CFG0_ROWEN     BIT(13)
+
+/* ISC Parallel Front End Configuration 1 Register */
+#define ISC_PFE_CFG1    0x00000010
+
+#define ISC_PFE_CFG1_COLMIN(v)         ((v))
+#define ISC_PFE_CFG1_COLMIN_MASK       GENMASK(15, 0)
+#define ISC_PFE_CFG1_COLMAX(v)         ((v) << 16)
+#define ISC_PFE_CFG1_COLMAX_MASK       GENMASK(31, 16)
+
+/* ISC Parallel Front End Configuration 2 Register */
+#define ISC_PFE_CFG2    0x00000014
+
+#define ISC_PFE_CFG2_ROWMIN(v)         ((v))
+#define ISC_PFE_CFG2_ROWMIN_MASK       GENMASK(15, 0)
+#define ISC_PFE_CFG2_ROWMAX(v)         ((v) << 16)
+#define ISC_PFE_CFG2_ROWMAX_MASK       GENMASK(31, 16)
+
 /* ISC Clock Enable Register */
 #define ISC_CLKEN               0x00000018
 
index 4bba9da..94cb309 100644 (file)
@@ -721,6 +721,40 @@ static void isc_start_dma(struct isc_device *isc)
        u32 sizeimage = isc->fmt.fmt.pix.sizeimage;
        u32 dctrl_dview;
        dma_addr_t addr0;
+       u32 h, w;
+
+       h = isc->fmt.fmt.pix.height;
+       w = isc->fmt.fmt.pix.width;
+
+       /*
+        * In case the sensor is not RAW, it will output a pixel (12-16 bits)
+        * with two samples on the ISC Data bus (which is 8-12)
+        * ISC will count each sample, so, we need to multiply these values
+        * by two, to get the real number of samples for the required pixels.
+        */
+       if (!ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) {
+               h <<= 1;
+               w <<= 1;
+       }
+
+       /*
+        * We limit the column/row count that the ISC will output according
+        * to the configured resolution that we want.
+        * This will avoid the situation where the sensor is misconfigured,
+        * sending more data, and the ISC will just take it and DMA to memory,
+        * causing corruption.
+        */
+       regmap_write(regmap, ISC_PFE_CFG1,
+                    (ISC_PFE_CFG1_COLMIN(0) & ISC_PFE_CFG1_COLMIN_MASK) |
+                    (ISC_PFE_CFG1_COLMAX(w - 1) & ISC_PFE_CFG1_COLMAX_MASK));
+
+       regmap_write(regmap, ISC_PFE_CFG2,
+                    (ISC_PFE_CFG2_ROWMIN(0) & ISC_PFE_CFG2_ROWMIN_MASK) |
+                    (ISC_PFE_CFG2_ROWMAX(h - 1) & ISC_PFE_CFG2_ROWMAX_MASK));
+
+       regmap_update_bits(regmap, ISC_PFE_CFG0,
+                          ISC_PFE_CFG0_COLEN | ISC_PFE_CFG0_ROWEN,
+                          ISC_PFE_CFG0_COLEN | ISC_PFE_CFG0_ROWEN);
 
        addr0 = vb2_dma_contig_plane_dma_addr(&isc->cur_frm->vb.vb2_buf, 0);
        regmap_write(regmap, ISC_DAD0, addr0);
@@ -1965,6 +1999,8 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)
        struct vb2_queue *q = &isc->vb2_vidq;
        int ret;
 
+       INIT_WORK(&isc->awb_work, isc_awb_work);
+
        ret = v4l2_device_register_subdev_nodes(&isc->v4l2_dev);
        if (ret < 0) {
                v4l2_err(&isc->v4l2_dev, "Failed to register subdev nodes\n");
@@ -2018,8 +2054,6 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)
                return ret;
        }
 
-       INIT_WORK(&isc->awb_work, isc_awb_work);
-
        /* Register video device */
        strscpy(vdev->name, ATMEL_ISC_NAME, sizeof(vdev->name));
        vdev->release           = video_device_release_empty;
@@ -2135,8 +2169,11 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc)
                        break;
                }
 
-               subdev_entity->asd = devm_kzalloc(dev,
-                                    sizeof(*subdev_entity->asd), GFP_KERNEL);
+               /* asd will be freed by the subsystem once it's added to the
+                * notifier list
+                */
+               subdev_entity->asd = kzalloc(sizeof(*subdev_entity->asd),
+                                            GFP_KERNEL);
                if (!subdev_entity->asd) {
                        of_node_put(rem);
                        ret = -ENOMEM;
@@ -2284,6 +2321,7 @@ static int atmel_isc_probe(struct platform_device *pdev)
                                                     subdev_entity->asd);
                if (ret) {
                        fwnode_handle_put(subdev_entity->asd->match.fwnode);
+                       kfree(subdev_entity->asd);
                        goto cleanup_subdev;
                }
 
index 3ce58de..1d96cca 100644 (file)
@@ -1515,10 +1515,20 @@ static int coda_queue_setup(struct vb2_queue *vq,
 
 static int coda_buf_prepare(struct vb2_buffer *vb)
 {
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
        struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
        struct coda_q_data *q_data;
 
        q_data = get_q_data(ctx, vb->vb2_queue->type);
+       if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
+               if (vbuf->field == V4L2_FIELD_ANY)
+                       vbuf->field = V4L2_FIELD_NONE;
+               if (vbuf->field != V4L2_FIELD_NONE) {
+                       v4l2_warn(&ctx->dev->v4l2_dev,
+                                 "%s field isn't supported\n", __func__);
+                       return -EINVAL;
+               }
+       }
 
        if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
                v4l2_warn(&ctx->dev->v4l2_dev,
index 8339163..4e24f5d 100644 (file)
@@ -104,7 +104,7 @@ static int vpbe_enum_outputs(struct vpbe_device *vpbe_dev,
                             struct v4l2_output *output)
 {
        struct vpbe_config *cfg = vpbe_dev->cfg;
-       int temp_index = output->index;
+       unsigned int temp_index = output->index;
 
        if (temp_index >= cfg->num_outputs)
                return -EINVAL;
index 37f0d71..cb6a9e3 100644 (file)
@@ -1527,23 +1527,20 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
        unsigned long size;
        struct videobuf_buffer *vb;
 
-       vb = q->bufs[b->index];
-
        if (!vout->streaming)
                return -EINVAL;
 
-       if (file->f_flags & O_NONBLOCK)
-               /* Call videobuf_dqbuf for non blocking mode */
-               ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1);
-       else
-               /* Call videobuf_dqbuf for  blocking mode */
-               ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
+       ret = videobuf_dqbuf(q, b, !!(file->f_flags & O_NONBLOCK));
+       if (ret)
+               return ret;
+
+       vb = q->bufs[b->index];
 
        addr = (unsigned long) vout->buf_phy_addr[vb->i];
        size = (unsigned long) vb->size;
        dma_unmap_single(vout->vid_dev->v4l2_dev.dev,  addr,
                                size, DMA_TO_DEVICE);
-       return ret;
+       return 0;
 }
 
 static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
index 799e526..8f097e5 100644 (file)
@@ -68,6 +68,7 @@ struct rcar_csi2;
 /* Field Detection Control */
 #define FLD_REG                                0x1c
 #define FLD_FLD_NUM(n)                 (((n) & 0xff) << 16)
+#define FLD_DET_SEL(n)                 (((n) & 0x3) << 4)
 #define FLD_FLD_EN4                    BIT(3)
 #define FLD_FLD_EN3                    BIT(2)
 #define FLD_FLD_EN2                    BIT(1)
@@ -84,6 +85,9 @@ struct rcar_csi2;
 
 /* Interrupt Enable */
 #define INTEN_REG                      0x30
+#define INTEN_INT_AFIFO_OF             BIT(27)
+#define INTEN_INT_ERRSOTHS             BIT(4)
+#define INTEN_INT_ERRSOTSYNCHS         BIT(3)
 
 /* Interrupt Source Mask */
 #define INTCLOSE_REG                   0x34
@@ -475,7 +479,7 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp)
 static int rcsi2_start_receiver(struct rcar_csi2 *priv)
 {
        const struct rcar_csi2_format *format;
-       u32 phycnt, vcdt = 0, vcdt2 = 0;
+       u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0;
        unsigned int i;
        int mbps, ret;
 
@@ -507,6 +511,16 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
                        vcdt2 |= vcdt_part << ((i % 2) * 16);
        }
 
+       if (priv->mf.field == V4L2_FIELD_ALTERNATE) {
+               fld = FLD_DET_SEL(1) | FLD_FLD_EN4 | FLD_FLD_EN3 | FLD_FLD_EN2
+                       | FLD_FLD_EN;
+
+               if (priv->mf.height == 240)
+                       fld |= FLD_FLD_NUM(0);
+               else
+                       fld |= FLD_FLD_NUM(1);
+       }
+
        phycnt = PHYCNT_ENABLECLK;
        phycnt |= (1 << priv->lanes) - 1;
 
@@ -514,6 +528,10 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
        if (mbps < 0)
                return mbps;
 
+       /* Enable interrupts. */
+       rcsi2_write(priv, INTEN_REG, INTEN_INT_AFIFO_OF | INTEN_INT_ERRSOTHS
+                   | INTEN_INT_ERRSOTSYNCHS);
+
        /* Init */
        rcsi2_write(priv, TREF_REG, TREF_TREF);
        rcsi2_write(priv, PHTC_REG, 0);
@@ -549,8 +567,7 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
        rcsi2_write(priv, PHYCNT_REG, phycnt);
        rcsi2_write(priv, LINKCNT_REG, LINKCNT_MONITOR_EN |
                    LINKCNT_REG_MONI_PACT_EN | LINKCNT_ICLK_NONSTOP);
-       rcsi2_write(priv, FLD_REG, FLD_FLD_NUM(2) | FLD_FLD_EN4 |
-                   FLD_FLD_EN3 | FLD_FLD_EN2 | FLD_FLD_EN);
+       rcsi2_write(priv, FLD_REG, fld);
        rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ);
        rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ | PHYCNT_RSTZ);
 
@@ -675,6 +692,43 @@ static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
        .pad    = &rcar_csi2_pad_ops,
 };
 
+static irqreturn_t rcsi2_irq(int irq, void *data)
+{
+       struct rcar_csi2 *priv = data;
+       u32 status, err_status;
+
+       status = rcsi2_read(priv, INTSTATE_REG);
+       err_status = rcsi2_read(priv, INTERRSTATE_REG);
+
+       if (!status)
+               return IRQ_HANDLED;
+
+       rcsi2_write(priv, INTSTATE_REG, status);
+
+       if (!err_status)
+               return IRQ_HANDLED;
+
+       rcsi2_write(priv, INTERRSTATE_REG, err_status);
+
+       dev_info(priv->dev, "Transfer error, restarting CSI-2 receiver\n");
+
+       return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t rcsi2_irq_thread(int irq, void *data)
+{
+       struct rcar_csi2 *priv = data;
+
+       mutex_lock(&priv->lock);
+       rcsi2_stop(priv);
+       usleep_range(1000, 2000);
+       if (rcsi2_start(priv))
+               dev_warn(priv->dev, "Failed to restart CSI-2 receiver\n");
+       mutex_unlock(&priv->lock);
+
+       return IRQ_HANDLED;
+}
+
 /* -----------------------------------------------------------------------------
  * Async handling and registration of subdevices and links.
  */
@@ -947,7 +1001,7 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
                                 struct platform_device *pdev)
 {
        struct resource *res;
-       int irq;
+       int irq, ret;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        priv->base = devm_ioremap_resource(&pdev->dev, res);
@@ -958,6 +1012,12 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
        if (irq < 0)
                return irq;
 
+       ret = devm_request_threaded_irq(&pdev->dev, irq, rcsi2_irq,
+                                       rcsi2_irq_thread, IRQF_SHARED,
+                                       KBUILD_MODNAME, priv);
+       if (ret)
+               return ret;
+
        priv->rstc = devm_reset_control_get(&pdev->dev, NULL);
        if (IS_ERR(priv->rstc))
                return PTR_ERR(priv->rstc);
index 7fb3a4f..447bdfb 100644 (file)
@@ -334,8 +334,8 @@ static int tegra_cec_probe(struct platform_device *pdev)
 
        hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);
 
-       if (!hdmi_dev)
-               return -ENODEV;
+       if (IS_ERR(hdmi_dev))
+               return PTR_ERR(hdmi_dev);
 
        cec = devm_kzalloc(&pdev->dev, sizeof(struct tegra_cec), GFP_KERNEL);
 
index 08929c0..870a2a5 100644 (file)
@@ -186,12 +186,12 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
        dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n",
                data, size, dma->nr_pages);
 
-       err = get_user_pages_longterm(data & PAGE_MASK, dma->nr_pages,
-                            flags, dma->pages, NULL);
+       err = get_user_pages(data & PAGE_MASK, dma->nr_pages,
+                            flags | FOLL_LONGTERM, dma->pages, NULL);
 
        if (err != dma->nr_pages) {
                dma->nr_pages = (err >= 0) ? err : 0;
-               dprintk(1, "get_user_pages_longterm: err=%d [%d]\n", err,
+               dprintk(1, "get_user_pages: err=%d [%d]\n", err,
                        dma->nr_pages);
                return err < 0 ? err : -EINVAL;
        }
index 9e9f803..6b71fad 100644 (file)
 #define MCONNID_SHIFT                                  0
 #define MCONNID_MASK                                   (0xff << 0)
 
+/* READ_WRITE_LEVELING_CONTROL */
+#define RDWRLVLFULL_START                              0x80000000
+
 /* DDR_PHY_CTRL_1 - EMIF4D */
 #define DLL_SLAVE_DLY_CTRL_SHIFT_4D                    4
 #define DLL_SLAVE_DLY_CTRL_MASK_4D                     (0xFF << 4)
@@ -598,6 +601,7 @@ extern struct emif_regs_amx3 ti_emif_regs_amx3;
 
 void ti_emif_save_context(void);
 void ti_emif_restore_context(void);
+void ti_emif_run_hw_leveling(void);
 void ti_emif_enter_sr(void);
 void ti_emif_exit_sr(void);
 void ti_emif_abort_sr(void);
index 0a53598..163b6c6 100644 (file)
@@ -51,6 +51,9 @@
 #define MC_EMEM_ADR_CFG 0x54
 #define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0)
 
+#define MC_TIMING_CONTROL              0xfc
+#define MC_TIMING_UPDATE               BIT(0)
+
 static const struct of_device_id tegra_mc_of_match[] = {
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
        { .compatible = "nvidia,tegra20-mc-gart", .data = &tegra20_mc_soc },
@@ -74,7 +77,7 @@ static const struct of_device_id tegra_mc_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tegra_mc_of_match);
 
-static int terga_mc_block_dma_common(struct tegra_mc *mc,
+static int tegra_mc_block_dma_common(struct tegra_mc *mc,
                                     const struct tegra_mc_reset *rst)
 {
        unsigned long flags;
@@ -90,13 +93,13 @@ static int terga_mc_block_dma_common(struct tegra_mc *mc,
        return 0;
 }
 
-static bool terga_mc_dma_idling_common(struct tegra_mc *mc,
+static bool tegra_mc_dma_idling_common(struct tegra_mc *mc,
                                       const struct tegra_mc_reset *rst)
 {
        return (mc_readl(mc, rst->status) & BIT(rst->bit)) != 0;
 }
 
-static int terga_mc_unblock_dma_common(struct tegra_mc *mc,
+static int tegra_mc_unblock_dma_common(struct tegra_mc *mc,
                                       const struct tegra_mc_reset *rst)
 {
        unsigned long flags;
@@ -112,17 +115,17 @@ static int terga_mc_unblock_dma_common(struct tegra_mc *mc,
        return 0;
 }
 
-static int terga_mc_reset_status_common(struct tegra_mc *mc,
+static int tegra_mc_reset_status_common(struct tegra_mc *mc,
                                        const struct tegra_mc_reset *rst)
 {
        return (mc_readl(mc, rst->control) & BIT(rst->bit)) != 0;
 }
 
-const struct tegra_mc_reset_ops terga_mc_reset_ops_common = {
-       .block_dma = terga_mc_block_dma_common,
-       .dma_idling = terga_mc_dma_idling_common,
-       .unblock_dma = terga_mc_unblock_dma_common,
-       .reset_status = terga_mc_reset_status_common,
+const struct tegra_mc_reset_ops tegra_mc_reset_ops_common = {
+       .block_dma = tegra_mc_block_dma_common,
+       .dma_idling = tegra_mc_dma_idling_common,
+       .unblock_dma = tegra_mc_unblock_dma_common,
+       .reset_status = tegra_mc_reset_status_common,
 };
 
 static inline struct tegra_mc *reset_to_mc(struct reset_controller_dev *rcdev)
@@ -282,25 +285,28 @@ static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
        u32 value;
 
        /* compute the number of MC clock cycles per tick */
-       tick = mc->tick * clk_get_rate(mc->clk);
+       tick = (unsigned long long)mc->tick * clk_get_rate(mc->clk);
        do_div(tick, NSEC_PER_SEC);
 
-       value = readl(mc->regs + MC_EMEM_ARB_CFG);
+       value = mc_readl(mc, MC_EMEM_ARB_CFG);
        value &= ~MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK;
        value |= MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(tick);
-       writel(value, mc->regs + MC_EMEM_ARB_CFG);
+       mc_writel(mc, value, MC_EMEM_ARB_CFG);
 
        /* write latency allowance defaults */
        for (i = 0; i < mc->soc->num_clients; i++) {
                const struct tegra_mc_la *la = &mc->soc->clients[i].la;
                u32 value;
 
-               value = readl(mc->regs + la->reg);
+               value = mc_readl(mc, la->reg);
                value &= ~(la->mask << la->shift);
                value |= (la->def & la->mask) << la->shift;
-               writel(value, mc->regs + la->reg);
+               mc_writel(mc, value, la->reg);
        }
 
+       /* latch new values */
+       mc_writel(mc, MC_TIMING_UPDATE, MC_TIMING_CONTROL);
+
        return 0;
 }
 
index 887a3b0..3929939 100644 (file)
@@ -35,7 +35,7 @@ static inline void mc_writel(struct tegra_mc *mc, u32 value,
        writel_relaxed(value, mc->regs + offset);
 }
 
-extern const struct tegra_mc_reset_ops terga_mc_reset_ops_common;
+extern const struct tegra_mc_reset_ops tegra_mc_reset_ops_common;
 
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
 extern const struct tegra_mc_soc tegra20_mc_soc;
index 6560a51..62305fa 100644 (file)
@@ -572,7 +572,7 @@ static const struct tegra_mc_client tegra114_mc_clients[] = {
                },
        }, {
                .id = 0x34,
-               .name = "fdcwr2",
+               .name = "fdcdwr2",
                .swgroup = TEGRA_SWGROUP_NV,
                .smmu = {
                        .reg = 0x22c,
@@ -975,7 +975,7 @@ const struct tegra_mc_soc tegra114_mc_soc = {
        .smmu = &tegra114_smmu_soc,
        .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
                   MC_INT_DECERR_EMEM,
-       .reset_ops = &terga_mc_reset_ops_common,
+       .reset_ops = &tegra_mc_reset_ops_common,
        .resets = tegra114_mc_resets,
        .num_resets = ARRAY_SIZE(tegra114_mc_resets),
 };
index eedb7d4..772716a 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/clkdev.h>
 #include <linux/debugfs.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
index b561a1f..8f8487b 100644 (file)
@@ -1074,7 +1074,7 @@ const struct tegra_mc_soc tegra124_mc_soc = {
        .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
                   MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
                   MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
-       .reset_ops = &terga_mc_reset_ops_common,
+       .reset_ops = &tegra_mc_reset_ops_common,
        .resets = tegra124_mc_resets,
        .num_resets = ARRAY_SIZE(tegra124_mc_resets),
 };
@@ -1104,7 +1104,7 @@ const struct tegra_mc_soc tegra132_mc_soc = {
        .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
                   MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
                   MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
-       .reset_ops = &terga_mc_reset_ops_common,
+       .reset_ops = &tegra_mc_reset_ops_common,
        .resets = tegra124_mc_resets,
        .num_resets = ARRAY_SIZE(tegra124_mc_resets),
 };
index 7119e53..121237b 100644 (file)
@@ -198,7 +198,7 @@ static const struct tegra_mc_reset tegra20_mc_resets[] = {
        TEGRA20_MC_RESET(VI,     0x100, 0x178, 0x104, 14),
 };
 
-static int terga20_mc_hotreset_assert(struct tegra_mc *mc,
+static int tegra20_mc_hotreset_assert(struct tegra_mc *mc,
                                      const struct tegra_mc_reset *rst)
 {
        unsigned long flags;
@@ -214,7 +214,7 @@ static int terga20_mc_hotreset_assert(struct tegra_mc *mc,
        return 0;
 }
 
-static int terga20_mc_hotreset_deassert(struct tegra_mc *mc,
+static int tegra20_mc_hotreset_deassert(struct tegra_mc *mc,
                                        const struct tegra_mc_reset *rst)
 {
        unsigned long flags;
@@ -230,7 +230,7 @@ static int terga20_mc_hotreset_deassert(struct tegra_mc *mc,
        return 0;
 }
 
-static int terga20_mc_block_dma(struct tegra_mc *mc,
+static int tegra20_mc_block_dma(struct tegra_mc *mc,
                                const struct tegra_mc_reset *rst)
 {
        unsigned long flags;
@@ -246,19 +246,19 @@ static int terga20_mc_block_dma(struct tegra_mc *mc,
        return 0;
 }
 
-static bool terga20_mc_dma_idling(struct tegra_mc *mc,
+static bool tegra20_mc_dma_idling(struct tegra_mc *mc,
                                  const struct tegra_mc_reset *rst)
 {
        return mc_readl(mc, rst->status) == 0;
 }
 
-static int terga20_mc_reset_status(struct tegra_mc *mc,
+static int tegra20_mc_reset_status(struct tegra_mc *mc,
                                   const struct tegra_mc_reset *rst)
 {
        return (mc_readl(mc, rst->reset) & BIT(rst->bit)) == 0;
 }
 
-static int terga20_mc_unblock_dma(struct tegra_mc *mc,
+static int tegra20_mc_unblock_dma(struct tegra_mc *mc,
                                  const struct tegra_mc_reset *rst)
 {
        unsigned long flags;
@@ -274,13 +274,13 @@ static int terga20_mc_unblock_dma(struct tegra_mc *mc,
        return 0;
 }
 
-const struct tegra_mc_reset_ops terga20_mc_reset_ops = {
-       .hotreset_assert = terga20_mc_hotreset_assert,
-       .hotreset_deassert = terga20_mc_hotreset_deassert,
-       .block_dma = terga20_mc_block_dma,
-       .dma_idling = terga20_mc_dma_idling,
-       .unblock_dma = terga20_mc_unblock_dma,
-       .reset_status = terga20_mc_reset_status,
+static const struct tegra_mc_reset_ops tegra20_mc_reset_ops = {
+       .hotreset_assert = tegra20_mc_hotreset_assert,
+       .hotreset_deassert = tegra20_mc_hotreset_deassert,
+       .block_dma = tegra20_mc_block_dma,
+       .dma_idling = tegra20_mc_dma_idling,
+       .unblock_dma = tegra20_mc_unblock_dma,
+       .reset_status = tegra20_mc_reset_status,
 };
 
 const struct tegra_mc_soc tegra20_mc_soc = {
@@ -290,7 +290,7 @@ const struct tegra_mc_soc tegra20_mc_soc = {
        .client_id_mask = 0x3f,
        .intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE |
                   MC_INT_DECERR_EMEM,
-       .reset_ops = &terga20_mc_reset_ops,
+       .reset_ops = &tegra20_mc_reset_ops,
        .resets = tegra20_mc_resets,
        .num_resets = ARRAY_SIZE(tegra20_mc_resets),
 };
index d00a771..aa22cda 100644 (file)
@@ -1132,7 +1132,7 @@ const struct tegra_mc_soc tegra210_mc_soc = {
        .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
                   MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
                   MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
-       .reset_ops = &terga_mc_reset_ops_common,
+       .reset_ops = &tegra_mc_reset_ops_common,
        .resets = tegra210_mc_resets,
        .num_resets = ARRAY_SIZE(tegra210_mc_resets),
 };
index bee5314..c9af0f6 100644 (file)
@@ -726,7 +726,7 @@ static const struct tegra_mc_client tegra30_mc_clients[] = {
                },
        }, {
                .id = 0x34,
-               .name = "fdcwr2",
+               .name = "fdcdwr2",
                .swgroup = TEGRA_SWGROUP_NV2,
                .smmu = {
                        .reg = 0x22c,
@@ -999,7 +999,7 @@ const struct tegra_mc_soc tegra30_mc_soc = {
        .smmu = &tegra30_smmu_soc,
        .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
                   MC_INT_DECERR_EMEM,
-       .reset_ops = &terga_mc_reset_ops_common,
+       .reset_ops = &tegra_mc_reset_ops_common,
        .resets = tegra30_mc_resets,
        .num_resets = ARRAY_SIZE(tegra30_mc_resets),
 };
index 2250d03..ab07aa1 100644 (file)
@@ -138,6 +138,9 @@ static int ti_emif_alloc_sram(struct device *dev,
        emif_data->pm_functions.exit_sr =
                sram_resume_address(emif_data,
                                    (unsigned long)ti_emif_exit_sr);
+       emif_data->pm_functions.run_hw_leveling =
+               sram_resume_address(emif_data,
+                                   (unsigned long)ti_emif_run_hw_leveling);
 
        emif_data->pm_data.regs_virt =
                (struct emif_regs_amx3 *)emif_data->ti_emif_sram_data_virt;
index a536918..d75ae18 100644 (file)
@@ -27,6 +27,7 @@
 #define EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK         0x0700
 
 #define EMIF_SDCFG_TYPE_DDR2                           0x2 << SDRAM_TYPE_SHIFT
+#define EMIF_SDCFG_TYPE_DDR3                           0x3 << SDRAM_TYPE_SHIFT
 #define EMIF_STATUS_READY                              0x4
 
 #define AM43XX_EMIF_PHY_CTRL_REG_COUNT                  0x120
@@ -244,6 +245,46 @@ emif_skip_restore_extra_regs:
        mov     pc, lr
 ENDPROC(ti_emif_restore_context)
 
+/*
+ * void ti_emif_run_hw_leveling(void)
+ *
+ * Used during resume to run hardware leveling again and restore the
+ * configuration of the EMIF PHY, only for DDR3.
+ */
+ENTRY(ti_emif_run_hw_leveling)
+       adr     r4, ti_emif_pm_sram_data
+       ldr     r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET]
+
+       ldr     r3, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
+       orr     r3, r3, #RDWRLVLFULL_START
+       ldr     r2, [r0, #EMIF_SDRAM_CONFIG]
+       and     r2, r2, #SDRAM_TYPE_MASK
+       cmp     r2, #EMIF_SDCFG_TYPE_DDR3
+       bne     skip_hwlvl
+
+       str     r3, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
+
+       /*
+        * If EMIF registers are touched during initial stage of HW
+        * leveling sequence there will be an L3 NOC timeout error issued
+        * as the EMIF will not respond, which is not fatal, but it is
+        * avoidable. This small wait loop is enough time for this condition
+        * to clear, even at worst case of CPU running at max speed of 1Ghz.
+        */
+       mov     r2, #0x2000
+1:
+       subs    r2, r2, #0x1
+       bne     1b
+
+       /* Bit clears when operation is complete */
+2:     ldr     r1, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
+       tst     r1, #RDWRLVLFULL_START
+       bne     2b
+
+skip_hwlvl:
+       mov     pc, lr
+ENDPROC(ti_emif_run_hw_leveling)
+
 /*
  * void ti_emif_enter_sr(void)
  *
index 26ad646..294d956 100644 (file)
@@ -16,7 +16,7 @@ config MFD_CS5535
        depends on PCI && (X86_32 || (X86 && COMPILE_TEST))
        ---help---
          This is the core driver for CS5535/CS5536 MFD functions.  This is
-          necessary for using the board's GPIO and MFGPT functionality.
+         necessary for using the board's GPIO and MFGPT functionality.
 
 config MFD_ALTERA_A10SR
        bool "Altera Arria10 DevKit System Resource chip"
@@ -29,6 +29,16 @@ config MFD_ALTERA_A10SR
          accessing the external gpio extender (LEDs & buttons) and
          power supply alarms (hwmon).
 
+config MFD_ALTERA_SYSMGR
+       bool "Altera SOCFPGA System Manager"
+       depends on (ARCH_SOCFPGA || ARCH_STRATIX10) && OF
+       select MFD_SYSCON
+       help
+         Select this to get System Manager support for all Altera branded
+         SOCFPGAs. The SOCFPGA System Manager handles all SOCFPGAs by
+         using regmap_mmio accesses for ARM32 parts and SMC calls to
+         EL3 for ARM64 parts.
+
 config MFD_ACT8945A
        tristate "Active-semi ACT8945A"
        select MFD_CORE
@@ -213,13 +223,13 @@ config MFD_CROS_EC
          protocol for talking to the EC is defined by the bus driver.
 
 config MFD_CROS_EC_CHARDEV
-        tristate "Chrome OS Embedded Controller userspace device interface"
-        depends on MFD_CROS_EC
-        ---help---
-          This driver adds support to talk with the ChromeOS EC from userspace.
+       tristate "Chrome OS Embedded Controller userspace device interface"
+       depends on MFD_CROS_EC
+       ---help---
+         This driver adds support to talk with the ChromeOS EC from userspace.
 
-          If you have a supported Chromebook, choose Y or M here.
-          The module will be called cros_ec_dev.
+         If you have a supported Chromebook, choose Y or M here.
+         The module will be called cros_ec_dev.
 
 config MFD_MADERA
        tristate "Cirrus Logic Madera codecs"
@@ -733,6 +743,20 @@ config MFD_MAX77620
          provides common support for accessing the device; additional drivers
          must be enabled in order to use the functionality of the device.
 
+config MFD_MAX77650
+       tristate "Maxim MAX77650/77651 PMIC Support"
+       depends on I2C
+       depends on OF || COMPILE_TEST
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         Say Y here to add support for Maxim Semiconductor MAX77650 and
+         MAX77651 Power Management ICs. This is the core multifunction
+         driver for interacting with the device. The module name is
+         'max77650'. Additional drivers can be enabled in order to use
+         the following functionalities of the device: GPIO, regulator,
+         charger, LED, onkey.
+
 config MFD_MAX77686
        tristate "Maxim Semiconductor MAX77686/802 PMIC Support"
        depends on I2C
@@ -867,7 +891,7 @@ config MFD_CPCAP
          At least Motorola Droid 4 is known to use CPCAP.
 
 config MFD_VIPERBOARD
-        tristate "Nano River Technologies Viperboard"
+       tristate "Nano River Technologies Viperboard"
        select MFD_CORE
        depends on USB
        default n
@@ -903,15 +927,15 @@ config PCF50633_ADC
        tristate "NXP PCF50633 ADC"
        depends on MFD_PCF50633
        help
-        Say yes here if you want to include support for ADC in the
-        NXP PCF50633 chip.
+         Say yes here if you want to include support for ADC in the
+         NXP PCF50633 chip.
 
 config PCF50633_GPIO
        tristate "NXP PCF50633 GPIO"
        depends on MFD_PCF50633
        help
-        Say yes here if you want to include support GPIO for pins on
-        the PCF50633 chip.
+         Say yes here if you want to include support GPIO for pins on
+         the PCF50633 chip.
 
 config UCB1400_CORE
        tristate "Philips UCB1400 Core driver"
@@ -1026,7 +1050,7 @@ config MFD_RN5T618
        select REGMAP_I2C
        help
          Say yes here to add support for the Ricoh RN5T567,
-          RN5T618, RC5T619 PMIC.
+         RN5T618, RC5T619 PMIC.
          This driver provides common support for accessing the device,
          additional drivers must be enabled in order to use the
          functionality of the device.
@@ -1079,9 +1103,9 @@ config MFD_SM501_GPIO
        bool "Export GPIO via GPIO layer"
        depends on MFD_SM501 && GPIOLIB
         ---help---
-        This option uses the gpio library layer to export the 64 GPIO
-        lines on the SM501. The platform data is used to supply the
-        base number for the first GPIO line to register.
+         This option uses the gpio library layer to export the 64 GPIO
+         lines on the SM501. The platform data is used to supply the
+         base number for the first GPIO line to register.
 
 config MFD_SKY81452
        tristate "Skyworks Solutions SKY81452"
@@ -1096,16 +1120,16 @@ config MFD_SKY81452
          will be called sky81452.
 
 config MFD_SMSC
-       bool "SMSC ECE1099 series chips"
-       depends on I2C=y
-       select MFD_CORE
-       select REGMAP_I2C
-       help
-        If you say yes here you get support for the
-        ece1099 chips from SMSC.
+       bool "SMSC ECE1099 series chips"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         If you say yes here you get support for the
+         ece1099 chips from SMSC.
 
-        To compile this driver as a module, choose M here: the
-        module will be called smsc.
+         To compile this driver as a module, choose M here: the
+         module will be called smsc.
 
 config MFD_SC27XX_PMIC
        tristate "Spreadtrum SC27xx PMICs"
@@ -1171,12 +1195,12 @@ config AB8500_CORE
          This chip embeds various other multimedia funtionalities as well.
 
 config AB8500_DEBUG
-       bool "Enable debug info via debugfs"
-       depends on AB8500_GPADC && DEBUG_FS
-       default y if DEBUG_FS
-       help
-         Select this option if you want debug information using the debug
-         filesystem, debugfs.
+       bool "Enable debug info via debugfs"
+       depends on AB8500_GPADC && DEBUG_FS
+       default y if DEBUG_FS
+       help
+         Select this option if you want debug information using the debug
+         filesystem, debugfs.
 
 config AB8500_GPADC
        bool "ST-Ericsson AB8500 GPADC driver"
@@ -1907,6 +1931,19 @@ config MFD_STPMIC1
          To compile this driver as a module, choose M here: the
          module will be called stpmic1.
 
+config MFD_STMFX
+       tristate "Support for STMicroelectronics Multi-Function eXpander (STMFX)"
+       depends on I2C
+       depends on OF || COMPILE_TEST
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         Support for the STMicroelectronics Multi-Function eXpander.
+
+         This driver provides common support for accessing the device,
+         additional drivers must be enabled in order to use the functionality
+         of the device.
+
 menu "Multimedia Capabilities Port drivers"
        depends on ARCH_SA1100
 
index b4569ed..52b1a90 100644 (file)
@@ -155,6 +155,7 @@ obj-$(CONFIG_MFD_DA9150)    += da9150-core.o
 
 obj-$(CONFIG_MFD_MAX14577)     += max14577.o
 obj-$(CONFIG_MFD_MAX77620)     += max77620.o
+obj-$(CONFIG_MFD_MAX77650)     += max77650.o
 obj-$(CONFIG_MFD_MAX77686)     += max77686.o
 obj-$(CONFIG_MFD_MAX77693)     += max77693.o
 obj-$(CONFIG_MFD_MAX77843)     += max77843.o
@@ -237,6 +238,7 @@ obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI)       += intel_soc_pmic_chtdc_ti.o
 obj-$(CONFIG_MFD_MT6397)       += mt6397-core.o
 
 obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
+obj-$(CONFIG_MFD_ALTERA_SYSMGR) += altera-sysmgr.o
 obj-$(CONFIG_MFD_STPMIC1)      += stpmic1.o
 obj-$(CONFIG_MFD_SUN4I_GPADC)  += sun4i-gpadc.o
 
@@ -246,4 +248,4 @@ obj-$(CONFIG_MFD_MXS_LRADC)     += mxs-lradc.o
 obj-$(CONFIG_MFD_SC27XX_PMIC)  += sprd-sc27xx-spi.o
 obj-$(CONFIG_RAVE_SP_CORE)     += rave-sp.o
 obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
-
+obj-$(CONFIG_MFD_STMFX)        += stmfx.o
index 8d652b2..f70d3f6 100644 (file)
@@ -2587,7 +2587,7 @@ static ssize_t ab8500_unsubscribe_write(struct file *file,
 }
 
 /*
- * - several deubgfs nodes fops
+ * - several debugfs nodes fops
  */
 
 static const struct file_operations ab8500_bank_fops = {
diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c
new file mode 100644 (file)
index 0000000..8976f82
--- /dev/null
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 2018-2019, Intel Corporation.
+ *  Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *  Copyright (C) 2012 Linaro Ltd.
+ *
+ *  Based on syscon driver.
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mfd/altera-sysmgr.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+/**
+ * struct altr_sysmgr - Altera SOCFPGA System Manager
+ * @regmap: the regmap used for System Manager accesses.
+ * @base  : the base address for the System Manager
+ */
+struct altr_sysmgr {
+       struct regmap   *regmap;
+       resource_size_t *base;
+};
+
+static struct platform_driver altr_sysmgr_driver;
+
+/**
+ * s10_protected_reg_write
+ * Write to a protected SMC register.
+ * @base: Base address of System Manager
+ * @reg:  Address offset of register
+ * @val:  Value to write
+ * Return: INTEL_SIP_SMC_STATUS_OK (0) on success
+ *        INTEL_SIP_SMC_REG_ERROR on error
+ *        INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION if not supported
+ */
+static int s10_protected_reg_write(void *base,
+                                  unsigned int reg, unsigned int val)
+{
+       struct arm_smccc_res result;
+       unsigned long sysmgr_base = (unsigned long)base;
+
+       arm_smccc_smc(INTEL_SIP_SMC_REG_WRITE, sysmgr_base + reg,
+                     val, 0, 0, 0, 0, 0, &result);
+
+       return (int)result.a0;
+}
+
+/**
+ * s10_protected_reg_read
+ * Read the status of a protected SMC register
+ * @base: Base address of System Manager.
+ * @reg:  Address of register
+ * @val:  Value read.
+ * Return: INTEL_SIP_SMC_STATUS_OK (0) on success
+ *        INTEL_SIP_SMC_REG_ERROR on error
+ *        INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION if not supported
+ */
+static int s10_protected_reg_read(void *base,
+                                 unsigned int reg, unsigned int *val)
+{
+       struct arm_smccc_res result;
+       unsigned long sysmgr_base = (unsigned long)base;
+
+       arm_smccc_smc(INTEL_SIP_SMC_REG_READ, sysmgr_base + reg,
+                     0, 0, 0, 0, 0, 0, &result);
+
+       *val = (unsigned int)result.a1;
+
+       return (int)result.a0;
+}
+
+static struct regmap_config altr_sysmgr_regmap_cfg = {
+       .name = "altr_sysmgr",
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .fast_io = true,
+       .use_single_read = true,
+       .use_single_write = true,
+};
+
+/**
+ * sysmgr_match_phandle
+ * Matching function used by driver_find_device().
+ * Return: True if match is found, otherwise false.
+ */
+static int sysmgr_match_phandle(struct device *dev, void *data)
+{
+       return dev->of_node == (struct device_node *)data;
+}
+
+/**
+ * altr_sysmgr_regmap_lookup_by_phandle
+ * Find the sysmgr previous configured in probe() and return regmap property.
+ * Return: regmap if found or error if not found.
+ */
+struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np,
+                                                   const char *property)
+{
+       struct device *dev;
+       struct altr_sysmgr *sysmgr;
+       struct device_node *sysmgr_np;
+
+       if (property)
+               sysmgr_np = of_parse_phandle(np, property, 0);
+       else
+               sysmgr_np = np;
+
+       if (!sysmgr_np)
+               return ERR_PTR(-ENODEV);
+
+       dev = driver_find_device(&altr_sysmgr_driver.driver, NULL,
+                                (void *)sysmgr_np, sysmgr_match_phandle);
+       of_node_put(sysmgr_np);
+       if (!dev)
+               return ERR_PTR(-EPROBE_DEFER);
+
+       sysmgr = dev_get_drvdata(dev);
+
+       return sysmgr->regmap;
+}
+EXPORT_SYMBOL_GPL(altr_sysmgr_regmap_lookup_by_phandle);
+
+static int sysmgr_probe(struct platform_device *pdev)
+{
+       struct altr_sysmgr *sysmgr;
+       struct regmap *regmap;
+       struct resource *res;
+       struct regmap_config sysmgr_config = altr_sysmgr_regmap_cfg;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+
+       sysmgr = devm_kzalloc(dev, sizeof(*sysmgr), GFP_KERNEL);
+       if (!sysmgr)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENOENT;
+
+       sysmgr_config.max_register = resource_size(res) -
+                                    sysmgr_config.reg_stride;
+       if (of_device_is_compatible(np, "altr,sys-mgr-s10")) {
+               /* Need physical address for SMCC call */
+               sysmgr->base = (resource_size_t *)res->start;
+               sysmgr_config.reg_read = s10_protected_reg_read;
+               sysmgr_config.reg_write = s10_protected_reg_write;
+
+               regmap = devm_regmap_init(dev, NULL, sysmgr->base,
+                                         &sysmgr_config);
+       } else {
+               sysmgr->base = devm_ioremap(dev, res->start,
+                                           resource_size(res));
+               if (!sysmgr->base)
+                       return -ENOMEM;
+
+               sysmgr_config.max_register = res->end - res->start - 3;
+               regmap = devm_regmap_init_mmio(dev, sysmgr->base,
+                                              &sysmgr_config);
+       }
+
+       if (IS_ERR(regmap)) {
+               pr_err("regmap init failed\n");
+               return PTR_ERR(regmap);
+       }
+
+       sysmgr->regmap = regmap;
+
+       platform_set_drvdata(pdev, sysmgr);
+
+       return 0;
+}
+
+static const struct of_device_id altr_sysmgr_of_match[] = {
+       { .compatible = "altr,sys-mgr" },
+       { .compatible = "altr,sys-mgr-s10" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, altr_sysmgr_of_match);
+
+static struct platform_driver altr_sysmgr_driver = {
+       .probe =  sysmgr_probe,
+       .driver = {
+               .name = "altr,system_manager",
+               .of_match_table = altr_sysmgr_of_match,
+       },
+};
+
+static int __init altr_sysmgr_init(void)
+{
+       return platform_driver_register(&altr_sysmgr_driver);
+}
+core_initcall(altr_sysmgr_init);
+
+static void __exit altr_sysmgr_exit(void)
+{
+       platform_driver_unregister(&altr_sysmgr_driver);
+}
+module_exit(altr_sysmgr_exit);
+
+MODULE_AUTHOR("Thor Thayer <>");
+MODULE_DESCRIPTION("SOCFPGA System Manager driver");
+MODULE_LICENSE("GPL v2");
index e82543b..35a9e16 100644 (file)
@@ -141,6 +141,7 @@ static const struct of_device_id atmel_hlcdc_match[] = {
        { .compatible = "atmel,sama5d2-hlcdc" },
        { .compatible = "atmel,sama5d3-hlcdc" },
        { .compatible = "atmel,sama5d4-hlcdc" },
+       { .compatible = "microchip,sam9x60-hlcdc" },
        { /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, atmel_hlcdc_match);
index a7b7c54..c2e8a0d 100644 (file)
@@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
        { .compatible = "x-powers,axp202", .data = (void *)AXP202_ID },
        { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID },
        { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
+       { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
        { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
        { },
 };
@@ -75,6 +76,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
        { "axp202", 0 },
        { "axp209", 0 },
        { "axp221", 0 },
+       { "axp223", 0 },
        { "axp806", 0 },
        { },
 };
index 3c97f2c..2215660 100644 (file)
@@ -198,6 +198,12 @@ static const struct resource axp22x_usb_power_supply_resources[] = {
        DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
 };
 
+/* AXP803 and AXP813/AXP818 share the same interrupts */
+static const struct resource axp803_usb_power_supply_resources[] = {
+       DEFINE_RES_IRQ_NAMED(AXP803_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
+       DEFINE_RES_IRQ_NAMED(AXP803_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
+};
+
 static const struct resource axp22x_pek_resources[] = {
        DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
        DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
@@ -741,6 +747,11 @@ static const struct mfd_cell axp803_cells[] = {
                .of_compatible  = "x-powers,axp813-ac-power-supply",
                .num_resources  = ARRAY_SIZE(axp20x_ac_power_supply_resources),
                .resources      = axp20x_ac_power_supply_resources,
+       }, {
+               .name           = "axp20x-usb-power-supply",
+               .num_resources  = ARRAY_SIZE(axp803_usb_power_supply_resources),
+               .resources      = axp803_usb_power_supply_resources,
+               .of_compatible  = "x-powers,axp813-usb-power-supply",
        },
        {       .name           = "axp20x-regulator" },
 };
@@ -793,6 +804,11 @@ static const struct mfd_cell axp813_cells[] = {
                .of_compatible  = "x-powers,axp813-ac-power-supply",
                .num_resources  = ARRAY_SIZE(axp20x_ac_power_supply_resources),
                .resources      = axp20x_ac_power_supply_resources,
+       }, {
+               .name           = "axp20x-usb-power-supply",
+               .num_resources  = ARRAY_SIZE(axp803_usb_power_supply_resources),
+               .resources      = axp803_usb_power_supply_resources,
+               .of_compatible  = "x-powers,axp813-usb-power-supply",
        },
 };
 
index 6acfe03..bd2bcdd 100644 (file)
@@ -75,20 +75,49 @@ static irqreturn_t ec_irq_thread(int irq, void *data)
 
 static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event)
 {
+       int ret;
        struct {
                struct cros_ec_command msg;
-               struct ec_params_host_sleep_event req;
+               union {
+                       struct ec_params_host_sleep_event req0;
+                       struct ec_params_host_sleep_event_v1 req1;
+                       struct ec_response_host_sleep_event_v1 resp1;
+               } u;
        } __packed buf;
 
        memset(&buf, 0, sizeof(buf));
 
-       buf.req.sleep_event = sleep_event;
+       if (ec_dev->host_sleep_v1) {
+               buf.u.req1.sleep_event = sleep_event;
+               buf.u.req1.suspend_params.sleep_timeout_ms =
+                               EC_HOST_SLEEP_TIMEOUT_DEFAULT;
+
+               buf.msg.outsize = sizeof(buf.u.req1);
+               if ((sleep_event == HOST_SLEEP_EVENT_S3_RESUME) ||
+                   (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME))
+                       buf.msg.insize = sizeof(buf.u.resp1);
+
+               buf.msg.version = 1;
+
+       } else {
+               buf.u.req0.sleep_event = sleep_event;
+               buf.msg.outsize = sizeof(buf.u.req0);
+       }
 
        buf.msg.command = EC_CMD_HOST_SLEEP_EVENT;
-       buf.msg.version = 0;
-       buf.msg.outsize = sizeof(buf.req);
 
-       return cros_ec_cmd_xfer(ec_dev, &buf.msg);
+       ret = cros_ec_cmd_xfer(ec_dev, &buf.msg);
+
+       /* For now, report failure to transition to S0ix with a warning. */
+       if (ret >= 0 && ec_dev->host_sleep_v1 &&
+           (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME))
+               WARN_ONCE(buf.u.resp1.resume_response.sleep_transitions &
+                         EC_HOST_RESUME_SLEEP_TIMEOUT,
+                         "EC detected sleep transition timeout. Total slp_s0 transitions: %d",
+                         buf.u.resp1.resume_response.sleep_transitions &
+                         EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK);
+
+       return ret;
 }
 
 int cros_ec_register(struct cros_ec_device *ec_dev)
index d275dea..54a58df 100644 (file)
@@ -385,7 +385,8 @@ static const struct mfd_cell cros_ec_rtc_cells[] = {
 };
 
 static const struct mfd_cell cros_usbpd_charger_cells[] = {
-       { .name = "cros-usbpd-charger" }
+       { .name = "cros-usbpd-charger" },
+       { .name = "cros-usbpd-logger" },
 };
 
 static const struct mfd_cell cros_ec_platform_cells[] = {
@@ -418,6 +419,39 @@ static int ec_device_probe(struct platform_device *pdev)
        device_initialize(&ec->class_dev);
        cdev_init(&ec->cdev, &fops);
 
+       /* Check whether this is actually a Fingerprint MCU rather than an EC */
+       if (cros_ec_check_features(ec, EC_FEATURE_FINGERPRINT)) {
+               dev_info(dev, "CrOS Fingerprint MCU detected.\n");
+               /*
+                * Help userspace differentiating ECs from FP MCU,
+                * regardless of the probing order.
+                */
+               ec_platform->ec_name = CROS_EC_DEV_FP_NAME;
+       }
+
+       /*
+        * Check whether this is actually an Integrated Sensor Hub (ISH)
+        * rather than an EC.
+        */
+       if (cros_ec_check_features(ec, EC_FEATURE_ISH)) {
+               dev_info(dev, "CrOS ISH MCU detected.\n");
+               /*
+                * Help userspace differentiating ECs from ISH MCU,
+                * regardless of the probing order.
+                */
+               ec_platform->ec_name = CROS_EC_DEV_ISH_NAME;
+       }
+
+       /* Check whether this is actually a Touchpad MCU rather than an EC */
+       if (cros_ec_check_features(ec, EC_FEATURE_TOUCHPAD)) {
+               dev_info(dev, "CrOS Touchpad MCU detected.\n");
+               /*
+                * Help userspace differentiating ECs from TP MCU,
+                * regardless of the probing order.
+                */
+               ec_platform->ec_name = CROS_EC_DEV_TP_NAME;
+       }
+
        /*
         * Add the class device
         * Link to the character device for creating the /dev entry
index 604c9dd..338b825 100644 (file)
@@ -178,6 +178,7 @@ static const struct reg_default cs47l35_reg_default[] = {
        { 0x00000448, 0x0a83 }, /* R1096 (0x448) - eDRE Enable */
        { 0x0000044a, 0x0000 }, /* R1098 (0x44a) - eDRE Manual */
        { 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */
+       { 0x00000451, 0x0000 }, /* R1105 (0x451) - DAC AEC Control 2 */
        { 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */
        { 0x00000490, 0x0069 }, /* R1168 (0x490) - PDM SPK1 CTRL 1 */
        { 0x00000491, 0x0000 }, /* R1169 (0x491) - PDM SPK1 CTRL 2 */
@@ -970,6 +971,7 @@ static bool cs47l35_16bit_readable_register(struct device *dev,
        case MADERA_EDRE_ENABLE:
        case MADERA_EDRE_MANUAL:
        case MADERA_DAC_AEC_CONTROL_1:
+       case MADERA_DAC_AEC_CONTROL_2:
        case MADERA_NOISE_GATE_CONTROL:
        case MADERA_PDM_SPK1_CTRL_1:
        case MADERA_PDM_SPK1_CTRL_2:
index 77207d9..c040d3d 100644 (file)
@@ -263,6 +263,7 @@ static const struct reg_default cs47l90_reg_default[] = {
        { 0x00000440, 0x003f }, /* R1088 (0x440) - DRE Enable */
        { 0x00000448, 0x003f }, /* R1096 (0x448) - eDRE Enable */
        { 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */
+       { 0x00000451, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 2 */
        { 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */
        { 0x00000490, 0x0069 }, /* R1168 (0x490) - PDM SPK1 CTRL 1 */
        { 0x00000491, 0x0000 }, /* R1169 (0x491) - PDM SPK1 CTRL 2 */
@@ -1692,6 +1693,7 @@ static bool cs47l90_16bit_readable_register(struct device *dev,
        case MADERA_DRE_ENABLE:
        case MADERA_EDRE_ENABLE:
        case MADERA_DAC_AEC_CONTROL_1:
+       case MADERA_DAC_AEC_CONTROL_2:
        case MADERA_NOISE_GATE_CONTROL:
        case MADERA_PDM_SPK1_CTRL_1:
        case MADERA_PDM_SPK1_CTRL_2:
index 6e4ce49..b125f90 100644 (file)
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
- * da9063-core.c: Device access for Dialog DA9063 modules
+ * Device access for Dialog DA9063 modules
  *
  * Copyright 2012 Dialog Semiconductors Ltd.
  * Copyright 2013 Philipp Zabel, Pengutronix
@@ -7,11 +8,6 @@
  * Author: Krystian Garbaciak, Dialog Semiconductor
  * Author: Michal Hajduk, Dialog 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.
- *
  */
 
 #include <linux/kernel.h>
@@ -26,7 +22,6 @@
 #include <linux/regmap.h>
 
 #include <linux/mfd/da9063/core.h>
-#include <linux/mfd/da9063/pdata.h>
 #include <linux/mfd/da9063/registers.h>
 
 #include <linux/proc_fs.h>
@@ -165,7 +160,6 @@ static int da9063_clear_fault_log(struct da9063 *da9063)
 
 int da9063_device_init(struct da9063 *da9063, unsigned int irq)
 {
-       struct da9063_pdata *pdata = da9063->dev->platform_data;
        int model, variant_id, variant_code;
        int ret;
 
@@ -173,24 +167,10 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
        if (ret < 0)
                dev_err(da9063->dev, "Cannot clear fault log\n");
 
-       if (pdata) {
-               da9063->flags = pdata->flags;
-               da9063->irq_base = pdata->irq_base;
-       } else {
-               da9063->flags = 0;
-               da9063->irq_base = -1;
-       }
+       da9063->flags = 0;
+       da9063->irq_base = -1;
        da9063->chip_irq = irq;
 
-       if (pdata && pdata->init != NULL) {
-               ret = pdata->init(da9063);
-               if (ret != 0) {
-                       dev_err(da9063->dev,
-                               "Platform initialization failed.\n");
-                       return ret;
-               }
-       }
-
        ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_ID, &model);
        if (ret < 0) {
                dev_err(da9063->dev, "Cannot read chip model id.\n");
index 50a24b1..455de74 100644 (file)
@@ -1,15 +1,10 @@
-/* da9063-i2c.c: Interrupt support for Dialog DA9063
+// SPDX-License-Identifier: GPL-2.0+
+/* I2C support for Dialog DA9063
  *
  * Copyright 2012 Dialog Semiconductor Ltd.
  * Copyright 2013 Philipp Zabel, Pengutronix
  *
  * Author: Krystian Garbaciak, Dialog 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.
- *
  */
 
 #include <linux/kernel.h>
@@ -22,7 +17,6 @@
 
 #include <linux/mfd/core.h>
 #include <linux/mfd/da9063/core.h>
-#include <linux/mfd/da9063/pdata.h>
 #include <linux/mfd/da9063/registers.h>
 
 #include <linux/of.h>
index ecc0c8c..e2bbedf 100644 (file)
@@ -1,15 +1,10 @@
-/* da9063-irq.c: Interrupts support for Dialog DA9063
+// SPDX-License-Identifier: GPL-2.0+
+/* Interrupt support for Dialog DA9063
  *
  * Copyright 2012 Dialog Semiconductor Ltd.
  * Copyright 2013 Philipp Zabel, Pengutronix
  *
  * Author: Michal Hajduk, Dialog 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.
- *
  */
 
 #include <linux/kernel.h>
@@ -19,7 +14,6 @@
 #include <linux/interrupt.h>
 #include <linux/regmap.h>
 #include <linux/mfd/da9063/core.h>
-#include <linux/mfd/da9063/pdata.h>
 
 #define        DA9063_REG_EVENT_A_OFFSET       0
 #define        DA9063_REG_EVENT_B_OFFSET       1
index cba2eb1..6b111be 100644 (file)
@@ -129,6 +129,19 @@ static const struct intel_lpss_platform_info cnl_i2c_info = {
 };
 
 static const struct pci_device_id intel_lpss_pci_ids[] = {
+       /* CML */
+       { PCI_VDEVICE(INTEL, 0x02a8), (kernel_ulong_t)&spt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x02a9), (kernel_ulong_t)&spt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x02aa), (kernel_ulong_t)&spt_info },
+       { PCI_VDEVICE(INTEL, 0x02ab), (kernel_ulong_t)&spt_info },
+       { PCI_VDEVICE(INTEL, 0x02c5), (kernel_ulong_t)&cnl_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x02c6), (kernel_ulong_t)&cnl_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x02c7), (kernel_ulong_t)&spt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x02e8), (kernel_ulong_t)&cnl_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x02e9), (kernel_ulong_t)&cnl_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x02ea), (kernel_ulong_t)&cnl_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x02eb), (kernel_ulong_t)&cnl_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x02fb), (kernel_ulong_t)&spt_info },
        /* BXT A-Step */
        { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info },
        { PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info },
index 45221e0..fc6aa4c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/clk-provider.h>
 #include <linux/debugfs.h>
 #include <linux/idr.h>
+#include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -273,6 +274,9 @@ static void intel_lpss_init_dev(const struct intel_lpss *lpss)
 {
        u32 value = LPSS_PRIV_SSP_REG_DIS_DMA_FIN;
 
+       /* Set the device in reset state */
+       writel(0, lpss->priv + LPSS_PRIV_RESETS);
+
        intel_lpss_deassert_reset(lpss);
 
        intel_lpss_set_remap_addr(lpss);
index 5bddb84..11adbf7 100644 (file)
@@ -74,16 +74,6 @@ static const struct dmi_system_id dmi_platform_info[] = {
        {
                .matches = {
                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
-                       DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
-                                       "6ES7647-0AA00-0YA2"),
-               },
-               .driver_data = (void *)400000,
-       },
-       {
-               .matches = {
-                       DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
-                       DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
-                                       "6ES7647-0AA00-1YA2"),
                },
                .driver_data = (void *)400000,
        },
index 64a3aec..be84bb2 100644 (file)
@@ -60,6 +60,7 @@ static struct mfd_cell cht_wc_dev[] = {
                .resources = cht_wc_ext_charger_resources,
        },
        {       .name = "cht_wcove_region", },
+       {       .name = "cht_wcove_leds", },
 };
 
 /*
index d8ddd1a..436361c 100644 (file)
@@ -37,6 +37,8 @@
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
+static struct max77620_chip *max77620_scratch;
+
 static const struct resource gpio_resources[] = {
        DEFINE_RES_IRQ(MAX77620_IRQ_TOP_GPIO),
 };
@@ -111,6 +113,26 @@ static const struct mfd_cell max20024_children[] = {
        },
 };
 
+static const struct mfd_cell max77663_children[] = {
+       { .name = "max77620-pinctrl", },
+       { .name = "max77620-clock", },
+       { .name = "max77663-pmic", },
+       { .name = "max77620-watchdog", },
+       {
+               .name = "max77620-gpio",
+               .resources = gpio_resources,
+               .num_resources = ARRAY_SIZE(gpio_resources),
+       }, {
+               .name = "max77620-rtc",
+               .resources = rtc_resources,
+               .num_resources = ARRAY_SIZE(rtc_resources),
+       }, {
+               .name = "max77663-power",
+               .resources = power_resources,
+               .num_resources = ARRAY_SIZE(power_resources),
+       },
+};
+
 static const struct regmap_range max77620_readable_ranges[] = {
        regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4),
 };
@@ -171,6 +193,35 @@ static const struct regmap_config max20024_regmap_config = {
        .volatile_table = &max77620_volatile_table,
 };
 
+static const struct regmap_range max77663_readable_ranges[] = {
+       regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_CID5),
+};
+
+static const struct regmap_access_table max77663_readable_table = {
+       .yes_ranges = max77663_readable_ranges,
+       .n_yes_ranges = ARRAY_SIZE(max77663_readable_ranges),
+};
+
+static const struct regmap_range max77663_writable_ranges[] = {
+       regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_CID5),
+};
+
+static const struct regmap_access_table max77663_writable_table = {
+       .yes_ranges = max77663_writable_ranges,
+       .n_yes_ranges = ARRAY_SIZE(max77663_writable_ranges),
+};
+
+static const struct regmap_config max77663_regmap_config = {
+       .name = "power-slave",
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = MAX77620_REG_CID5 + 1,
+       .cache_type = REGCACHE_RBTREE,
+       .rd_table = &max77663_readable_table,
+       .wr_table = &max77663_writable_table,
+       .volatile_table = &max77620_volatile_table,
+};
+
 /*
  * MAX77620 and MAX20024 has the following steps of the interrupt handling
  * for TOP interrupts:
@@ -240,6 +291,9 @@ static int max77620_get_fps_period_reg_value(struct max77620_chip *chip,
        case MAX77620:
                fps_min_period = MAX77620_FPS_PERIOD_MIN_US;
                break;
+       case MAX77663:
+               fps_min_period = MAX20024_FPS_PERIOD_MIN_US;
+               break;
        default:
                return -EINVAL;
        }
@@ -274,6 +328,9 @@ static int max77620_config_fps(struct max77620_chip *chip,
        case MAX77620:
                fps_max_period = MAX77620_FPS_PERIOD_MAX_US;
                break;
+       case MAX77663:
+               fps_max_period = MAX20024_FPS_PERIOD_MAX_US;
+               break;
        default:
                return -EINVAL;
        }
@@ -375,6 +432,9 @@ static int max77620_initialise_fps(struct max77620_chip *chip)
        }
 
 skip_fps:
+       if (chip->chip_id == MAX77663)
+               return 0;
+
        /* Enable wake on EN0 pin */
        ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
                                 MAX77620_ONOFFCNFG2_WK_EN0,
@@ -423,6 +483,15 @@ static int max77620_read_es_version(struct max77620_chip *chip)
        return ret;
 }
 
+static void max77620_pm_power_off(void)
+{
+       struct max77620_chip *chip = max77620_scratch;
+
+       regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1,
+                          MAX77620_ONOFFCNFG1_SFT_RST,
+                          MAX77620_ONOFFCNFG1_SFT_RST);
+}
+
 static int max77620_probe(struct i2c_client *client,
                          const struct i2c_device_id *id)
 {
@@ -430,6 +499,7 @@ static int max77620_probe(struct i2c_client *client,
        struct max77620_chip *chip;
        const struct mfd_cell *mfd_cells;
        int n_mfd_cells;
+       bool pm_off;
        int ret;
 
        chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
@@ -453,6 +523,11 @@ static int max77620_probe(struct i2c_client *client,
                n_mfd_cells = ARRAY_SIZE(max20024_children);
                rmap_config = &max20024_regmap_config;
                break;
+       case MAX77663:
+               mfd_cells = max77663_children;
+               n_mfd_cells = ARRAY_SIZE(max77663_children);
+               rmap_config = &max77663_regmap_config;
+               break;
        default:
                dev_err(chip->dev, "ChipID is invalid %d\n", chip->chip_id);
                return -EINVAL;
@@ -491,6 +566,12 @@ static int max77620_probe(struct i2c_client *client,
                return ret;
        }
 
+       pm_off = of_device_is_system_power_controller(client->dev.of_node);
+       if (pm_off && !pm_power_off) {
+               max77620_scratch = chip;
+               pm_power_off = max77620_pm_power_off;
+       }
+
        return 0;
 }
 
@@ -546,6 +627,9 @@ static int max77620_i2c_suspend(struct device *dev)
                return ret;
        }
 
+       if (chip->chip_id == MAX77663)
+               goto out;
+
        /* Disable WK_EN0 */
        ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
                                 MAX77620_ONOFFCNFG2_WK_EN0, 0);
@@ -581,7 +665,7 @@ static int max77620_i2c_resume(struct device *dev)
         * For MAX20024: No need to configure WKEN0 on resume as
         * it is configured on Init.
         */
-       if (chip->chip_id == MAX20024)
+       if (chip->chip_id == MAX20024 || chip->chip_id == MAX77663)
                goto out;
 
        /* Enable WK_EN0 */
@@ -603,6 +687,7 @@ out:
 static const struct i2c_device_id max77620_id[] = {
        {"max77620", MAX77620},
        {"max20024", MAX20024},
+       {"max77663", MAX77663},
        {},
 };
 
diff --git a/drivers/mfd/max77650.c b/drivers/mfd/max77650.c
new file mode 100644 (file)
index 0000000..60e07ac
--- /dev/null
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// Core MFD driver for MAXIM 77650/77651 charger/power-supply.
+// Programming manual: https://pdfserv.maximintegrated.com/en/an/AN6428.pdf
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max77650.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+#define MAX77650_INT_GPI_F_MSK         BIT(0)
+#define MAX77650_INT_GPI_R_MSK         BIT(1)
+#define MAX77650_INT_GPI_MSK \
+                       (MAX77650_INT_GPI_F_MSK | MAX77650_INT_GPI_R_MSK)
+#define MAX77650_INT_nEN_F_MSK         BIT(2)
+#define MAX77650_INT_nEN_R_MSK         BIT(3)
+#define MAX77650_INT_TJAL1_R_MSK       BIT(4)
+#define MAX77650_INT_TJAL2_R_MSK       BIT(5)
+#define MAX77650_INT_DOD_R_MSK         BIT(6)
+
+#define MAX77650_INT_THM_MSK           BIT(0)
+#define MAX77650_INT_CHG_MSK           BIT(1)
+#define MAX77650_INT_CHGIN_MSK         BIT(2)
+#define MAX77650_INT_TJ_REG_MSK                BIT(3)
+#define MAX77650_INT_CHGIN_CTRL_MSK    BIT(4)
+#define MAX77650_INT_SYS_CTRL_MSK      BIT(5)
+#define MAX77650_INT_SYS_CNFG_MSK      BIT(6)
+
+#define MAX77650_INT_GLBL_OFFSET       0
+#define MAX77650_INT_CHG_OFFSET                1
+
+#define MAX77650_SBIA_LPM_MASK         BIT(5)
+#define MAX77650_SBIA_LPM_DISABLED     0x00
+
+enum {
+       MAX77650_INT_GPI,
+       MAX77650_INT_nEN_F,
+       MAX77650_INT_nEN_R,
+       MAX77650_INT_TJAL1_R,
+       MAX77650_INT_TJAL2_R,
+       MAX77650_INT_DOD_R,
+       MAX77650_INT_THM,
+       MAX77650_INT_CHG,
+       MAX77650_INT_CHGIN,
+       MAX77650_INT_TJ_REG,
+       MAX77650_INT_CHGIN_CTRL,
+       MAX77650_INT_SYS_CTRL,
+       MAX77650_INT_SYS_CNFG,
+};
+
+static const struct resource max77650_charger_resources[] = {
+       DEFINE_RES_IRQ_NAMED(MAX77650_INT_CHG, "CHG"),
+       DEFINE_RES_IRQ_NAMED(MAX77650_INT_CHGIN, "CHGIN"),
+};
+
+static const struct resource max77650_gpio_resources[] = {
+       DEFINE_RES_IRQ_NAMED(MAX77650_INT_GPI, "GPI"),
+};
+
+static const struct resource max77650_onkey_resources[] = {
+       DEFINE_RES_IRQ_NAMED(MAX77650_INT_nEN_F, "nEN_F"),
+       DEFINE_RES_IRQ_NAMED(MAX77650_INT_nEN_R, "nEN_R"),
+};
+
+static const struct mfd_cell max77650_cells[] = {
+       {
+               .name           = "max77650-regulator",
+               .of_compatible  = "maxim,max77650-regulator",
+       }, {
+               .name           = "max77650-charger",
+               .of_compatible  = "maxim,max77650-charger",
+               .resources      = max77650_charger_resources,
+               .num_resources  = ARRAY_SIZE(max77650_charger_resources),
+       }, {
+               .name           = "max77650-gpio",
+               .of_compatible  = "maxim,max77650-gpio",
+               .resources      = max77650_gpio_resources,
+               .num_resources  = ARRAY_SIZE(max77650_gpio_resources),
+       }, {
+               .name           = "max77650-led",
+               .of_compatible  = "maxim,max77650-led",
+       }, {
+               .name           = "max77650-onkey",
+               .of_compatible  = "maxim,max77650-onkey",
+               .resources      = max77650_onkey_resources,
+               .num_resources  = ARRAY_SIZE(max77650_onkey_resources),
+       },
+};
+
+static const struct regmap_irq max77650_irqs[] = {
+       [MAX77650_INT_GPI] = {
+               .reg_offset = MAX77650_INT_GLBL_OFFSET,
+               .mask = MAX77650_INT_GPI_MSK,
+               .type = {
+                       .type_falling_val = MAX77650_INT_GPI_F_MSK,
+                       .type_rising_val = MAX77650_INT_GPI_R_MSK,
+                       .types_supported = IRQ_TYPE_EDGE_BOTH,
+               },
+       },
+       REGMAP_IRQ_REG(MAX77650_INT_nEN_F,
+                      MAX77650_INT_GLBL_OFFSET, MAX77650_INT_nEN_F_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_nEN_R,
+                      MAX77650_INT_GLBL_OFFSET, MAX77650_INT_nEN_R_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_TJAL1_R,
+                      MAX77650_INT_GLBL_OFFSET, MAX77650_INT_TJAL1_R_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_TJAL2_R,
+                      MAX77650_INT_GLBL_OFFSET, MAX77650_INT_TJAL2_R_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_DOD_R,
+                      MAX77650_INT_GLBL_OFFSET, MAX77650_INT_DOD_R_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_THM,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_THM_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_CHG,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHG_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_CHGIN,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHGIN_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_TJ_REG,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_TJ_REG_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_CHGIN_CTRL,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHGIN_CTRL_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_SYS_CTRL,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_SYS_CTRL_MSK),
+       REGMAP_IRQ_REG(MAX77650_INT_SYS_CNFG,
+                      MAX77650_INT_CHG_OFFSET, MAX77650_INT_SYS_CNFG_MSK),
+};
+
+static const struct regmap_irq_chip max77650_irq_chip = {
+       .name                   = "max77650-irq",
+       .irqs                   = max77650_irqs,
+       .num_irqs               = ARRAY_SIZE(max77650_irqs),
+       .num_regs               = 2,
+       .status_base            = MAX77650_REG_INT_GLBL,
+       .mask_base              = MAX77650_REG_INTM_GLBL,
+       .type_in_mask           = true,
+       .type_invert            = true,
+       .init_ack_masked        = true,
+       .clear_on_unmask        = true,
+};
+
+static const struct regmap_config max77650_regmap_config = {
+       .name           = "max77650",
+       .reg_bits       = 8,
+       .val_bits       = 8,
+};
+
+static int max77650_i2c_probe(struct i2c_client *i2c)
+{
+       struct regmap_irq_chip_data *irq_data;
+       struct device *dev = &i2c->dev;
+       struct irq_domain *domain;
+       struct regmap *map;
+       unsigned int val;
+       int rv, id;
+
+       map = devm_regmap_init_i2c(i2c, &max77650_regmap_config);
+       if (IS_ERR(map)) {
+               dev_err(dev, "Unable to initialise I2C Regmap\n");
+               return PTR_ERR(map);
+       }
+
+       rv = regmap_read(map, MAX77650_REG_CID, &val);
+       if (rv) {
+               dev_err(dev, "Unable to read Chip ID\n");
+               return rv;
+       }
+
+       id = MAX77650_CID_BITS(val);
+       switch (id) {
+       case MAX77650_CID_77650A:
+       case MAX77650_CID_77650C:
+       case MAX77650_CID_77651A:
+       case MAX77650_CID_77651B:
+               break;
+       default:
+               dev_err(dev, "Chip not supported - ID: 0x%02x\n", id);
+               return -ENODEV;
+       }
+
+       /*
+        * This IC has a low-power mode which reduces the quiescent current
+        * consumption to ~5.6uA but is only suitable for systems consuming
+        * less than ~2mA. Since this is not likely the case even on
+        * linux-based wearables - keep the chip in normal power mode.
+        */
+       rv = regmap_update_bits(map,
+                               MAX77650_REG_CNFG_GLBL,
+                               MAX77650_SBIA_LPM_MASK,
+                               MAX77650_SBIA_LPM_DISABLED);
+       if (rv) {
+               dev_err(dev, "Unable to change the power mode\n");
+               return rv;
+       }
+
+       rv = devm_regmap_add_irq_chip(dev, map, i2c->irq,
+                                     IRQF_ONESHOT | IRQF_SHARED, 0,
+                                     &max77650_irq_chip, &irq_data);
+       if (rv) {
+               dev_err(dev, "Unable to add Regmap IRQ chip\n");
+               return rv;
+       }
+
+       domain = regmap_irq_get_domain(irq_data);
+
+       return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
+                                   max77650_cells, ARRAY_SIZE(max77650_cells),
+                                   NULL, 0, domain);
+}
+
+static const struct of_device_id max77650_of_match[] = {
+       { .compatible = "maxim,max77650" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, max77650_of_match);
+
+static struct i2c_driver max77650_i2c_driver = {
+       .driver = {
+               .name = "max77650",
+               .of_match_table = of_match_ptr(max77650_of_match),
+       },
+       .probe_new = max77650_i2c_probe,
+};
+module_i2c_driver(max77650_i2c_driver);
+
+MODULE_DESCRIPTION("MAXIM 77650/77651 multi-function core driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL v2");
index 94e3f32..1ade4c8 100644 (file)
@@ -269,6 +269,19 @@ fail_alloc:
        return ret;
 }
 
+/**
+ * mfd_add_devices - register child devices
+ *
+ * @parent:    Pointer to parent device.
+ * @id:                Can be PLATFORM_DEVID_AUTO to let the Platform API take care
+ *             of device numbering, or will be added to a device's cell_id.
+ * @cells:     Array of (struct mfd_cell)s describing child devices.
+ * @n_devs:    Number of child devices to register.
+ * @mem_base:  Parent register range resource for child devices.
+ * @irq_base:  Base of the range of virtual interrupt numbers allocated for
+ *             this MFD device. Unused if @domain is specified.
+ * @domain:    Interrupt domain to create mappings for hardware interrupts.
+ */
 int mfd_add_devices(struct device *parent, int id,
                    const struct mfd_cell *cells, int n_devs,
                    struct resource *mem_base,
index 216fbf6..9437778 100644 (file)
@@ -568,14 +568,6 @@ static int rk808_remove(struct i2c_client *client)
        return 0;
 }
 
-static const struct i2c_device_id rk808_ids[] = {
-       { "rk805" },
-       { "rk808" },
-       { "rk818" },
-       { },
-};
-MODULE_DEVICE_TABLE(i2c, rk808_ids);
-
 static struct i2c_driver rk808_i2c_driver = {
        .driver = {
                .name = "rk808",
@@ -583,7 +575,6 @@ static struct i2c_driver rk808_i2c_driver = {
        },
        .probe    = rk808_probe,
        .remove   = rk808_remove,
-       .id_table = rk808_ids,
 };
 
 module_i2c_driver(rk808_i2c_driver);
index 5213190..95473ff 100644 (file)
 #include <linux/regmap.h>
 
 static const struct mfd_cell s5m8751_devs[] = {
-       {
-               .name = "s5m8751-pmic",
-       }, {
-               .name = "s5m-charger",
-       }, {
-               .name = "s5m8751-codec",
-       },
+       { .name = "s5m8751-pmic", },
+       { .name = "s5m-charger", },
+       { .name = "s5m8751-codec", },
 };
 
 static const struct mfd_cell s5m8763_devs[] = {
-       {
-               .name = "s5m8763-pmic",
-       }, {
-               .name = "s5m-rtc",
-       }, {
-               .name = "s5m-charger",
-       },
+       { .name = "s5m8763-pmic", },
+       { .name = "s5m-rtc", },
+       { .name = "s5m-charger", },
 };
 
 static const struct mfd_cell s5m8767_devs[] = {
+       { .name = "s5m8767-pmic", },
+       { .name = "s5m-rtc", },
        {
-               .name = "s5m8767-pmic",
-       }, {
-               .name = "s5m-rtc",
-       }, {
                .name = "s5m8767-clk",
                .of_compatible = "samsung,s5m8767-clk",
-       }
+       },
 };
 
 static const struct mfd_cell s2mps11_devs[] = {
+       { .name = "s2mps11-regulator", },
+       { .name = "s2mps14-rtc", },
        {
-               .name = "s2mps11-regulator",
-       }, {
-               .name = "s2mps14-rtc",
-       }, {
                .name = "s2mps11-clk",
                .of_compatible = "samsung,s2mps11-clk",
-       }
+       },
 };
 
 static const struct mfd_cell s2mps13_devs[] = {
@@ -79,37 +67,30 @@ static const struct mfd_cell s2mps13_devs[] = {
 };
 
 static const struct mfd_cell s2mps14_devs[] = {
+       { .name = "s2mps14-regulator", },
+       { .name = "s2mps14-rtc", },
        {
-               .name = "s2mps14-regulator",
-       }, {
-               .name = "s2mps14-rtc",
-       }, {
                .name = "s2mps14-clk",
                .of_compatible = "samsung,s2mps14-clk",
-       }
+       },
 };
 
 static const struct mfd_cell s2mps15_devs[] = {
+       { .name = "s2mps15-regulator", },
+       { .name = "s2mps15-rtc", },
        {
-               .name = "s2mps15-regulator",
-       }, {
-               .name = "s2mps15-rtc",
-       }, {
                .name = "s2mps13-clk",
                .of_compatible = "samsung,s2mps13-clk",
        },
 };
 
 static const struct mfd_cell s2mpa01_devs[] = {
-       {
-               .name = "s2mpa01-pmic",
-       },
+       { .name = "s2mpa01-pmic", },
+       { .name = "s2mps14-rtc", },
 };
 
 static const struct mfd_cell s2mpu02_devs[] = {
-       {
-               .name = "s2mpu02-regulator",
-       },
+       { .name = "s2mpu02-regulator", },
 };
 
 #ifdef CONFIG_OF
index ad00990..a98c5d1 100644 (file)
@@ -455,6 +455,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
        case S5M8767X:
                sec_irq_chip = &s5m8767_irq_chip;
                break;
+       case S2MPA01:
+               sec_irq_chip = &s2mps14_irq_chip;
+               break;
        case S2MPS11X:
                sec_irq_chip = &s2mps11_irq_chip;
                break;
index 36b96fe..0ae27cd 100644 (file)
@@ -80,8 +80,6 @@ struct ssbi {
        int (*write)(struct ssbi *, u16 addr, const u8 *buf, int len);
 };
 
-#define to_ssbi(dev)   platform_get_drvdata(to_platform_device(dev))
-
 static inline u32 ssbi_readl(struct ssbi *ssbi, u32 reg)
 {
        return readl(ssbi->base + reg);
@@ -243,7 +241,7 @@ err:
 
 int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len)
 {
-       struct ssbi *ssbi = to_ssbi(dev);
+       struct ssbi *ssbi = dev_get_drvdata(dev);
        unsigned long flags;
        int ret;
 
@@ -257,7 +255,7 @@ EXPORT_SYMBOL_GPL(ssbi_read);
 
 int ssbi_write(struct device *dev, u16 addr, const u8 *buf, int len)
 {
-       struct ssbi *ssbi = to_ssbi(dev);
+       struct ssbi *ssbi = dev_get_drvdata(dev);
        unsigned long flags;
        int ret;
 
diff --git a/drivers/mfd/stmfx.c b/drivers/mfd/stmfx.c
new file mode 100644 (file)
index 0000000..fe8efba
--- /dev/null
@@ -0,0 +1,545 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for STMicroelectronics Multi-Function eXpander (STMFX) core
+ *
+ * Copyright (C) 2019 STMicroelectronics
+ * Author(s): Amelie Delaunay <amelie.delaunay@st.com>.
+ */
+#include <linux/bitfield.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/stmfx.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+
+static bool stmfx_reg_volatile(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case STMFX_REG_SYS_CTRL:
+       case STMFX_REG_IRQ_SRC_EN:
+       case STMFX_REG_IRQ_PENDING:
+       case STMFX_REG_IRQ_GPI_PENDING1:
+       case STMFX_REG_IRQ_GPI_PENDING2:
+       case STMFX_REG_IRQ_GPI_PENDING3:
+       case STMFX_REG_GPIO_STATE1:
+       case STMFX_REG_GPIO_STATE2:
+       case STMFX_REG_GPIO_STATE3:
+       case STMFX_REG_IRQ_GPI_SRC1:
+       case STMFX_REG_IRQ_GPI_SRC2:
+       case STMFX_REG_IRQ_GPI_SRC3:
+       case STMFX_REG_GPO_SET1:
+       case STMFX_REG_GPO_SET2:
+       case STMFX_REG_GPO_SET3:
+       case STMFX_REG_GPO_CLR1:
+       case STMFX_REG_GPO_CLR2:
+       case STMFX_REG_GPO_CLR3:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool stmfx_reg_writeable(struct device *dev, unsigned int reg)
+{
+       return (reg >= STMFX_REG_SYS_CTRL);
+}
+
+static const struct regmap_config stmfx_regmap_config = {
+       .reg_bits       = 8,
+       .reg_stride     = 1,
+       .val_bits       = 8,
+       .max_register   = STMFX_REG_MAX,
+       .volatile_reg   = stmfx_reg_volatile,
+       .writeable_reg  = stmfx_reg_writeable,
+       .cache_type     = REGCACHE_RBTREE,
+};
+
+static const struct resource stmfx_pinctrl_resources[] = {
+       DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_GPIO),
+};
+
+static const struct resource stmfx_idd_resources[] = {
+       DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_IDD),
+       DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_ERROR),
+};
+
+static const struct resource stmfx_ts_resources[] = {
+       DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_DET),
+       DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_NE),
+       DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_TH),
+       DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_FULL),
+       DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_OVF),
+};
+
+static struct mfd_cell stmfx_cells[] = {
+       {
+               .of_compatible = "st,stmfx-0300-pinctrl",
+               .name = "stmfx-pinctrl",
+               .resources = stmfx_pinctrl_resources,
+               .num_resources = ARRAY_SIZE(stmfx_pinctrl_resources),
+       },
+       {
+               .of_compatible = "st,stmfx-0300-idd",
+               .name = "stmfx-idd",
+               .resources = stmfx_idd_resources,
+               .num_resources = ARRAY_SIZE(stmfx_idd_resources),
+       },
+       {
+               .of_compatible = "st,stmfx-0300-ts",
+               .name = "stmfx-ts",
+               .resources = stmfx_ts_resources,
+               .num_resources = ARRAY_SIZE(stmfx_ts_resources),
+       },
+};
+
+static u8 stmfx_func_to_mask(u32 func)
+{
+       u8 mask = 0;
+
+       if (func & STMFX_FUNC_GPIO)
+               mask |= STMFX_REG_SYS_CTRL_GPIO_EN;
+
+       if ((func & STMFX_FUNC_ALTGPIO_LOW) || (func & STMFX_FUNC_ALTGPIO_HIGH))
+               mask |= STMFX_REG_SYS_CTRL_ALTGPIO_EN;
+
+       if (func & STMFX_FUNC_TS)
+               mask |= STMFX_REG_SYS_CTRL_TS_EN;
+
+       if (func & STMFX_FUNC_IDD)
+               mask |= STMFX_REG_SYS_CTRL_IDD_EN;
+
+       return mask;
+}
+
+int stmfx_function_enable(struct stmfx *stmfx, u32 func)
+{
+       u32 sys_ctrl;
+       u8 mask;
+       int ret;
+
+       ret = regmap_read(stmfx->map, STMFX_REG_SYS_CTRL, &sys_ctrl);
+       if (ret)
+               return ret;
+
+       /*
+        * IDD and TS have priority in STMFX FW, so if IDD and TS are enabled,
+        * ALTGPIO function is disabled by STMFX FW. If IDD or TS is enabled,
+        * the number of aGPIO available decreases. To avoid GPIO management
+        * disturbance, abort IDD or TS function enable in this case.
+        */
+       if (((func & STMFX_FUNC_IDD) || (func & STMFX_FUNC_TS)) &&
+           (sys_ctrl & STMFX_REG_SYS_CTRL_ALTGPIO_EN)) {
+               dev_err(stmfx->dev, "ALTGPIO function already enabled\n");
+               return -EBUSY;
+       }
+
+       /* If TS is enabled, aGPIO[3:0] cannot be used */
+       if ((func & STMFX_FUNC_ALTGPIO_LOW) &&
+           (sys_ctrl & STMFX_REG_SYS_CTRL_TS_EN)) {
+               dev_err(stmfx->dev, "TS in use, aGPIO[3:0] unavailable\n");
+               return -EBUSY;
+       }
+
+       /* If IDD is enabled, aGPIO[7:4] cannot be used */
+       if ((func & STMFX_FUNC_ALTGPIO_HIGH) &&
+           (sys_ctrl & STMFX_REG_SYS_CTRL_IDD_EN)) {
+               dev_err(stmfx->dev, "IDD in use, aGPIO[7:4] unavailable\n");
+               return -EBUSY;
+       }
+
+       mask = stmfx_func_to_mask(func);
+
+       return regmap_update_bits(stmfx->map, STMFX_REG_SYS_CTRL, mask, mask);
+}
+EXPORT_SYMBOL_GPL(stmfx_function_enable);
+
+int stmfx_function_disable(struct stmfx *stmfx, u32 func)
+{
+       u8 mask = stmfx_func_to_mask(func);
+
+       return regmap_update_bits(stmfx->map, STMFX_REG_SYS_CTRL, mask, 0);
+}
+EXPORT_SYMBOL_GPL(stmfx_function_disable);
+
+static void stmfx_irq_bus_lock(struct irq_data *data)
+{
+       struct stmfx *stmfx = irq_data_get_irq_chip_data(data);
+
+       mutex_lock(&stmfx->lock);
+}
+
+static void stmfx_irq_bus_sync_unlock(struct irq_data *data)
+{
+       struct stmfx *stmfx = irq_data_get_irq_chip_data(data);
+
+       regmap_write(stmfx->map, STMFX_REG_IRQ_SRC_EN, stmfx->irq_src);
+
+       mutex_unlock(&stmfx->lock);
+}
+
+static void stmfx_irq_mask(struct irq_data *data)
+{
+       struct stmfx *stmfx = irq_data_get_irq_chip_data(data);
+
+       stmfx->irq_src &= ~BIT(data->hwirq % 8);
+}
+
+static void stmfx_irq_unmask(struct irq_data *data)
+{
+       struct stmfx *stmfx = irq_data_get_irq_chip_data(data);
+
+       stmfx->irq_src |= BIT(data->hwirq % 8);
+}
+
+static struct irq_chip stmfx_irq_chip = {
+       .name                   = "stmfx-core",
+       .irq_bus_lock           = stmfx_irq_bus_lock,
+       .irq_bus_sync_unlock    = stmfx_irq_bus_sync_unlock,
+       .irq_mask               = stmfx_irq_mask,
+       .irq_unmask             = stmfx_irq_unmask,
+};
+
+static irqreturn_t stmfx_irq_handler(int irq, void *data)
+{
+       struct stmfx *stmfx = data;
+       unsigned long n, pending;
+       u32 ack;
+       int ret;
+
+       ret = regmap_read(stmfx->map, STMFX_REG_IRQ_PENDING,
+                         (u32 *)&pending);
+       if (ret)
+               return IRQ_NONE;
+
+       /*
+        * There is no ACK for GPIO, MFX_REG_IRQ_PENDING_GPIO is a logical OR
+        * of MFX_REG_IRQ_GPI _PENDING1/_PENDING2/_PENDING3
+        */
+       ack = pending & ~BIT(STMFX_REG_IRQ_SRC_EN_GPIO);
+       if (ack) {
+               ret = regmap_write(stmfx->map, STMFX_REG_IRQ_ACK, ack);
+               if (ret)
+                       return IRQ_NONE;
+       }
+
+       for_each_set_bit(n, &pending, STMFX_REG_IRQ_SRC_MAX)
+               handle_nested_irq(irq_find_mapping(stmfx->irq_domain, n));
+
+       return IRQ_HANDLED;
+}
+
+static int stmfx_irq_map(struct irq_domain *d, unsigned int virq,
+                        irq_hw_number_t hwirq)
+{
+       irq_set_chip_data(virq, d->host_data);
+       irq_set_chip_and_handler(virq, &stmfx_irq_chip, handle_simple_irq);
+       irq_set_nested_thread(virq, 1);
+       irq_set_noprobe(virq);
+
+       return 0;
+}
+
+static void stmfx_irq_unmap(struct irq_domain *d, unsigned int virq)
+{
+       irq_set_chip_and_handler(virq, NULL, NULL);
+       irq_set_chip_data(virq, NULL);
+}
+
+static const struct irq_domain_ops stmfx_irq_ops = {
+       .map    = stmfx_irq_map,
+       .unmap  = stmfx_irq_unmap,
+};
+
+static void stmfx_irq_exit(struct i2c_client *client)
+{
+       struct stmfx *stmfx = i2c_get_clientdata(client);
+       int hwirq;
+
+       for (hwirq = 0; hwirq < STMFX_REG_IRQ_SRC_MAX; hwirq++)
+               irq_dispose_mapping(irq_find_mapping(stmfx->irq_domain, hwirq));
+
+       irq_domain_remove(stmfx->irq_domain);
+}
+
+static int stmfx_irq_init(struct i2c_client *client)
+{
+       struct stmfx *stmfx = i2c_get_clientdata(client);
+       u32 irqoutpin = 0, irqtrigger;
+       int ret;
+
+       stmfx->irq_domain = irq_domain_add_simple(stmfx->dev->of_node,
+                                                 STMFX_REG_IRQ_SRC_MAX, 0,
+                                                 &stmfx_irq_ops, stmfx);
+       if (!stmfx->irq_domain) {
+               dev_err(stmfx->dev, "Failed to create IRQ domain\n");
+               return -EINVAL;
+       }
+
+       if (!of_property_read_bool(stmfx->dev->of_node, "drive-open-drain"))
+               irqoutpin |= STMFX_REG_IRQ_OUT_PIN_TYPE;
+
+       irqtrigger = irq_get_trigger_type(client->irq);
+       if ((irqtrigger & IRQ_TYPE_EDGE_RISING) ||
+           (irqtrigger & IRQ_TYPE_LEVEL_HIGH))
+               irqoutpin |= STMFX_REG_IRQ_OUT_PIN_POL;
+
+       ret = regmap_write(stmfx->map, STMFX_REG_IRQ_OUT_PIN, irqoutpin);
+       if (ret)
+               return ret;
+
+       ret = devm_request_threaded_irq(stmfx->dev, client->irq,
+                                       NULL, stmfx_irq_handler,
+                                       irqtrigger | IRQF_ONESHOT,
+                                       "stmfx", stmfx);
+       if (ret)
+               stmfx_irq_exit(client);
+
+       return ret;
+}
+
+static int stmfx_chip_reset(struct stmfx *stmfx)
+{
+       int ret;
+
+       ret = regmap_write(stmfx->map, STMFX_REG_SYS_CTRL,
+                          STMFX_REG_SYS_CTRL_SWRST);
+       if (ret)
+               return ret;
+
+       msleep(STMFX_BOOT_TIME_MS);
+
+       return ret;
+}
+
+static int stmfx_chip_init(struct i2c_client *client)
+{
+       struct stmfx *stmfx = i2c_get_clientdata(client);
+       u32 id;
+       u8 version[2];
+       int ret;
+
+       stmfx->vdd = devm_regulator_get_optional(&client->dev, "vdd");
+       ret = PTR_ERR_OR_ZERO(stmfx->vdd);
+       if (ret == -ENODEV) {
+               stmfx->vdd = NULL;
+       } else if (ret == -EPROBE_DEFER) {
+               return ret;
+       } else if (ret) {
+               dev_err(&client->dev, "Failed to get VDD regulator: %d\n", ret);
+               return ret;
+       }
+
+       if (stmfx->vdd) {
+               ret = regulator_enable(stmfx->vdd);
+               if (ret) {
+                       dev_err(&client->dev, "VDD enable failed: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       ret = regmap_read(stmfx->map, STMFX_REG_CHIP_ID, &id);
+       if (ret) {
+               dev_err(&client->dev, "Error reading chip ID: %d\n", ret);
+               goto err;
+       }
+
+       /*
+        * Check that ID is the complement of the I2C address:
+        * STMFX I2C address follows the 7-bit format (MSB), that's why
+        * client->addr is shifted.
+        *
+        * STMFX_I2C_ADDR|       STMFX         |        Linux
+        *   input pin   | I2C device address  | I2C device address
+        *---------------------------------------------------------
+        *       0       | b: 1000 010x h:0x84 |       0x42
+        *       1       | b: 1000 011x h:0x86 |       0x43
+        */
+       if (FIELD_GET(STMFX_REG_CHIP_ID_MASK, ~id) != (client->addr << 1)) {
+               dev_err(&client->dev, "Unknown chip ID: %#x\n", id);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       ret = regmap_bulk_read(stmfx->map, STMFX_REG_FW_VERSION_MSB,
+                              version, ARRAY_SIZE(version));
+       if (ret) {
+               dev_err(&client->dev, "Error reading FW version: %d\n", ret);
+               goto err;
+       }
+
+       dev_info(&client->dev, "STMFX id: %#x, fw version: %x.%02x\n",
+                id, version[0], version[1]);
+
+       ret = stmfx_chip_reset(stmfx);
+       if (ret) {
+               dev_err(&client->dev, "Failed to reset chip: %d\n", ret);
+               goto err;
+       }
+
+       return 0;
+
+err:
+       if (stmfx->vdd)
+               return regulator_disable(stmfx->vdd);
+
+       return ret;
+}
+
+static int stmfx_chip_exit(struct i2c_client *client)
+{
+       struct stmfx *stmfx = i2c_get_clientdata(client);
+
+       regmap_write(stmfx->map, STMFX_REG_IRQ_SRC_EN, 0);
+       regmap_write(stmfx->map, STMFX_REG_SYS_CTRL, 0);
+
+       if (stmfx->vdd)
+               return regulator_disable(stmfx->vdd);
+
+       return 0;
+}
+
+static int stmfx_probe(struct i2c_client *client,
+                      const struct i2c_device_id *id)
+{
+       struct device *dev = &client->dev;
+       struct stmfx *stmfx;
+       int ret;
+
+       stmfx = devm_kzalloc(dev, sizeof(*stmfx), GFP_KERNEL);
+       if (!stmfx)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, stmfx);
+
+       stmfx->dev = dev;
+
+       stmfx->map = devm_regmap_init_i2c(client, &stmfx_regmap_config);
+       if (IS_ERR(stmfx->map)) {
+               ret = PTR_ERR(stmfx->map);
+               dev_err(dev, "Failed to allocate register map: %d\n", ret);
+               return ret;
+       }
+
+       mutex_init(&stmfx->lock);
+
+       ret = stmfx_chip_init(client);
+       if (ret) {
+               if (ret == -ETIMEDOUT)
+                       return -EPROBE_DEFER;
+               return ret;
+       }
+
+       if (client->irq < 0) {
+               dev_err(dev, "Failed to get IRQ: %d\n", client->irq);
+               ret = client->irq;
+               goto err_chip_exit;
+       }
+
+       ret = stmfx_irq_init(client);
+       if (ret)
+               goto err_chip_exit;
+
+       ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
+                                  stmfx_cells, ARRAY_SIZE(stmfx_cells), NULL,
+                                  0, stmfx->irq_domain);
+       if (ret)
+               goto err_irq_exit;
+
+       return 0;
+
+err_irq_exit:
+       stmfx_irq_exit(client);
+err_chip_exit:
+       stmfx_chip_exit(client);
+
+       return ret;
+}
+
+static int stmfx_remove(struct i2c_client *client)
+{
+       stmfx_irq_exit(client);
+
+       return stmfx_chip_exit(client);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int stmfx_suspend(struct device *dev)
+{
+       struct stmfx *stmfx = dev_get_drvdata(dev);
+       int ret;
+
+       ret = regmap_raw_read(stmfx->map, STMFX_REG_SYS_CTRL,
+                             &stmfx->bkp_sysctrl, sizeof(stmfx->bkp_sysctrl));
+       if (ret)
+               return ret;
+
+       ret = regmap_raw_read(stmfx->map, STMFX_REG_IRQ_OUT_PIN,
+                             &stmfx->bkp_irqoutpin,
+                             sizeof(stmfx->bkp_irqoutpin));
+       if (ret)
+               return ret;
+
+       if (stmfx->vdd)
+               return regulator_disable(stmfx->vdd);
+
+       return 0;
+}
+
+static int stmfx_resume(struct device *dev)
+{
+       struct stmfx *stmfx = dev_get_drvdata(dev);
+       int ret;
+
+       if (stmfx->vdd) {
+               ret = regulator_enable(stmfx->vdd);
+               if (ret) {
+                       dev_err(stmfx->dev,
+                               "VDD enable failed: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       ret = regmap_raw_write(stmfx->map, STMFX_REG_SYS_CTRL,
+                              &stmfx->bkp_sysctrl, sizeof(stmfx->bkp_sysctrl));
+       if (ret)
+               return ret;
+
+       ret = regmap_raw_write(stmfx->map, STMFX_REG_IRQ_OUT_PIN,
+                              &stmfx->bkp_irqoutpin,
+                              sizeof(stmfx->bkp_irqoutpin));
+       if (ret)
+               return ret;
+
+       ret = regmap_raw_write(stmfx->map, STMFX_REG_IRQ_SRC_EN,
+                              &stmfx->irq_src, sizeof(stmfx->irq_src));
+       if (ret)
+               return ret;
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(stmfx_dev_pm_ops, stmfx_suspend, stmfx_resume);
+
+static const struct of_device_id stmfx_of_match[] = {
+       { .compatible = "st,stmfx-0300", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, stmfx_of_match);
+
+static struct i2c_driver stmfx_driver = {
+       .driver = {
+               .name = "stmfx-core",
+               .of_match_table = of_match_ptr(stmfx_of_match),
+               .pm = &stmfx_dev_pm_ops,
+       },
+       .probe = stmfx_probe,
+       .remove = stmfx_remove,
+};
+module_i2c_driver(stmfx_driver);
+
+MODULE_DESCRIPTION("STMFX core driver");
+MODULE_AUTHOR("Amelie Delaunay <amelie.delaunay@st.com>");
+MODULE_LICENSE("GPL v2");
index 2b658be..2f12a41 100644 (file)
@@ -148,13 +148,12 @@ static const struct of_device_id sun6i_prcm_dt_ids[] = {
 
 static int sun6i_prcm_probe(struct platform_device *pdev)
 {
-       struct device_node *np = pdev->dev.of_node;
        const struct of_device_id *match;
        const struct prcm_data *data;
        struct resource *res;
        int ret;
 
-       match = of_match_node(sun6i_prcm_dt_ids, np);
+       match = of_match_node(sun6i_prcm_dt_ids, pdev->dev.of_node);
        if (!match)
                return -EINVAL;
 
index 0ecdffb..f6922a0 100644 (file)
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/hwspinlock.h>
 #include <linux/io.h>
@@ -45,6 +46,7 @@ static const struct regmap_config syscon_regmap_config = {
 
 static struct syscon *of_syscon_register(struct device_node *np)
 {
+       struct clk *clk;
        struct syscon *syscon;
        struct regmap *regmap;
        void __iomem *base;
@@ -119,6 +121,18 @@ static struct syscon *of_syscon_register(struct device_node *np)
                goto err_regmap;
        }
 
+       clk = of_clk_get(np, 0);
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               /* clock is optional */
+               if (ret != -ENOENT)
+                       goto err_clk;
+       } else {
+               ret = regmap_mmio_attach_clk(regmap, clk);
+               if (ret)
+                       goto err_attach;
+       }
+
        syscon->regmap = regmap;
        syscon->np = np;
 
@@ -128,6 +142,11 @@ static struct syscon *of_syscon_register(struct device_node *np)
 
        return syscon;
 
+err_attach:
+       if (!IS_ERR(clk))
+               clk_put(clk);
+err_clk:
+       regmap_exit(regmap);
 err_regmap:
        iounmap(base);
 err_map:
index 43d8683..e9cfb14 100644 (file)
@@ -82,8 +82,7 @@ struct t7l66xb {
 
 static int t7l66xb_mmc_enable(struct platform_device *mmc)
 {
-       struct platform_device *dev = to_platform_device(mmc->dev.parent);
-       struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
+       struct t7l66xb *t7l66xb = dev_get_drvdata(mmc->dev.parent);
        unsigned long flags;
        u8 dev_ctl;
        int ret;
@@ -108,8 +107,7 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc)
 
 static int t7l66xb_mmc_disable(struct platform_device *mmc)
 {
-       struct platform_device *dev = to_platform_device(mmc->dev.parent);
-       struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
+       struct t7l66xb *t7l66xb = dev_get_drvdata(mmc->dev.parent);
        unsigned long flags;
        u8 dev_ctl;
 
@@ -128,16 +126,14 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc)
 
 static void t7l66xb_mmc_pwr(struct platform_device *mmc, int state)
 {
-       struct platform_device *dev = to_platform_device(mmc->dev.parent);
-       struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
+       struct t7l66xb *t7l66xb = dev_get_drvdata(mmc->dev.parent);
 
        tmio_core_mmc_pwr(t7l66xb->scr + 0x200, 0, state);
 }
 
 static void t7l66xb_mmc_clk_div(struct platform_device *mmc, int state)
 {
-       struct platform_device *dev = to_platform_device(mmc->dev.parent);
-       struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
+       struct t7l66xb *t7l66xb = dev_get_drvdata(mmc->dev.parent);
 
        tmio_core_mmc_clk_div(t7l66xb->scr + 0x200, 0, state);
 }
index 85fab37..f417c6f 100644 (file)
@@ -80,16 +80,14 @@ static int tc6387xb_resume(struct platform_device *dev)
 
 static void tc6387xb_mmc_pwr(struct platform_device *mmc, int state)
 {
-       struct platform_device *dev = to_platform_device(mmc->dev.parent);
-       struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
+       struct tc6387xb *tc6387xb = dev_get_drvdata(mmc->dev.parent);
 
        tmio_core_mmc_pwr(tc6387xb->scr + 0x200, 0, state);
 }
 
 static void tc6387xb_mmc_clk_div(struct platform_device *mmc, int state)
 {
-       struct platform_device *dev = to_platform_device(mmc->dev.parent);
-       struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
+       struct tc6387xb *tc6387xb = dev_get_drvdata(mmc->dev.parent);
 
        tmio_core_mmc_clk_div(tc6387xb->scr + 0x200, 0, state);
 }
@@ -97,8 +95,7 @@ static void tc6387xb_mmc_clk_div(struct platform_device *mmc, int state)
 
 static int tc6387xb_mmc_enable(struct platform_device *mmc)
 {
-       struct platform_device *dev      = to_platform_device(mmc->dev.parent);
-       struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
+       struct tc6387xb *tc6387xb = dev_get_drvdata(mmc->dev.parent);
 
        clk_prepare_enable(tc6387xb->clk32k);
 
@@ -110,8 +107,7 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc)
 
 static int tc6387xb_mmc_disable(struct platform_device *mmc)
 {
-       struct platform_device *dev      = to_platform_device(mmc->dev.parent);
-       struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
+       struct tc6387xb *tc6387xb = dev_get_drvdata(mmc->dev.parent);
 
        clk_disable_unprepare(tc6387xb->clk32k);
 
index 0c9f039..6943048 100644 (file)
@@ -122,14 +122,13 @@ enum {
 
 static int tc6393xb_nand_enable(struct platform_device *nand)
 {
-       struct platform_device *dev = to_platform_device(nand->dev.parent);
-       struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+       struct tc6393xb *tc6393xb = dev_get_drvdata(nand->dev.parent);
        unsigned long flags;
 
        raw_spin_lock_irqsave(&tc6393xb->lock, flags);
 
        /* SMD buffer on */
-       dev_dbg(&dev->dev, "SMD buffer on\n");
+       dev_dbg(nand->dev.parent, "SMD buffer on\n");
        tmio_iowrite8(0xff, tc6393xb->scr + SCR_GPI_BCR(1));
 
        raw_spin_unlock_irqrestore(&tc6393xb->lock, flags);
@@ -312,8 +311,7 @@ static int tc6393xb_fb_disable(struct platform_device *dev)
 
 int tc6393xb_lcd_set_power(struct platform_device *fb, bool on)
 {
-       struct platform_device *dev = to_platform_device(fb->dev.parent);
-       struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+       struct tc6393xb *tc6393xb = dev_get_drvdata(fb->dev.parent);
        u8 fer;
        unsigned long flags;
 
@@ -334,8 +332,7 @@ EXPORT_SYMBOL(tc6393xb_lcd_set_power);
 
 int tc6393xb_lcd_mode(struct platform_device *fb,
                                        const struct fb_videomode *mode) {
-       struct platform_device *dev = to_platform_device(fb->dev.parent);
-       struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+       struct tc6393xb *tc6393xb = dev_get_drvdata(fb->dev.parent);
        unsigned long flags;
 
        raw_spin_lock_irqsave(&tc6393xb->lock, flags);
@@ -351,8 +348,7 @@ EXPORT_SYMBOL(tc6393xb_lcd_mode);
 
 static int tc6393xb_mmc_enable(struct platform_device *mmc)
 {
-       struct platform_device *dev = to_platform_device(mmc->dev.parent);
-       struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+       struct tc6393xb *tc6393xb = dev_get_drvdata(mmc->dev.parent);
 
        tmio_core_mmc_enable(tc6393xb->scr + 0x200, 0,
                tc6393xb_mmc_resources[0].start & 0xfffe);
@@ -362,8 +358,7 @@ static int tc6393xb_mmc_enable(struct platform_device *mmc)
 
 static int tc6393xb_mmc_resume(struct platform_device *mmc)
 {
-       struct platform_device *dev = to_platform_device(mmc->dev.parent);
-       struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+       struct tc6393xb *tc6393xb = dev_get_drvdata(mmc->dev.parent);
 
        tmio_core_mmc_resume(tc6393xb->scr + 0x200, 0,
                tc6393xb_mmc_resources[0].start & 0xfffe);
@@ -373,16 +368,14 @@ static int tc6393xb_mmc_resume(struct platform_device *mmc)
 
 static void tc6393xb_mmc_pwr(struct platform_device *mmc, int state)
 {
-       struct platform_device *dev = to_platform_device(mmc->dev.parent);
-       struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+       struct tc6393xb *tc6393xb = dev_get_drvdata(mmc->dev.parent);
 
        tmio_core_mmc_pwr(tc6393xb->scr + 0x200, 0, state);
 }
 
 static void tc6393xb_mmc_clk_div(struct platform_device *mmc, int state)
 {
-       struct platform_device *dev = to_platform_device(mmc->dev.parent);
-       struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+       struct tc6393xb *tc6393xb = dev_get_drvdata(mmc->dev.parent);
 
        tmio_core_mmc_clk_div(tc6393xb->scr + 0x200, 0, state);
 }
index 3bd7506..f78be03 100644 (file)
@@ -27,6 +27,7 @@ static const struct of_device_id tps65912_spi_of_match_table[] = {
        { .compatible = "ti,tps65912", },
        { /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, tps65912_spi_of_match_table);
 
 static int tps65912_spi_probe(struct spi_device *spi)
 {
index 7c3c5fd..86052c5 100644 (file)
@@ -322,8 +322,19 @@ int twl6040_power(struct twl6040 *twl6040, int on)
                        }
                }
 
+               /*
+                * Register access can produce errors after power-up unless we
+                * wait at least 8ms based on measurements on duovero.
+                */
+               usleep_range(10000, 12000);
+
                /* Sync with the HW */
-               regcache_sync(twl6040->regmap);
+               ret = regcache_sync(twl6040->regmap);
+               if (ret) {
+                       dev_err(twl6040->dev, "Failed to sync with the HW: %i\n",
+                               ret);
+                       goto out;
+               }
 
                /* Default PLL configuration after power up */
                twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
index 3209ee0..b80cb6a 100644 (file)
@@ -496,30 +496,6 @@ config VEXPRESS_SYSCFG
          bus. System Configuration interface is one of the possible means
          of generating transactions on this bus.
 
-config ASPEED_P2A_CTRL
-       depends on (ARCH_ASPEED || COMPILE_TEST) && REGMAP && MFD_SYSCON
-       tristate "Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC bridge control"
-       help
-         Control Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC mappings through
-         ioctl()s, the driver also provides an interface for userspace mappings to
-         a pre-defined region.
-
-config ASPEED_LPC_CTRL
-       depends on (ARCH_ASPEED || COMPILE_TEST) && REGMAP && MFD_SYSCON
-       tristate "Aspeed ast2400/2500 HOST LPC to BMC bridge control"
-       ---help---
-         Control Aspeed ast2400/2500 HOST LPC to BMC mappings through
-         ioctl()s, the driver also provides a read/write interface to a BMC ram
-         region where the host LPC read/write region can be buffered.
-
-config ASPEED_LPC_SNOOP
-       tristate "Aspeed ast2500 HOST LPC snoop support"
-       depends on (ARCH_ASPEED || COMPILE_TEST) && REGMAP && MFD_SYSCON
-       help
-         Provides a driver to control the LPC snoop interface which
-         allows the BMC to listen on and save the data written by
-         the host to an arbitrary LPC I/O port.
-
 config PCI_ENDPOINT_TEST
        depends on PCI
        select CRC32
index c362395..b9affcd 100644 (file)
@@ -54,9 +54,6 @@ obj-$(CONFIG_GENWQE)          += genwqe/
 obj-$(CONFIG_ECHO)             += echo/
 obj-$(CONFIG_VEXPRESS_SYSCFG)  += vexpress-syscfg.o
 obj-$(CONFIG_CXL_BASE)         += cxl/
-obj-$(CONFIG_ASPEED_LPC_CTRL)  += aspeed-lpc-ctrl.o
-obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
-obj-$(CONFIG_ASPEED_P2A_CTRL)  += aspeed-p2a-ctrl.o
 obj-$(CONFIG_PCI_ENDPOINT_TEST)        += pci_endpoint_test.o
 obj-$(CONFIG_OCXL)             += ocxl/
 obj-y                          += cardreader/
diff --git a/drivers/misc/aspeed-lpc-ctrl.c b/drivers/misc/aspeed-lpc-ctrl.c
deleted file mode 100644 (file)
index a024f80..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright 2017 IBM 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.
- */
-
-#include <linux/clk.h>
-#include <linux/mfd/syscon.h>
-#include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/platform_device.h>
-#include <linux/poll.h>
-#include <linux/regmap.h>
-
-#include <linux/aspeed-lpc-ctrl.h>
-
-#define DEVICE_NAME    "aspeed-lpc-ctrl"
-
-#define HICR5 0x0
-#define HICR5_ENL2H    BIT(8)
-#define HICR5_ENFWH    BIT(10)
-
-#define HICR7 0x8
-#define HICR8 0xc
-
-struct aspeed_lpc_ctrl {
-       struct miscdevice       miscdev;
-       struct regmap           *regmap;
-       struct clk              *clk;
-       phys_addr_t             mem_base;
-       resource_size_t         mem_size;
-       u32             pnor_size;
-       u32             pnor_base;
-};
-
-static struct aspeed_lpc_ctrl *file_aspeed_lpc_ctrl(struct file *file)
-{
-       return container_of(file->private_data, struct aspeed_lpc_ctrl,
-                       miscdev);
-}
-
-static int aspeed_lpc_ctrl_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct aspeed_lpc_ctrl *lpc_ctrl = file_aspeed_lpc_ctrl(file);
-       unsigned long vsize = vma->vm_end - vma->vm_start;
-       pgprot_t prot = vma->vm_page_prot;
-
-       if (vma->vm_pgoff + vsize > lpc_ctrl->mem_base + lpc_ctrl->mem_size)
-               return -EINVAL;
-
-       /* ast2400/2500 AHB accesses are not cache coherent */
-       prot = pgprot_noncached(prot);
-
-       if (remap_pfn_range(vma, vma->vm_start,
-               (lpc_ctrl->mem_base >> PAGE_SHIFT) + vma->vm_pgoff,
-               vsize, prot))
-               return -EAGAIN;
-
-       return 0;
-}
-
-static long aspeed_lpc_ctrl_ioctl(struct file *file, unsigned int cmd,
-               unsigned long param)
-{
-       struct aspeed_lpc_ctrl *lpc_ctrl = file_aspeed_lpc_ctrl(file);
-       void __user *p = (void __user *)param;
-       struct aspeed_lpc_ctrl_mapping map;
-       u32 addr;
-       u32 size;
-       long rc;
-
-       if (copy_from_user(&map, p, sizeof(map)))
-               return -EFAULT;
-
-       if (map.flags != 0)
-               return -EINVAL;
-
-       switch (cmd) {
-       case ASPEED_LPC_CTRL_IOCTL_GET_SIZE:
-               /* The flash windows don't report their size */
-               if (map.window_type != ASPEED_LPC_CTRL_WINDOW_MEMORY)
-                       return -EINVAL;
-
-               /* Support more than one window id in the future */
-               if (map.window_id != 0)
-                       return -EINVAL;
-
-               map.size = lpc_ctrl->mem_size;
-
-               return copy_to_user(p, &map, sizeof(map)) ? -EFAULT : 0;
-       case ASPEED_LPC_CTRL_IOCTL_MAP:
-
-               /*
-                * The top half of HICR7 is the MSB of the BMC address of the
-                * mapping.
-                * The bottom half of HICR7 is the MSB of the HOST LPC
-                * firmware space address of the mapping.
-                *
-                * The 1 bits in the top of half of HICR8 represent the bits
-                * (in the requested address) that should be ignored and
-                * replaced with those from the top half of HICR7.
-                * The 1 bits in the bottom half of HICR8 represent the bits
-                * (in the requested address) that should be kept and pass
-                * into the BMC address space.
-                */
-
-               /*
-                * It doesn't make sense to talk about a size or offset with
-                * low 16 bits set. Both HICR7 and HICR8 talk about the top 16
-                * bits of addresses and sizes.
-                */
-
-               if ((map.size & 0x0000ffff) || (map.offset & 0x0000ffff))
-                       return -EINVAL;
-
-               /*
-                * Because of the way the masks work in HICR8 offset has to
-                * be a multiple of size.
-                */
-               if (map.offset & (map.size - 1))
-                       return -EINVAL;
-
-               if (map.window_type == ASPEED_LPC_CTRL_WINDOW_FLASH) {
-                       addr = lpc_ctrl->pnor_base;
-                       size = lpc_ctrl->pnor_size;
-               } else if (map.window_type == ASPEED_LPC_CTRL_WINDOW_MEMORY) {
-                       addr = lpc_ctrl->mem_base;
-                       size = lpc_ctrl->mem_size;
-               } else {
-                       return -EINVAL;
-               }
-
-               /* Check overflow first! */
-               if (map.offset + map.size < map.offset ||
-                       map.offset + map.size > size)
-                       return -EINVAL;
-
-               if (map.size == 0 || map.size > size)
-                       return -EINVAL;
-
-               addr += map.offset;
-
-               /*
-                * addr (host lpc address) is safe regardless of values. This
-                * simply changes the address the host has to request on its
-                * side of the LPC bus. This cannot impact the hosts own
-                * memory space by surprise as LPC specific accessors are
-                * required. The only strange thing that could be done is
-                * setting the lower 16 bits but the shift takes care of that.
-                */
-
-               rc = regmap_write(lpc_ctrl->regmap, HICR7,
-                               (addr | (map.addr >> 16)));
-               if (rc)
-                       return rc;
-
-               rc = regmap_write(lpc_ctrl->regmap, HICR8,
-                               (~(map.size - 1)) | ((map.size >> 16) - 1));
-               if (rc)
-                       return rc;
-
-               /*
-                * Enable LPC FHW cycles. This is required for the host to
-                * access the regions specified.
-                */
-               return regmap_update_bits(lpc_ctrl->regmap, HICR5,
-                               HICR5_ENFWH | HICR5_ENL2H,
-                               HICR5_ENFWH | HICR5_ENL2H);
-       }
-
-       return -EINVAL;
-}
-
-static const struct file_operations aspeed_lpc_ctrl_fops = {
-       .owner          = THIS_MODULE,
-       .mmap           = aspeed_lpc_ctrl_mmap,
-       .unlocked_ioctl = aspeed_lpc_ctrl_ioctl,
-};
-
-static int aspeed_lpc_ctrl_probe(struct platform_device *pdev)
-{
-       struct aspeed_lpc_ctrl *lpc_ctrl;
-       struct device_node *node;
-       struct resource resm;
-       struct device *dev;
-       int rc;
-
-       dev = &pdev->dev;
-
-       lpc_ctrl = devm_kzalloc(dev, sizeof(*lpc_ctrl), GFP_KERNEL);
-       if (!lpc_ctrl)
-               return -ENOMEM;
-
-       node = of_parse_phandle(dev->of_node, "flash", 0);
-       if (!node) {
-               dev_err(dev, "Didn't find host pnor flash node\n");
-               return -ENODEV;
-       }
-
-       rc = of_address_to_resource(node, 1, &resm);
-       of_node_put(node);
-       if (rc) {
-               dev_err(dev, "Couldn't address to resource for flash\n");
-               return rc;
-       }
-
-       lpc_ctrl->pnor_size = resource_size(&resm);
-       lpc_ctrl->pnor_base = resm.start;
-
-       dev_set_drvdata(&pdev->dev, lpc_ctrl);
-
-       node = of_parse_phandle(dev->of_node, "memory-region", 0);
-       if (!node) {
-               dev_err(dev, "Didn't find reserved memory\n");
-               return -EINVAL;
-       }
-
-       rc = of_address_to_resource(node, 0, &resm);
-       of_node_put(node);
-       if (rc) {
-               dev_err(dev, "Couldn't address to resource for reserved memory\n");
-               return -ENOMEM;
-       }
-
-       lpc_ctrl->mem_size = resource_size(&resm);
-       lpc_ctrl->mem_base = resm.start;
-
-       lpc_ctrl->regmap = syscon_node_to_regmap(
-                       pdev->dev.parent->of_node);
-       if (IS_ERR(lpc_ctrl->regmap)) {
-               dev_err(dev, "Couldn't get regmap\n");
-               return -ENODEV;
-       }
-
-       lpc_ctrl->clk = devm_clk_get(dev, NULL);
-       if (IS_ERR(lpc_ctrl->clk)) {
-               dev_err(dev, "couldn't get clock\n");
-               return PTR_ERR(lpc_ctrl->clk);
-       }
-       rc = clk_prepare_enable(lpc_ctrl->clk);
-       if (rc) {
-               dev_err(dev, "couldn't enable clock\n");
-               return rc;
-       }
-
-       lpc_ctrl->miscdev.minor = MISC_DYNAMIC_MINOR;
-       lpc_ctrl->miscdev.name = DEVICE_NAME;
-       lpc_ctrl->miscdev.fops = &aspeed_lpc_ctrl_fops;
-       lpc_ctrl->miscdev.parent = dev;
-       rc = misc_register(&lpc_ctrl->miscdev);
-       if (rc) {
-               dev_err(dev, "Unable to register device\n");
-               goto err;
-       }
-
-       dev_info(dev, "Loaded at %pr\n", &resm);
-
-       return 0;
-
-err:
-       clk_disable_unprepare(lpc_ctrl->clk);
-       return rc;
-}
-
-static int aspeed_lpc_ctrl_remove(struct platform_device *pdev)
-{
-       struct aspeed_lpc_ctrl *lpc_ctrl = dev_get_drvdata(&pdev->dev);
-
-       misc_deregister(&lpc_ctrl->miscdev);
-       clk_disable_unprepare(lpc_ctrl->clk);
-
-       return 0;
-}
-
-static const struct of_device_id aspeed_lpc_ctrl_match[] = {
-       { .compatible = "aspeed,ast2400-lpc-ctrl" },
-       { .compatible = "aspeed,ast2500-lpc-ctrl" },
-       { },
-};
-
-static struct platform_driver aspeed_lpc_ctrl_driver = {
-       .driver = {
-               .name           = DEVICE_NAME,
-               .of_match_table = aspeed_lpc_ctrl_match,
-       },
-       .probe = aspeed_lpc_ctrl_probe,
-       .remove = aspeed_lpc_ctrl_remove,
-};
-
-module_platform_driver(aspeed_lpc_ctrl_driver);
-
-MODULE_DEVICE_TABLE(of, aspeed_lpc_ctrl_match);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Cyril Bur <cyrilbur@gmail.com>");
-MODULE_DESCRIPTION("Control for aspeed 2400/2500 LPC HOST to BMC mappings");
diff --git a/drivers/misc/aspeed-lpc-snoop.c b/drivers/misc/aspeed-lpc-snoop.c
deleted file mode 100644 (file)
index 2feb434..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Copyright 2017 Google 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.
- *
- * Provides a simple driver to control the ASPEED LPC snoop interface which
- * allows the BMC to listen on and save the data written by
- * the host to an arbitrary LPC I/O port.
- *
- * Typically used by the BMC to "watch" host boot progress via port
- * 0x80 writes made by the BIOS during the boot process.
- */
-
-#include <linux/bitops.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/kfifo.h>
-#include <linux/mfd/syscon.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/poll.h>
-#include <linux/regmap.h>
-
-#define DEVICE_NAME    "aspeed-lpc-snoop"
-
-#define NUM_SNOOP_CHANNELS 2
-#define SNOOP_FIFO_SIZE 2048
-
-#define HICR5  0x0
-#define HICR5_EN_SNP0W         BIT(0)
-#define HICR5_ENINT_SNP0W      BIT(1)
-#define HICR5_EN_SNP1W         BIT(2)
-#define HICR5_ENINT_SNP1W      BIT(3)
-
-#define HICR6  0x4
-#define HICR6_STR_SNP0W                BIT(0)
-#define HICR6_STR_SNP1W                BIT(1)
-#define SNPWADR        0x10
-#define SNPWADR_CH0_MASK       GENMASK(15, 0)
-#define SNPWADR_CH0_SHIFT      0
-#define SNPWADR_CH1_MASK       GENMASK(31, 16)
-#define SNPWADR_CH1_SHIFT      16
-#define SNPWDR 0x14
-#define SNPWDR_CH0_MASK                GENMASK(7, 0)
-#define SNPWDR_CH0_SHIFT       0
-#define SNPWDR_CH1_MASK                GENMASK(15, 8)
-#define SNPWDR_CH1_SHIFT       8
-#define HICRB  0x80
-#define HICRB_ENSNP0D          BIT(14)
-#define HICRB_ENSNP1D          BIT(15)
-
-struct aspeed_lpc_snoop_model_data {
-       /* The ast2400 has bits 14 and 15 as reserved, whereas the ast2500
-        * can use them.
-        */
-       unsigned int has_hicrb_ensnp;
-};
-
-struct aspeed_lpc_snoop_channel {
-       struct kfifo            fifo;
-       wait_queue_head_t       wq;
-       struct miscdevice       miscdev;
-};
-
-struct aspeed_lpc_snoop {
-       struct regmap           *regmap;
-       int                     irq;
-       struct aspeed_lpc_snoop_channel chan[NUM_SNOOP_CHANNELS];
-};
-
-static struct aspeed_lpc_snoop_channel *snoop_file_to_chan(struct file *file)
-{
-       return container_of(file->private_data,
-                           struct aspeed_lpc_snoop_channel,
-                           miscdev);
-}
-
-static ssize_t snoop_file_read(struct file *file, char __user *buffer,
-                               size_t count, loff_t *ppos)
-{
-       struct aspeed_lpc_snoop_channel *chan = snoop_file_to_chan(file);
-       unsigned int copied;
-       int ret = 0;
-
-       if (kfifo_is_empty(&chan->fifo)) {
-               if (file->f_flags & O_NONBLOCK)
-                       return -EAGAIN;
-               ret = wait_event_interruptible(chan->wq,
-                               !kfifo_is_empty(&chan->fifo));
-               if (ret == -ERESTARTSYS)
-                       return -EINTR;
-       }
-       ret = kfifo_to_user(&chan->fifo, buffer, count, &copied);
-
-       return ret ? ret : copied;
-}
-
-static unsigned int snoop_file_poll(struct file *file,
-                                   struct poll_table_struct *pt)
-{
-       struct aspeed_lpc_snoop_channel *chan = snoop_file_to_chan(file);
-
-       poll_wait(file, &chan->wq, pt);
-       return !kfifo_is_empty(&chan->fifo) ? POLLIN : 0;
-}
-
-static const struct file_operations snoop_fops = {
-       .owner  = THIS_MODULE,
-       .read   = snoop_file_read,
-       .poll   = snoop_file_poll,
-       .llseek = noop_llseek,
-};
-
-/* Save a byte to a FIFO and discard the oldest byte if FIFO is full */
-static void put_fifo_with_discard(struct aspeed_lpc_snoop_channel *chan, u8 val)
-{
-       if (!kfifo_initialized(&chan->fifo))
-               return;
-       if (kfifo_is_full(&chan->fifo))
-               kfifo_skip(&chan->fifo);
-       kfifo_put(&chan->fifo, val);
-       wake_up_interruptible(&chan->wq);
-}
-
-static irqreturn_t aspeed_lpc_snoop_irq(int irq, void *arg)
-{
-       struct aspeed_lpc_snoop *lpc_snoop = arg;
-       u32 reg, data;
-
-       if (regmap_read(lpc_snoop->regmap, HICR6, &reg))
-               return IRQ_NONE;
-
-       /* Check if one of the snoop channels is interrupting */
-       reg &= (HICR6_STR_SNP0W | HICR6_STR_SNP1W);
-       if (!reg)
-               return IRQ_NONE;
-
-       /* Ack pending IRQs */
-       regmap_write(lpc_snoop->regmap, HICR6, reg);
-
-       /* Read and save most recent snoop'ed data byte to FIFO */
-       regmap_read(lpc_snoop->regmap, SNPWDR, &data);
-
-       if (reg & HICR6_STR_SNP0W) {
-               u8 val = (data & SNPWDR_CH0_MASK) >> SNPWDR_CH0_SHIFT;
-
-               put_fifo_with_discard(&lpc_snoop->chan[0], val);
-       }
-       if (reg & HICR6_STR_SNP1W) {
-               u8 val = (data & SNPWDR_CH1_MASK) >> SNPWDR_CH1_SHIFT;
-
-               put_fifo_with_discard(&lpc_snoop->chan[1], val);
-       }
-
-       return IRQ_HANDLED;
-}
-
-static int aspeed_lpc_snoop_config_irq(struct aspeed_lpc_snoop *lpc_snoop,
-                                      struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       int rc;
-
-       lpc_snoop->irq = platform_get_irq(pdev, 0);
-       if (!lpc_snoop->irq)
-               return -ENODEV;
-
-       rc = devm_request_irq(dev, lpc_snoop->irq,
-                             aspeed_lpc_snoop_irq, IRQF_SHARED,
-                             DEVICE_NAME, lpc_snoop);
-       if (rc < 0) {
-               dev_warn(dev, "Unable to request IRQ %d\n", lpc_snoop->irq);
-               lpc_snoop->irq = 0;
-               return rc;
-       }
-
-       return 0;
-}
-
-static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
-                                  struct device *dev,
-                                  int channel, u16 lpc_port)
-{
-       int rc = 0;
-       u32 hicr5_en, snpwadr_mask, snpwadr_shift, hicrb_en;
-       const struct aspeed_lpc_snoop_model_data *model_data =
-               of_device_get_match_data(dev);
-
-       init_waitqueue_head(&lpc_snoop->chan[channel].wq);
-       /* Create FIFO datastructure */
-       rc = kfifo_alloc(&lpc_snoop->chan[channel].fifo,
-                        SNOOP_FIFO_SIZE, GFP_KERNEL);
-       if (rc)
-               return rc;
-
-       lpc_snoop->chan[channel].miscdev.minor = MISC_DYNAMIC_MINOR;
-       lpc_snoop->chan[channel].miscdev.name =
-               devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, channel);
-       lpc_snoop->chan[channel].miscdev.fops = &snoop_fops;
-       lpc_snoop->chan[channel].miscdev.parent = dev;
-       rc = misc_register(&lpc_snoop->chan[channel].miscdev);
-       if (rc)
-               return rc;
-
-       /* Enable LPC snoop channel at requested port */
-       switch (channel) {
-       case 0:
-               hicr5_en = HICR5_EN_SNP0W | HICR5_ENINT_SNP0W;
-               snpwadr_mask = SNPWADR_CH0_MASK;
-               snpwadr_shift = SNPWADR_CH0_SHIFT;
-               hicrb_en = HICRB_ENSNP0D;
-               break;
-       case 1:
-               hicr5_en = HICR5_EN_SNP1W | HICR5_ENINT_SNP1W;
-               snpwadr_mask = SNPWADR_CH1_MASK;
-               snpwadr_shift = SNPWADR_CH1_SHIFT;
-               hicrb_en = HICRB_ENSNP1D;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       regmap_update_bits(lpc_snoop->regmap, HICR5, hicr5_en, hicr5_en);
-       regmap_update_bits(lpc_snoop->regmap, SNPWADR, snpwadr_mask,
-                          lpc_port << snpwadr_shift);
-       if (model_data->has_hicrb_ensnp)
-               regmap_update_bits(lpc_snoop->regmap, HICRB,
-                               hicrb_en, hicrb_en);
-
-       return rc;
-}
-
-static void aspeed_lpc_disable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
-                                    int channel)
-{
-       switch (channel) {
-       case 0:
-               regmap_update_bits(lpc_snoop->regmap, HICR5,
-                                  HICR5_EN_SNP0W | HICR5_ENINT_SNP0W,
-                                  0);
-               break;
-       case 1:
-               regmap_update_bits(lpc_snoop->regmap, HICR5,
-                                  HICR5_EN_SNP1W | HICR5_ENINT_SNP1W,
-                                  0);
-               break;
-       default:
-               return;
-       }
-
-       kfifo_free(&lpc_snoop->chan[channel].fifo);
-       misc_deregister(&lpc_snoop->chan[channel].miscdev);
-}
-
-static int aspeed_lpc_snoop_probe(struct platform_device *pdev)
-{
-       struct aspeed_lpc_snoop *lpc_snoop;
-       struct device *dev;
-       u32 port;
-       int rc;
-
-       dev = &pdev->dev;
-
-       lpc_snoop = devm_kzalloc(dev, sizeof(*lpc_snoop), GFP_KERNEL);
-       if (!lpc_snoop)
-               return -ENOMEM;
-
-       lpc_snoop->regmap = syscon_node_to_regmap(
-                       pdev->dev.parent->of_node);
-       if (IS_ERR(lpc_snoop->regmap)) {
-               dev_err(dev, "Couldn't get regmap\n");
-               return -ENODEV;
-       }
-
-       dev_set_drvdata(&pdev->dev, lpc_snoop);
-
-       rc = of_property_read_u32_index(dev->of_node, "snoop-ports", 0, &port);
-       if (rc) {
-               dev_err(dev, "no snoop ports configured\n");
-               return -ENODEV;
-       }
-
-       rc = aspeed_lpc_snoop_config_irq(lpc_snoop, pdev);
-       if (rc)
-               return rc;
-
-       rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 0, port);
-       if (rc)
-               return rc;
-
-       /* Configuration of 2nd snoop channel port is optional */
-       if (of_property_read_u32_index(dev->of_node, "snoop-ports",
-                                      1, &port) == 0) {
-               rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 1, port);
-               if (rc)
-                       aspeed_lpc_disable_snoop(lpc_snoop, 0);
-       }
-
-       return rc;
-}
-
-static int aspeed_lpc_snoop_remove(struct platform_device *pdev)
-{
-       struct aspeed_lpc_snoop *lpc_snoop = dev_get_drvdata(&pdev->dev);
-
-       /* Disable both snoop channels */
-       aspeed_lpc_disable_snoop(lpc_snoop, 0);
-       aspeed_lpc_disable_snoop(lpc_snoop, 1);
-
-       return 0;
-}
-
-static const struct aspeed_lpc_snoop_model_data ast2400_model_data = {
-       .has_hicrb_ensnp = 0,
-};
-
-static const struct aspeed_lpc_snoop_model_data ast2500_model_data = {
-       .has_hicrb_ensnp = 1,
-};
-
-static const struct of_device_id aspeed_lpc_snoop_match[] = {
-       { .compatible = "aspeed,ast2400-lpc-snoop",
-         .data = &ast2400_model_data },
-       { .compatible = "aspeed,ast2500-lpc-snoop",
-         .data = &ast2500_model_data },
-       { },
-};
-
-static struct platform_driver aspeed_lpc_snoop_driver = {
-       .driver = {
-               .name           = DEVICE_NAME,
-               .of_match_table = aspeed_lpc_snoop_match,
-       },
-       .probe = aspeed_lpc_snoop_probe,
-       .remove = aspeed_lpc_snoop_remove,
-};
-
-module_platform_driver(aspeed_lpc_snoop_driver);
-
-MODULE_DEVICE_TABLE(of, aspeed_lpc_snoop_match);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Robert Lippert <rlippert@google.com>");
-MODULE_DESCRIPTION("Linux driver to control Aspeed LPC snoop functionality");
diff --git a/drivers/misc/aspeed-p2a-ctrl.c b/drivers/misc/aspeed-p2a-ctrl.c
deleted file mode 100644 (file)
index b60fbea..0000000
+++ /dev/null
@@ -1,444 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright 2019 Google 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.
- *
- * Provides a simple driver to control the ASPEED P2A interface which allows
- * the host to read and write to various regions of the BMC's memory.
- */
-
-#include <linux/fs.h>
-#include <linux/io.h>
-#include <linux/mfd/syscon.h>
-#include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#include <linux/aspeed-p2a-ctrl.h>
-
-#define DEVICE_NAME    "aspeed-p2a-ctrl"
-
-/* SCU2C is a Misc. Control Register. */
-#define SCU2C 0x2c
-/* SCU180 is the PCIe Configuration Setting Control Register. */
-#define SCU180 0x180
-/* Bit 1 controls the P2A bridge, while bit 0 controls the entire VGA device
- * on the PCI bus.
- */
-#define SCU180_ENP2A BIT(1)
-
-/* The ast2400/2500 both have six ranges. */
-#define P2A_REGION_COUNT 6
-
-struct region {
-       u64 min;
-       u64 max;
-       u32 bit;
-};
-
-struct aspeed_p2a_model_data {
-       /* min, max, bit */
-       struct region regions[P2A_REGION_COUNT];
-};
-
-struct aspeed_p2a_ctrl {
-       struct miscdevice miscdev;
-       struct regmap *regmap;
-
-       const struct aspeed_p2a_model_data *config;
-
-       /* Access to these needs to be locked, held via probe, mapping ioctl,
-        * and release, remove.
-        */
-       struct mutex tracking;
-       u32 readers;
-       u32 readerwriters[P2A_REGION_COUNT];
-
-       phys_addr_t mem_base;
-       resource_size_t mem_size;
-};
-
-struct aspeed_p2a_user {
-       struct file *file;
-       struct aspeed_p2a_ctrl *parent;
-
-       /* The entire memory space is opened for reading once the bridge is
-        * enabled, therefore this needs only to be tracked once per user.
-        * If any user has it open for read, the bridge must stay enabled.
-        */
-       u32 read;
-
-       /* Each entry of the array corresponds to a P2A Region.  If the user
-        * opens for read or readwrite, the reference goes up here.  On
-        * release, this array is walked and references adjusted accordingly.
-        */
-       u32 readwrite[P2A_REGION_COUNT];
-};
-
-static void aspeed_p2a_enable_bridge(struct aspeed_p2a_ctrl *p2a_ctrl)
-{
-       regmap_update_bits(p2a_ctrl->regmap,
-               SCU180, SCU180_ENP2A, SCU180_ENP2A);
-}
-
-static void aspeed_p2a_disable_bridge(struct aspeed_p2a_ctrl *p2a_ctrl)
-{
-       regmap_update_bits(p2a_ctrl->regmap, SCU180, SCU180_ENP2A, 0);
-}
-
-static int aspeed_p2a_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       unsigned long vsize;
-       pgprot_t prot;
-       struct aspeed_p2a_user *priv = file->private_data;
-       struct aspeed_p2a_ctrl *ctrl = priv->parent;
-
-       if (ctrl->mem_base == 0 && ctrl->mem_size == 0)
-               return -EINVAL;
-
-       vsize = vma->vm_end - vma->vm_start;
-       prot = vma->vm_page_prot;
-
-       if (vma->vm_pgoff + vsize > ctrl->mem_base + ctrl->mem_size)
-               return -EINVAL;
-
-       /* ast2400/2500 AHB accesses are not cache coherent */
-       prot = pgprot_noncached(prot);
-
-       if (remap_pfn_range(vma, vma->vm_start,
-               (ctrl->mem_base >> PAGE_SHIFT) + vma->vm_pgoff,
-               vsize, prot))
-               return -EAGAIN;
-
-       return 0;
-}
-
-static bool aspeed_p2a_region_acquire(struct aspeed_p2a_user *priv,
-               struct aspeed_p2a_ctrl *ctrl,
-               struct aspeed_p2a_ctrl_mapping *map)
-{
-       int i;
-       u64 base, end;
-       bool matched = false;
-
-       base = map->addr;
-       end = map->addr + (map->length - 1);
-
-       /* If the value is a legal u32, it will find a match. */
-       for (i = 0; i < P2A_REGION_COUNT; i++) {
-               const struct region *curr = &ctrl->config->regions[i];
-
-               /* If the top of this region is lower than your base, skip it.
-                */
-               if (curr->max < base)
-                       continue;
-
-               /* If the bottom of this region is higher than your end, bail.
-                */
-               if (curr->min > end)
-                       break;
-
-               /* Lock this and update it, therefore it someone else is
-                * closing their file out, this'll preserve the increment.
-                */
-               mutex_lock(&ctrl->tracking);
-               ctrl->readerwriters[i] += 1;
-               mutex_unlock(&ctrl->tracking);
-
-               /* Track with the user, so when they close their file, we can
-                * decrement properly.
-                */
-               priv->readwrite[i] += 1;
-
-               /* Enable the region as read-write. */
-               regmap_update_bits(ctrl->regmap, SCU2C, curr->bit, 0);
-               matched = true;
-       }
-
-       return matched;
-}
-
-static long aspeed_p2a_ioctl(struct file *file, unsigned int cmd,
-               unsigned long data)
-{
-       struct aspeed_p2a_user *priv = file->private_data;
-       struct aspeed_p2a_ctrl *ctrl = priv->parent;
-       void __user *arg = (void __user *)data;
-       struct aspeed_p2a_ctrl_mapping map;
-
-       if (copy_from_user(&map, arg, sizeof(map)))
-               return -EFAULT;
-
-       switch (cmd) {
-       case ASPEED_P2A_CTRL_IOCTL_SET_WINDOW:
-               /* If they want a region to be read-only, since the entire
-                * region is read-only once enabled, we just need to track this
-                * user wants to read from the bridge, and if it's not enabled.
-                * Enable it.
-                */
-               if (map.flags == ASPEED_P2A_CTRL_READ_ONLY) {
-                       mutex_lock(&ctrl->tracking);
-                       ctrl->readers += 1;
-                       mutex_unlock(&ctrl->tracking);
-
-                       /* Track with the user, so when they close their file,
-                        * we can decrement properly.
-                        */
-                       priv->read += 1;
-               } else if (map.flags == ASPEED_P2A_CTRL_READWRITE) {
-                       /* If we don't acquire any region return error. */
-                       if (!aspeed_p2a_region_acquire(priv, ctrl, &map)) {
-                               return -EINVAL;
-                       }
-               } else {
-                       /* Invalid map flags. */
-                       return -EINVAL;
-               }
-
-               aspeed_p2a_enable_bridge(ctrl);
-               return 0;
-       case ASPEED_P2A_CTRL_IOCTL_GET_MEMORY_CONFIG:
-               /* This is a request for the memory-region and corresponding
-                * length that is used by the driver for mmap.
-                */
-
-               map.flags = 0;
-               map.addr = ctrl->mem_base;
-               map.length = ctrl->mem_size;
-
-               return copy_to_user(arg, &map, sizeof(map)) ? -EFAULT : 0;
-       }
-
-       return -EINVAL;
-}
-
-
-/*
- * When a user opens this file, we create a structure to track their mappings.
- *
- * A user can map a region as read-only (bridge enabled), or read-write (bit
- * flipped, and bridge enabled).  Either way, this tracking is used, s.t. when
- * they release the device references are handled.
- *
- * The bridge is not enabled until a user calls an ioctl to map a region,
- * simply opening the device does not enable it.
- */
-static int aspeed_p2a_open(struct inode *inode, struct file *file)
-{
-       struct aspeed_p2a_user *priv;
-
-       priv = kmalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       priv->file = file;
-       priv->read = 0;
-       memset(priv->readwrite, 0, sizeof(priv->readwrite));
-
-       /* The file's private_data is initialized to the p2a_ctrl. */
-       priv->parent = file->private_data;
-
-       /* Set the file's private_data to the user's data. */
-       file->private_data = priv;
-
-       return 0;
-}
-
-/*
- * This will close the users mappings.  It will go through what they had opened
- * for readwrite, and decrement those counts.  If at the end, this is the last
- * user, it'll close the bridge.
- */
-static int aspeed_p2a_release(struct inode *inode, struct file *file)
-{
-       int i;
-       u32 bits = 0;
-       bool open_regions = false;
-       struct aspeed_p2a_user *priv = file->private_data;
-
-       /* Lock others from changing these values until everything is updated
-        * in one pass.
-        */
-       mutex_lock(&priv->parent->tracking);
-
-       priv->parent->readers -= priv->read;
-
-       for (i = 0; i < P2A_REGION_COUNT; i++) {
-               priv->parent->readerwriters[i] -= priv->readwrite[i];
-
-               if (priv->parent->readerwriters[i] > 0)
-                       open_regions = true;
-               else
-                       bits |= priv->parent->config->regions[i].bit;
-       }
-
-       /* Setting a bit to 1 disables the region, so let's just OR with the
-        * above to disable any.
-        */
-
-       /* Note, if another user is trying to ioctl, they can't grab tracking,
-        * and therefore can't grab either register mutex.
-        * If another user is trying to close, they can't grab tracking either.
-        */
-       regmap_update_bits(priv->parent->regmap, SCU2C, bits, bits);
-
-       /* If parent->readers is zero and open windows is 0, disable the
-        * bridge.
-        */
-       if (!open_regions && priv->parent->readers == 0)
-               aspeed_p2a_disable_bridge(priv->parent);
-
-       mutex_unlock(&priv->parent->tracking);
-
-       kfree(priv);
-
-       return 0;
-}
-
-static const struct file_operations aspeed_p2a_ctrl_fops = {
-       .owner = THIS_MODULE,
-       .mmap = aspeed_p2a_mmap,
-       .unlocked_ioctl = aspeed_p2a_ioctl,
-       .open = aspeed_p2a_open,
-       .release = aspeed_p2a_release,
-};
-
-/* The regions are controlled by SCU2C */
-static void aspeed_p2a_disable_all(struct aspeed_p2a_ctrl *p2a_ctrl)
-{
-       int i;
-       u32 value = 0;
-
-       for (i = 0; i < P2A_REGION_COUNT; i++)
-               value |= p2a_ctrl->config->regions[i].bit;
-
-       regmap_update_bits(p2a_ctrl->regmap, SCU2C, value, value);
-
-       /* Disable the bridge. */
-       aspeed_p2a_disable_bridge(p2a_ctrl);
-}
-
-static int aspeed_p2a_ctrl_probe(struct platform_device *pdev)
-{
-       struct aspeed_p2a_ctrl *misc_ctrl;
-       struct device *dev;
-       struct resource resm;
-       struct device_node *node;
-       int rc = 0;
-
-       dev = &pdev->dev;
-
-       misc_ctrl = devm_kzalloc(dev, sizeof(*misc_ctrl), GFP_KERNEL);
-       if (!misc_ctrl)
-               return -ENOMEM;
-
-       mutex_init(&misc_ctrl->tracking);
-
-       /* optional. */
-       node = of_parse_phandle(dev->of_node, "memory-region", 0);
-       if (node) {
-               rc = of_address_to_resource(node, 0, &resm);
-               of_node_put(node);
-               if (rc) {
-                       dev_err(dev, "Couldn't address to resource for reserved memory\n");
-                       return -ENODEV;
-               }
-
-               misc_ctrl->mem_size = resource_size(&resm);
-               misc_ctrl->mem_base = resm.start;
-       }
-
-       misc_ctrl->regmap = syscon_node_to_regmap(pdev->dev.parent->of_node);
-       if (IS_ERR(misc_ctrl->regmap)) {
-               dev_err(dev, "Couldn't get regmap\n");
-               return -ENODEV;
-       }
-
-       misc_ctrl->config = of_device_get_match_data(dev);
-
-       dev_set_drvdata(&pdev->dev, misc_ctrl);
-
-       aspeed_p2a_disable_all(misc_ctrl);
-
-       misc_ctrl->miscdev.minor = MISC_DYNAMIC_MINOR;
-       misc_ctrl->miscdev.name = DEVICE_NAME;
-       misc_ctrl->miscdev.fops = &aspeed_p2a_ctrl_fops;
-       misc_ctrl->miscdev.parent = dev;
-
-       rc = misc_register(&misc_ctrl->miscdev);
-       if (rc)
-               dev_err(dev, "Unable to register device\n");
-
-       return rc;
-}
-
-static int aspeed_p2a_ctrl_remove(struct platform_device *pdev)
-{
-       struct aspeed_p2a_ctrl *p2a_ctrl = dev_get_drvdata(&pdev->dev);
-
-       misc_deregister(&p2a_ctrl->miscdev);
-
-       return 0;
-}
-
-#define SCU2C_DRAM     BIT(25)
-#define SCU2C_SPI      BIT(24)
-#define SCU2C_SOC      BIT(23)
-#define SCU2C_FLASH    BIT(22)
-
-static const struct aspeed_p2a_model_data ast2400_model_data = {
-       .regions = {
-               {0x00000000, 0x17FFFFFF, SCU2C_FLASH},
-               {0x18000000, 0x1FFFFFFF, SCU2C_SOC},
-               {0x20000000, 0x2FFFFFFF, SCU2C_FLASH},
-               {0x30000000, 0x3FFFFFFF, SCU2C_SPI},
-               {0x40000000, 0x5FFFFFFF, SCU2C_DRAM},
-               {0x60000000, 0xFFFFFFFF, SCU2C_SOC},
-       }
-};
-
-static const struct aspeed_p2a_model_data ast2500_model_data = {
-       .regions = {
-               {0x00000000, 0x0FFFFFFF, SCU2C_FLASH},
-               {0x10000000, 0x1FFFFFFF, SCU2C_SOC},
-               {0x20000000, 0x3FFFFFFF, SCU2C_FLASH},
-               {0x40000000, 0x5FFFFFFF, SCU2C_SOC},
-               {0x60000000, 0x7FFFFFFF, SCU2C_SPI},
-               {0x80000000, 0xFFFFFFFF, SCU2C_DRAM},
-       }
-};
-
-static const struct of_device_id aspeed_p2a_ctrl_match[] = {
-       { .compatible = "aspeed,ast2400-p2a-ctrl",
-         .data = &ast2400_model_data },
-       { .compatible = "aspeed,ast2500-p2a-ctrl",
-         .data = &ast2500_model_data },
-       { },
-};
-
-static struct platform_driver aspeed_p2a_ctrl_driver = {
-       .driver = {
-               .name           = DEVICE_NAME,
-               .of_match_table = aspeed_p2a_ctrl_match,
-       },
-       .probe = aspeed_p2a_ctrl_probe,
-       .remove = aspeed_p2a_ctrl_remove,
-};
-
-module_platform_driver(aspeed_p2a_ctrl_driver);
-
-MODULE_DEVICE_TABLE(of, aspeed_p2a_ctrl_match);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Patrick Venture <venture@google.com>");
-MODULE_DESCRIPTION("Control for aspeed 2400/2500 P2A VGA HOST to BMC mappings");
index 25265fd..89cff9d 100644 (file)
@@ -603,7 +603,7 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, void *uaddr,
        /* pin user pages in memory */
        rc = get_user_pages_fast(data & PAGE_MASK, /* page aligned addr */
                                 m->nr_pages,
-                                m->write,              /* readable/writable */
+                                m->write ? FOLL_WRITE : 0,     /* readable/writable */
                                 m->page_list); /* ptrs to pages */
        if (rc < 0)
                goto fail_get_user_pages;
index 29582fe..7b015f2 100644 (file)
 #define PCI_ENDPOINT_TEST_IRQ_TYPE             0x24
 #define PCI_ENDPOINT_TEST_IRQ_NUMBER           0x28
 
+#define PCI_DEVICE_ID_TI_AM654                 0xb00c
+
+#define is_am654_pci_dev(pdev)         \
+               ((pdev)->device == PCI_DEVICE_ID_TI_AM654)
+
 static DEFINE_IDA(pci_endpoint_test_ida);
 
 #define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
@@ -588,6 +593,7 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
        int ret = -EINVAL;
        enum pci_barno bar;
        struct pci_endpoint_test *test = to_endpoint_test(file->private_data);
+       struct pci_dev *pdev = test->pdev;
 
        mutex_lock(&test->mutex);
        switch (cmd) {
@@ -595,6 +601,8 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
                bar = arg;
                if (bar < 0 || bar > 5)
                        goto ret;
+               if (is_am654_pci_dev(pdev) && bar == BAR_0)
+                       goto ret;
                ret = pci_endpoint_test_bar(test, bar);
                break;
        case PCITEST_LEGACY_IRQ:
@@ -662,6 +670,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
        data = (struct pci_endpoint_test_data *)ent->driver_data;
        if (data) {
                test_reg_bar = data->test_reg_bar;
+               test->test_reg_bar = test_reg_bar;
                test->alignment = data->alignment;
                irq_type = data->irq_type;
        }
@@ -785,11 +794,20 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
 }
 
+static const struct pci_endpoint_test_data am654_data = {
+       .test_reg_bar = BAR_2,
+       .alignment = SZ_64K,
+       .irq_type = IRQ_TYPE_MSI,
+};
+
 static const struct pci_device_id pci_endpoint_test_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x) },
        { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x) },
        { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0x81c0) },
        { PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, 0xedda) },
+       { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654),
+         .driver_data = (kernel_ulong_t)&am654_data
+       },
        { }
 };
 MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
index 997f925..422d08d 100644 (file)
@@ -242,7 +242,7 @@ static int vmci_host_setup_notify(struct vmci_ctx *context,
        /*
         * Lock physical page backing a given user VA.
         */
-       retval = get_user_pages_fast(uva, 1, 1, &context->notify_page);
+       retval = get_user_pages_fast(uva, 1, FOLL_WRITE, &context->notify_page);
        if (retval != 1) {
                context->notify_page = NULL;
                return VMCI_ERROR_GENERIC;
index f5f1aac..1174735 100644 (file)
@@ -659,7 +659,8 @@ static int qp_host_get_user_memory(u64 produce_uva,
        int err = VMCI_SUCCESS;
 
        retval = get_user_pages_fast((uintptr_t) produce_uva,
-                                    produce_q->kernel_if->num_pages, 1,
+                                    produce_q->kernel_if->num_pages,
+                                    FOLL_WRITE,
                                     produce_q->kernel_if->u.h.header_page);
        if (retval < (int)produce_q->kernel_if->num_pages) {
                pr_debug("get_user_pages_fast(produce) failed (retval=%d)",
@@ -671,7 +672,8 @@ static int qp_host_get_user_memory(u64 produce_uva,
        }
 
        retval = get_user_pages_fast((uintptr_t) consume_uva,
-                                    consume_q->kernel_if->num_pages, 1,
+                                    consume_q->kernel_if->num_pages,
+                                    FOLL_WRITE,
                                     consume_q->kernel_if->u.h.header_page);
        if (retval < (int)consume_q->kernel_if->num_pages) {
                pr_debug("get_user_pages_fast(consume) failed (retval=%d)",
index ec980bd..b61de36 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/of_platform.h>
index e22bbff..9cb93e1 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/slot-gpio.h>
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/unaligned.h>
 
 #include "mvsdio.h"
index c1d3f0e..e7d80c8 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <mach/hardware.h>
 #include <linux/platform_data/mmc-pxamci.h>
index fd5fe12..8932396 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/mtd/concat.h>
 
 #include <mach/hardware.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/mach/flash.h>
 
 struct sa_subdev_info {
index 6d43ddb..e4fe8c4 100644 (file)
@@ -364,7 +364,7 @@ static int vf610_nfc_cmd(struct nand_chip *chip,
 {
        const struct nand_op_instr *instr;
        struct vf610_nfc *nfc = chip_to_nfc(chip);
-       int op_id = -1, trfr_sz = 0, offset;
+       int op_id = -1, trfr_sz = 0, offset = 0;
        u32 col = 0, row = 0, cmd1 = 0, cmd2 = 0, code = 0;
        bool force8bit = false;
 
index da1fc17..b996967 100644 (file)
@@ -1098,13 +1098,6 @@ static int bond_option_arp_validate_set(struct bonding *bond,
 {
        netdev_dbg(bond->dev, "Setting arp_validate to %s (%llu)\n",
                   newval->string, newval->value);
-
-       if (bond->dev->flags & IFF_UP) {
-               if (!newval->value)
-                       bond->recv_probe = NULL;
-               else if (bond->params.arp_interval)
-                       bond->recv_probe = bond_arp_rcv;
-       }
        bond->params.arp_validate = newval->value;
 
        return 0;
index 37ebd89..9e06dff 100644 (file)
@@ -871,7 +871,7 @@ static int emac_probe(struct platform_device *pdev)
        /* Read MAC-address from DT */
        mac_addr = of_get_mac_address(np);
        if (!IS_ERR(mac_addr))
-               memcpy(ndev->dev_addr, mac_addr, ETH_ALEN);
+               ether_addr_copy(ndev->dev_addr, mac_addr);
 
        /* Check if the MAC address is valid, if not get a random one */
        if (!is_valid_ether_addr(ndev->dev_addr)) {
index 7f89ad5..13a1d99 100644 (file)
@@ -961,7 +961,7 @@ int arc_emac_probe(struct net_device *ndev, int interface)
        mac_addr = of_get_mac_address(dev->of_node);
 
        if (!IS_ERR(mac_addr))
-               memcpy(ndev->dev_addr, mac_addr, ETH_ALEN);
+               ether_addr_copy(ndev->dev_addr, mac_addr);
        else
                eth_hw_addr_random(ndev);
 
index 15b1130..0e5de88 100644 (file)
@@ -1504,7 +1504,7 @@ static int octeon_mgmt_probe(struct platform_device *pdev)
        mac = of_get_mac_address(pdev->dev.of_node);
 
        if (!IS_ERR(mac))
-               memcpy(netdev->dev_addr, mac, ETH_ALEN);
+               ether_addr_copy(netdev->dev_addr, mac);
        else
                eth_hw_addr_random(netdev);
 
index e9a0213..6238e69 100644 (file)
@@ -41,7 +41,7 @@ config CS89x0_PLATFORM
 
 config EP93XX_ETH
        tristate "EP93xx Ethernet support"
-       depends on ARM && ARCH_EP93XX
+       depends on (ARM && ARCH_EP93XX) || COMPILE_TEST
        select MII
        help
          This is a driver for the ethernet hardware included in EP93xx CPUs.
index 13dfdfc..a6da987 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 
-#include <mach/hardware.h>
+#include <linux/platform_data/eth-ep93xx.h>
 
 #define DRV_MODULE_NAME                "ep93xx-eth"
 #define DRV_MODULE_VERSION     "0.1"
index 953ee56..5e1aff9 100644 (file)
@@ -1413,7 +1413,7 @@ static struct dm9000_plat_data *dm9000_parse_dt(struct device *dev)
 
        mac_addr = of_get_mac_address(np);
        if (!IS_ERR(mac_addr))
-               memcpy(pdata->dev_addr, mac_addr, sizeof(pdata->dev_addr));
+               ether_addr_copy(pdata->dev_addr, mac_addr);
 
        return pdata;
 }
index 7b7e526..30cdb24 100644 (file)
@@ -903,7 +903,7 @@ static int mpc52xx_fec_probe(struct platform_device *op)
         */
        mac_addr = of_get_mac_address(np);
        if (!IS_ERR(mac_addr)) {
-               memcpy(ndev->dev_addr, mac_addr, ETH_ALEN);
+               ether_addr_copy(ndev->dev_addr, mac_addr);
        } else {
                struct mpc52xx_fec __iomem *fec = priv->fec;
 
index 9cd2c28..7ab8095 100644 (file)
@@ -729,7 +729,7 @@ static int mac_probe(struct platform_device *_of_dev)
                err = -EINVAL;
                goto _return_of_get_parent;
        }
-       memcpy(mac_dev->addr, mac_addr, sizeof(mac_dev->addr));
+       ether_addr_copy(mac_dev->addr, mac_addr);
 
        /* Get the port handles */
        nph = of_count_phandle_with_args(mac_node, "fsl,fman-ports", NULL);
index 90ea7a1..5fad73b 100644 (file)
@@ -1015,7 +1015,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
 
        mac_addr = of_get_mac_address(ofdev->dev.of_node);
        if (!IS_ERR(mac_addr))
-               memcpy(ndev->dev_addr, mac_addr, ETH_ALEN);
+               ether_addr_copy(ndev->dev_addr, mac_addr);
 
        ret = fep->ops->allocate_bd(ndev);
        if (ret)
index df13c69..e670cd2 100644 (file)
@@ -873,7 +873,7 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
        mac_addr = of_get_mac_address(np);
 
        if (!IS_ERR(mac_addr))
-               memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
+               ether_addr_copy(dev->dev_addr, mac_addr);
 
        if (model && !strcasecmp(model, "TSEC"))
                priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
index 216e99a..4d6892d 100644 (file)
@@ -3911,7 +3911,7 @@ static int ucc_geth_probe(struct platform_device* ofdev)
 
        mac_addr = of_get_mac_address(np);
        if (!IS_ERR(mac_addr))
-               memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
+               ether_addr_copy(dev->dev_addr, mac_addr);
 
        ugeth->ug_info = ug_info;
        ugeth->dev = device;
index b398d6c..3dcd9c3 100644 (file)
@@ -118,7 +118,7 @@ static int init_sub_crq_irqs(struct ibmvnic_adapter *adapter);
 static int ibmvnic_init(struct ibmvnic_adapter *);
 static int ibmvnic_reset_init(struct ibmvnic_adapter *);
 static void release_crq_queue(struct ibmvnic_adapter *);
-static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p);
+static int __ibmvnic_set_mac(struct net_device *, u8 *);
 static int init_crq_queue(struct ibmvnic_adapter *adapter);
 static int send_query_phys_parms(struct ibmvnic_adapter *adapter);
 
@@ -849,11 +849,7 @@ static int ibmvnic_login(struct net_device *netdev)
                }
        } while (retry);
 
-       /* handle pending MAC address changes after successful login */
-       if (adapter->mac_change_pending) {
-               __ibmvnic_set_mac(netdev, &adapter->desired.mac);
-               adapter->mac_change_pending = false;
-       }
+       __ibmvnic_set_mac(netdev, adapter->mac_addr);
 
        return 0;
 }
@@ -1115,7 +1111,6 @@ static int ibmvnic_open(struct net_device *netdev)
        }
 
        rc = __ibmvnic_open(netdev);
-       netif_carrier_on(netdev);
 
        return rc;
 }
@@ -1686,28 +1681,40 @@ static void ibmvnic_set_multi(struct net_device *netdev)
        }
 }
 
-static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p)
+static int __ibmvnic_set_mac(struct net_device *netdev, u8 *dev_addr)
 {
        struct ibmvnic_adapter *adapter = netdev_priv(netdev);
-       struct sockaddr *addr = p;
        union ibmvnic_crq crq;
        int rc;
 
-       if (!is_valid_ether_addr(addr->sa_data))
-               return -EADDRNOTAVAIL;
+       if (!is_valid_ether_addr(dev_addr)) {
+               rc = -EADDRNOTAVAIL;
+               goto err;
+       }
 
        memset(&crq, 0, sizeof(crq));
        crq.change_mac_addr.first = IBMVNIC_CRQ_CMD;
        crq.change_mac_addr.cmd = CHANGE_MAC_ADDR;
-       ether_addr_copy(&crq.change_mac_addr.mac_addr[0], addr->sa_data);
+       ether_addr_copy(&crq.change_mac_addr.mac_addr[0], dev_addr);
 
        init_completion(&adapter->fw_done);
        rc = ibmvnic_send_crq(adapter, &crq);
-       if (rc)
-               return rc;
+       if (rc) {
+               rc = -EIO;
+               goto err;
+       }
+
        wait_for_completion(&adapter->fw_done);
        /* netdev->dev_addr is changed in handle_change_mac_rsp function */
-       return adapter->fw_done_rc ? -EIO : 0;
+       if (adapter->fw_done_rc) {
+               rc = -EIO;
+               goto err;
+       }
+
+       return 0;
+err:
+       ether_addr_copy(adapter->mac_addr, netdev->dev_addr);
+       return rc;
 }
 
 static int ibmvnic_set_mac(struct net_device *netdev, void *p)
@@ -1716,13 +1723,10 @@ static int ibmvnic_set_mac(struct net_device *netdev, void *p)
        struct sockaddr *addr = p;
        int rc;
 
-       if (adapter->state == VNIC_PROBED) {
-               memcpy(&adapter->desired.mac, addr, sizeof(struct sockaddr));
-               adapter->mac_change_pending = true;
-               return 0;
-       }
-
-       rc = __ibmvnic_set_mac(netdev, addr);
+       rc = 0;
+       ether_addr_copy(adapter->mac_addr, addr->sa_data);
+       if (adapter->state != VNIC_PROBED)
+               rc = __ibmvnic_set_mac(netdev, addr->sa_data);
 
        return rc;
 }
@@ -1859,8 +1863,6 @@ static int do_reset(struct ibmvnic_adapter *adapter,
            adapter->reset_reason != VNIC_RESET_CHANGE_PARAM)
                call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev);
 
-       netif_carrier_on(netdev);
-
        return 0;
 }
 
@@ -1930,8 +1932,6 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter,
                return 0;
        }
 
-       netif_carrier_on(netdev);
-
        return 0;
 }
 
@@ -3937,8 +3937,8 @@ static int handle_change_mac_rsp(union ibmvnic_crq *crq,
                dev_err(dev, "Error %ld in CHANGE_MAC_ADDR_RSP\n", rc);
                goto out;
        }
-       memcpy(netdev->dev_addr, &crq->change_mac_addr_rsp.mac_addr[0],
-              ETH_ALEN);
+       ether_addr_copy(netdev->dev_addr,
+                       &crq->change_mac_addr_rsp.mac_addr[0]);
 out:
        complete(&adapter->fw_done);
        return rc;
@@ -4475,6 +4475,10 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
                    crq->link_state_indication.phys_link_state;
                adapter->logical_link_state =
                    crq->link_state_indication.logical_link_state;
+               if (adapter->phys_link_state && adapter->logical_link_state)
+                       netif_carrier_on(netdev);
+               else
+                       netif_carrier_off(netdev);
                break;
        case CHANGE_MAC_ADDR_RSP:
                netdev_dbg(netdev, "Got MAC address change Response\n");
@@ -4852,8 +4856,6 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
        init_completion(&adapter->init_done);
        adapter->resetting = false;
 
-       adapter->mac_change_pending = false;
-
        do {
                rc = init_crq_queue(adapter);
                if (rc) {
index cffdac3..dcf2eb6 100644 (file)
@@ -969,7 +969,6 @@ struct ibmvnic_tunables {
        u64 rx_entries;
        u64 tx_entries;
        u64 mtu;
-       struct sockaddr mac;
 };
 
 struct ibmvnic_adapter {
@@ -1091,7 +1090,6 @@ struct ibmvnic_adapter {
        bool resetting;
        bool napi_enabled, from_passive_init;
 
-       bool mac_change_pending;
        bool failover_pending;
        bool force_reset_recovery;
 
index 07e254f..409b69f 100644 (file)
@@ -2750,7 +2750,7 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,
 
        mac_addr = of_get_mac_address(pnp);
        if (!IS_ERR(mac_addr))
-               memcpy(ppd.mac_addr, mac_addr, ETH_ALEN);
+               ether_addr_copy(ppd.mac_addr, mac_addr);
 
        mv643xx_eth_property(pnp, "tx-queue-size", ppd.tx_queue_size);
        mv643xx_eth_property(pnp, "tx-sram-addr", ppd.tx_sram_addr);
index 8186135..e758650 100644 (file)
@@ -4565,7 +4565,7 @@ static int mvneta_probe(struct platform_device *pdev)
        dt_mac_addr = of_get_mac_address(dn);
        if (!IS_ERR(dt_mac_addr)) {
                mac_from = "device tree";
-               memcpy(dev->dev_addr, dt_mac_addr, ETH_ALEN);
+               ether_addr_copy(dev->dev_addr, dt_mac_addr);
        } else {
                mvneta_get_mac_addr(pp, hw_mac_addr);
                if (is_valid_ether_addr(hw_mac_addr)) {
index 56d43d9..d38952e 100644 (file)
@@ -5058,8 +5058,10 @@ static int mvpp2_port_probe(struct platform_device *pdev,
        dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO |
                            NETIF_F_HW_VLAN_CTAG_FILTER;
 
-       if (mvpp22_rss_is_supported())
+       if (mvpp22_rss_is_supported()) {
                dev->hw_features |= NETIF_F_RXHASH;
+               dev->features |= NETIF_F_NTUPLE;
+       }
 
        if (port->pool_long->id == MVPP2_BM_JUMBO && port->id != 0) {
                dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
index 9d070cc..5adf307 100644 (file)
@@ -4805,7 +4805,7 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
         */
        iap = of_get_mac_address(hw->pdev->dev.of_node);
        if (!IS_ERR(iap))
-               memcpy(dev->dev_addr, iap, ETH_ALEN);
+               ether_addr_copy(dev->dev_addr, iap);
        else
                memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8,
                              ETH_ALEN);
index 5aac978..23883d1 100644 (file)
@@ -291,6 +291,9 @@ create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, const char *name,
        mlx5_fill_page_array(&eq->buf, pas);
 
        MLX5_SET(create_eq_in, in, opcode, MLX5_CMD_OP_CREATE_EQ);
+       if (!param->mask && MLX5_CAP_GEN(dev, log_max_uctx))
+               MLX5_SET(create_eq_in, in, uid, MLX5_SHARED_RESOURCE_UID);
+
        MLX5_SET64(create_eq_in, in, event_bitmask, param->mask);
 
        eqc = MLX5_ADDR_OF(create_eq_in, in, eq_context_entry);
index b6b3ff0..7ccb950 100644 (file)
@@ -22,7 +22,6 @@ config MLXSW_CORE_HWMON
 config MLXSW_CORE_THERMAL
        bool "Thermal zone support for Mellanox Technologies Switch ASICs"
        depends on MLXSW_CORE && THERMAL
-       depends on !(MLXSW_CORE=y && THERMAL=m)
        default y
        ---help---
         Say Y here if you want to automatically control fans speed according
index b44172a..ba4fdf1 100644 (file)
@@ -426,7 +426,7 @@ static void ks8851_init_mac(struct ks8851_net *ks)
 
        mac_addr = of_get_mac_address(ks->spidev->dev.of_node);
        if (!IS_ERR(mac_addr)) {
-               memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
+               ether_addr_copy(dev->dev_addr, mac_addr);
                ks8851_write_mac_addr(dev);
                return;
        }
index dc76b0d..e5c8412 100644 (file)
@@ -1328,7 +1328,7 @@ static int ks8851_probe(struct platform_device *pdev)
        if (pdev->dev.of_node) {
                mac = of_get_mac_address(pdev->dev.of_node);
                if (!IS_ERR(mac))
-                       memcpy(ks->mac_addr, mac, ETH_ALEN);
+                       ether_addr_copy(ks->mac_addr, mac);
        } else {
                struct ks8851_mll_platform_data *pdata;
 
index da138ed..fec604c 100644 (file)
@@ -1369,7 +1369,7 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
        if (!is_valid_ether_addr(ndev->dev_addr)) {
                const char *macaddr = of_get_mac_address(np);
                if (!IS_ERR(macaddr))
-                       memcpy(ndev->dev_addr, macaddr, ETH_ALEN);
+                       ether_addr_copy(ndev->dev_addr, macaddr);
        }
        if (!is_valid_ether_addr(ndev->dev_addr))
                eth_hw_addr_random(ndev);
index 549be1c..2e20334 100644 (file)
@@ -6992,8 +6992,7 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
        new_bus->priv = tp;
        new_bus->parent = &pdev->dev;
        new_bus->irq[0] = PHY_IGNORE_INTERRUPT;
-       snprintf(new_bus->id, MII_BUS_ID_SIZE, "r8169-%x",
-                PCI_DEVID(pdev->bus->number, pdev->devfn));
+       snprintf(new_bus->id, MII_BUS_ID_SIZE, "r8169-%x", pci_dev_id(pdev));
 
        new_bus->read = r8169_mdio_read_reg;
        new_bus->write = r8169_mdio_write_reg;
index 7c4e282..6354f19 100644 (file)
@@ -3193,7 +3193,7 @@ static struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev)
 
        mac_addr = of_get_mac_address(np);
        if (!IS_ERR(mac_addr))
-               memcpy(pdata->mac_addr, mac_addr, ETH_ALEN);
+               ether_addr_copy(pdata->mac_addr, mac_addr);
 
        pdata->no_ether_link =
                of_property_read_bool(np, "renesas,no-ether-link");
index 70cce63..696037d 100644 (file)
@@ -735,6 +735,7 @@ static int sgiseeq_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, dev);
+       SET_NETDEV_DEV(dev, &pdev->dev);
        sp = netdev_priv(dev);
 
        /* Make private data page aligned */
index 5b3b06a..d466e33 100644 (file)
@@ -15,7 +15,7 @@
  * Adopted from dwmac-sti.c
  */
 
-#include <linux/mfd/syscon.h>
+#include <linux/mfd/altera-sysmgr.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_net.h>
@@ -114,7 +114,8 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
 
        dwmac->interface = of_get_phy_mode(np);
 
-       sys_mgr_base_addr = syscon_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon");
+       sys_mgr_base_addr =
+               altr_sysmgr_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon");
        if (IS_ERR(sys_mgr_base_addr)) {
                dev_info(dev, "No sysmgr-syscon node found\n");
                return PTR_ERR(sys_mgr_base_addr);
index 195669f..ba124a4 100644 (file)
@@ -1015,6 +1015,8 @@ static struct mac_device_info *sun8i_dwmac_setup(void *ppriv)
        mac->mac = &sun8i_dwmac_ops;
        mac->dma = &sun8i_dwmac_dma_ops;
 
+       priv->dev->priv_flags |= IFF_UNICAST_FLT;
+
        /* The loopback bit seems to be re-set when link change
         * Simply mask it each time
         * Speed 10/100/1000 are set in BIT(2)/BIT(3)
index 26db6aa..7cbc01f 100644 (file)
@@ -208,7 +208,7 @@ static int quark_default_data(struct pci_dev *pdev,
                ret = 1;
        }
 
-       plat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn);
+       plat->bus_id = pci_dev_id(pdev);
        plat->phy_addr = ret;
        plat->interface = PHY_INTERFACE_MODE_RMII;
 
index c3f53a4..ed12e1e 100644 (file)
@@ -19,4 +19,4 @@ ti_cpsw-y := cpsw.o davinci_cpdma.o cpsw_ale.o cpsw_priv.o cpsw_sl.o cpsw_ethtoo
 obj-$(CONFIG_TI_KEYSTONE_NETCP) += keystone_netcp.o
 keystone_netcp-y := netcp_core.o cpsw_ale.o
 obj-$(CONFIG_TI_KEYSTONE_NETCP_ETHSS) += keystone_netcp_ethss.o
-keystone_netcp_ethss-y := netcp_ethss.o netcp_sgmii.o netcp_xgbepcsr.o
+keystone_netcp_ethss-y := netcp_ethss.o netcp_sgmii.o netcp_xgbepcsr.o cpsw_ale.o
index b18eeb0..634fc48 100644 (file)
@@ -2233,7 +2233,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 no_phy_slave:
                mac_addr = of_get_mac_address(slave_node);
                if (!IS_ERR(mac_addr)) {
-                       memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
+                       ether_addr_copy(slave_data->mac_addr, mac_addr);
                } else {
                        ret = ti_cm_get_macid(&pdev->dev, i,
                                              slave_data->mac_addr);
index 997475c..47c4515 100644 (file)
@@ -361,7 +361,7 @@ static void temac_do_set_mac_address(struct net_device *ndev)
 
 static int temac_init_mac_address(struct net_device *ndev, const void *address)
 {
-       memcpy(ndev->dev_addr, address, ETH_ALEN);
+       ether_addr_copy(ndev->dev_addr, address);
        if (!is_valid_ether_addr(ndev->dev_addr))
                eth_hw_addr_random(ndev);
        temac_do_set_mac_address(ndev);
index 6911707..6886270 100644 (file)
@@ -1167,7 +1167,7 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
 
        if (!IS_ERR(mac_address)) {
                /* Set the MAC address. */
-               memcpy(ndev->dev_addr, mac_address, ETH_ALEN);
+               ether_addr_copy(ndev->dev_addr, mac_address);
        } else {
                dev_warn(dev, "No MAC address found, using random\n");
                eth_hw_addr_random(ndev);
index ed6623a..319db3e 100644 (file)
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/net_tstamp.h>
+#include <linux/of.h>
 #include <linux/phy.h>
 #include <linux/platform_device.h>
 #include <linux/ptp_classify.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <mach/ixp46x_ts.h>
-#include <mach/npe.h>
-#include <mach/qmgr.h>
+#include <linux/soc/ixp4xx/npe.h>
+#include <linux/soc/ixp4xx/qmgr.h>
 
 #define DEBUG_DESC             0
 #define DEBUG_RX               0
@@ -1497,6 +1498,15 @@ static struct platform_driver ixp4xx_eth_driver = {
 static int __init eth_init_module(void)
 {
        int err;
+
+       /*
+        * FIXME: we bail out on device tree boot but this really needs
+        * to be fixed in a nicer way: this registers the MDIO bus before
+        * even matching the driver infrastructure, we should only probe
+        * detected hardware.
+        */
+       if (of_have_populated_dt())
+               return -ENODEV;
        if ((err = ixp4xx_mdio_register()))
                return err;
        return platform_driver_register(&ixp4xx_eth_driver);
index b2ff903..b188fce 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/ieee802154.h>
+#include <linux/io.h>
 #include <linux/kfifo.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
index 6fa29ea..6644762 100644 (file)
@@ -33,7 +33,7 @@
 #define ETH_PLL_CTL7           0x60
 
 #define ETH_PHY_CNTL0          0x80
-#define   EPHY_G12A_ID         0x33000180
+#define   EPHY_G12A_ID         0x33010180
 #define ETH_PHY_CNTL1          0x84
 #define  PHY_CNTL1_ST_MODE     GENMASK(2, 0)
 #define  PHY_CNTL1_ST_PHYADD   GENMASK(7, 3)
index 761ce3b..a669945 100644 (file)
@@ -217,12 +217,12 @@ static int rtl8211e_config_init(struct phy_device *phydev)
        if (oldpage < 0)
                goto err_restore_page;
 
-       ret = phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4);
+       ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4);
        if (ret)
                goto err_restore_page;
 
-       ret = phy_modify(phydev, 0x1c, RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
-                        val);
+       ret = __phy_modify(phydev, 0x1c, RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
+                          val);
 
 err_restore_page:
        return phy_restore_page(phydev, oldpage, ret);
@@ -275,6 +275,8 @@ static struct phy_driver realtek_drvs[] = {
                .config_aneg    = rtl8211_config_aneg,
                .read_mmd       = &genphy_read_mmd_unsupported,
                .write_mmd      = &genphy_write_mmd_unsupported,
+               .read_page      = rtl821x_read_page,
+               .write_page     = rtl821x_write_page,
        }, {
                PHY_ID_MATCH_EXACT(0x001cc912),
                .name           = "RTL8211B Gigabit Ethernet",
@@ -284,12 +286,16 @@ static struct phy_driver realtek_drvs[] = {
                .write_mmd      = &genphy_write_mmd_unsupported,
                .suspend        = rtl8211b_suspend,
                .resume         = rtl8211b_resume,
+               .read_page      = rtl821x_read_page,
+               .write_page     = rtl821x_write_page,
        }, {
                PHY_ID_MATCH_EXACT(0x001cc913),
                .name           = "RTL8211C Gigabit Ethernet",
                .config_init    = rtl8211c_config_init,
                .read_mmd       = &genphy_read_mmd_unsupported,
                .write_mmd      = &genphy_write_mmd_unsupported,
+               .read_page      = rtl821x_read_page,
+               .write_page     = rtl821x_write_page,
        }, {
                PHY_ID_MATCH_EXACT(0x001cc914),
                .name           = "RTL8211DN Gigabit Ethernet",
@@ -297,6 +303,8 @@ static struct phy_driver realtek_drvs[] = {
                .config_intr    = rtl8211e_config_intr,
                .suspend        = genphy_suspend,
                .resume         = genphy_resume,
+               .read_page      = rtl821x_read_page,
+               .write_page     = rtl821x_write_page,
        }, {
                PHY_ID_MATCH_EXACT(0x001cc915),
                .name           = "RTL8211E Gigabit Ethernet",
@@ -305,6 +313,8 @@ static struct phy_driver realtek_drvs[] = {
                .config_intr    = &rtl8211e_config_intr,
                .suspend        = genphy_suspend,
                .resume         = genphy_resume,
+               .read_page      = rtl821x_read_page,
+               .write_page     = rtl821x_write_page,
        }, {
                PHY_ID_MATCH_EXACT(0x001cc916),
                .name           = "RTL8211F Gigabit Ethernet",
index 5c60dc6..46a05b6 100644 (file)
@@ -22,8 +22,8 @@
 #include <linux/platform_device.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
-#include <mach/npe.h>
-#include <mach/qmgr.h>
+#include <linux/soc/ixp4xx/npe.h>
+#include <linux/soc/ixp4xx/qmgr.h>
 
 #define DEBUG_DESC             0
 #define DEBUG_RX               0
index 0496493..b7a49ae 100644 (file)
@@ -95,7 +95,7 @@ mt76_eeprom_override(struct mt76_dev *dev)
 
        mac = of_get_mac_address(np);
        if (!IS_ERR(mac))
-               memcpy(dev->macaddr, mac, ETH_ALEN);
+               ether_addr_copy(dev->macaddr, mac);
 #endif
 
        if (!is_valid_ether_addr(dev->macaddr)) {
index f3d753d..2030805 100644 (file)
@@ -756,6 +756,17 @@ static const guid_t *to_abstraction_guid(enum nvdimm_claim_class claim_class,
                return &guid_null;
 }
 
+static void reap_victim(struct nd_mapping *nd_mapping,
+               struct nd_label_ent *victim)
+{
+       struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
+       u32 slot = to_slot(ndd, victim->label);
+
+       dev_dbg(ndd->dev, "free: %d\n", slot);
+       nd_label_free_slot(ndd, slot);
+       victim->label = NULL;
+}
+
 static int __pmem_label_update(struct nd_region *nd_region,
                struct nd_mapping *nd_mapping, struct nd_namespace_pmem *nspm,
                int pos, unsigned long flags)
@@ -763,9 +774,9 @@ static int __pmem_label_update(struct nd_region *nd_region,
        struct nd_namespace_common *ndns = &nspm->nsio.common;
        struct nd_interleave_set *nd_set = nd_region->nd_set;
        struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
-       struct nd_label_ent *label_ent, *victim = NULL;
        struct nd_namespace_label *nd_label;
        struct nd_namespace_index *nsindex;
+       struct nd_label_ent *label_ent;
        struct nd_label_id label_id;
        struct resource *res;
        unsigned long *free;
@@ -834,18 +845,10 @@ static int __pmem_label_update(struct nd_region *nd_region,
        list_for_each_entry(label_ent, &nd_mapping->labels, list) {
                if (!label_ent->label)
                        continue;
-               if (memcmp(nspm->uuid, label_ent->label->uuid,
-                                       NSLABEL_UUID_LEN) != 0)
-                       continue;
-               victim = label_ent;
-               list_move_tail(&victim->list, &nd_mapping->labels);
-               break;
-       }
-       if (victim) {
-               dev_dbg(ndd->dev, "free: %d\n", slot);
-               slot = to_slot(ndd, victim->label);
-               nd_label_free_slot(ndd, slot);
-               victim->label = NULL;
+               if (test_and_clear_bit(ND_LABEL_REAP, &label_ent->flags)
+                               || memcmp(nspm->uuid, label_ent->label->uuid,
+                                       NSLABEL_UUID_LEN) == 0)
+                       reap_victim(nd_mapping, label_ent);
        }
 
        /* update index */
index f293556..d021464 100644 (file)
@@ -1247,12 +1247,27 @@ static int namespace_update_uuid(struct nd_region *nd_region,
        for (i = 0; i < nd_region->ndr_mappings; i++) {
                struct nd_mapping *nd_mapping = &nd_region->mapping[i];
                struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
+               struct nd_label_ent *label_ent;
                struct resource *res;
 
                for_each_dpa_resource(ndd, res)
                        if (strcmp(res->name, old_label_id.id) == 0)
                                sprintf((void *) res->name, "%s",
                                                new_label_id.id);
+
+               mutex_lock(&nd_mapping->lock);
+               list_for_each_entry(label_ent, &nd_mapping->labels, list) {
+                       struct nd_namespace_label *nd_label = label_ent->label;
+                       struct nd_label_id label_id;
+
+                       if (!nd_label)
+                               continue;
+                       nd_label_gen_id(&label_id, nd_label->uuid,
+                                       __le32_to_cpu(nd_label->flags));
+                       if (strcmp(old_label_id.id, label_id.id) == 0)
+                               set_bit(ND_LABEL_REAP, &label_ent->flags);
+               }
+               mutex_unlock(&nd_mapping->lock);
        }
        kfree(*old_uuid);
  out:
index a5ac3b2..191d62a 100644 (file)
@@ -113,8 +113,12 @@ struct nd_percpu_lane {
        spinlock_t lock;
 };
 
+enum nd_label_flags {
+       ND_LABEL_REAP,
+};
 struct nd_label_ent {
        struct list_head list;
+       unsigned long flags;
        struct nd_namespace_label *label;
 };
 
index a6644a2..7da80f3 100644 (file)
@@ -1257,10 +1257,9 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
                return 0;
        }
 
+       effects |= nvme_known_admin_effects(opcode);
        if (ctrl->effects)
                effects = le32_to_cpu(ctrl->effects->acs[opcode]);
-       else
-               effects = nvme_known_admin_effects(opcode);
 
        /*
         * For simplicity, IO to all namespaces is quiesced even if the command
@@ -2342,20 +2341,35 @@ static const struct attribute_group *nvme_subsys_attrs_groups[] = {
        NULL,
 };
 
-static int nvme_active_ctrls(struct nvme_subsystem *subsys)
+static bool nvme_validate_cntlid(struct nvme_subsystem *subsys,
+               struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
 {
-       int count = 0;
-       struct nvme_ctrl *ctrl;
+       struct nvme_ctrl *tmp;
+
+       lockdep_assert_held(&nvme_subsystems_lock);
+
+       list_for_each_entry(tmp, &subsys->ctrls, subsys_entry) {
+               if (ctrl->state == NVME_CTRL_DELETING ||
+                   ctrl->state == NVME_CTRL_DEAD)
+                       continue;
+
+               if (tmp->cntlid == ctrl->cntlid) {
+                       dev_err(ctrl->device,
+                               "Duplicate cntlid %u with %s, rejecting\n",
+                               ctrl->cntlid, dev_name(tmp->device));
+                       return false;
+               }
 
-       mutex_lock(&subsys->lock);
-       list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) {
-               if (ctrl->state != NVME_CTRL_DELETING &&
-                   ctrl->state != NVME_CTRL_DEAD)
-                       count++;
+               if ((id->cmic & (1 << 1)) ||
+                   (ctrl->opts && ctrl->opts->discovery_nqn))
+                       continue;
+
+               dev_err(ctrl->device,
+                       "Subsystem does not support multiple controllers\n");
+               return false;
        }
-       mutex_unlock(&subsys->lock);
 
-       return count;
+       return true;
 }
 
 static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
@@ -2395,22 +2409,13 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
        mutex_lock(&nvme_subsystems_lock);
        found = __nvme_find_get_subsystem(subsys->subnqn);
        if (found) {
-               /*
-                * Verify that the subsystem actually supports multiple
-                * controllers, else bail out.
-                */
-               if (!(ctrl->opts && ctrl->opts->discovery_nqn) &&
-                   nvme_active_ctrls(found) && !(id->cmic & (1 << 1))) {
-                       dev_err(ctrl->device,
-                               "ignoring ctrl due to duplicate subnqn (%s).\n",
-                               found->subnqn);
-                       nvme_put_subsystem(found);
-                       ret = -EINVAL;
-                       goto out_unlock;
-               }
-
                __nvme_release_subsystem(subsys);
                subsys = found;
+
+               if (!nvme_validate_cntlid(subsys, ctrl, id)) {
+                       ret = -EINVAL;
+                       goto out_put_subsystem;
+               }
        } else {
                ret = device_add(&subsys->dev);
                if (ret) {
@@ -2422,23 +2427,20 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
                list_add_tail(&subsys->entry, &nvme_subsystems);
        }
 
-       ctrl->subsys = subsys;
-       mutex_unlock(&nvme_subsystems_lock);
-
        if (sysfs_create_link(&subsys->dev.kobj, &ctrl->device->kobj,
                        dev_name(ctrl->device))) {
                dev_err(ctrl->device,
                        "failed to create sysfs link from subsystem.\n");
-               /* the transport driver will eventually put the subsystem */
-               return -EINVAL;
+               goto out_put_subsystem;
        }
 
-       mutex_lock(&subsys->lock);
+       ctrl->subsys = subsys;
        list_add_tail(&ctrl->subsys_entry, &subsys->ctrls);
-       mutex_unlock(&subsys->lock);
-
+       mutex_unlock(&nvme_subsystems_lock);
        return 0;
 
+out_put_subsystem:
+       nvme_put_subsystem(subsys);
 out_unlock:
        mutex_unlock(&nvme_subsystems_lock);
        put_device(&subsys->dev);
@@ -3605,19 +3607,18 @@ static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
 {
        u32 aer_notice_type = (result & 0xff00) >> 8;
 
+       trace_nvme_async_event(ctrl, aer_notice_type);
+
        switch (aer_notice_type) {
        case NVME_AER_NOTICE_NS_CHANGED:
-               trace_nvme_async_event(ctrl, aer_notice_type);
                set_bit(NVME_AER_NOTICE_NS_CHANGED, &ctrl->events);
                nvme_queue_scan(ctrl);
                break;
        case NVME_AER_NOTICE_FW_ACT_STARTING:
-               trace_nvme_async_event(ctrl, aer_notice_type);
                queue_work(nvme_wq, &ctrl->fw_act_work);
                break;
 #ifdef CONFIG_NVME_MULTIPATH
        case NVME_AER_NOTICE_ANA:
-               trace_nvme_async_event(ctrl, aer_notice_type);
                if (!ctrl->ana_log_buf)
                        break;
                queue_work(nvme_wq, &ctrl->ana_work);
@@ -3696,10 +3697,10 @@ static void nvme_free_ctrl(struct device *dev)
        __free_page(ctrl->discard_page);
 
        if (subsys) {
-               mutex_lock(&subsys->lock);
+               mutex_lock(&nvme_subsystems_lock);
                list_del(&ctrl->subsys_entry);
-               mutex_unlock(&subsys->lock);
                sysfs_remove_link(&subsys->dev.kobj, dev_name(ctrl->device));
+               mutex_unlock(&nvme_subsystems_lock);
        }
 
        ctrl->ops->free_ctrl(ctrl);
index 592d1e6..5838f7c 100644 (file)
@@ -978,7 +978,7 @@ EXPORT_SYMBOL_GPL(nvmf_free_options);
                                 NVMF_OPT_DISABLE_SQFLOW)
 
 static struct nvme_ctrl *
-nvmf_create_ctrl(struct device *dev, const char *buf, size_t count)
+nvmf_create_ctrl(struct device *dev, const char *buf)
 {
        struct nvmf_ctrl_options *opts;
        struct nvmf_transport_ops *ops;
@@ -1073,7 +1073,7 @@ static ssize_t nvmf_dev_write(struct file *file, const char __user *ubuf,
                goto out_unlock;
        }
 
-       ctrl = nvmf_create_ctrl(nvmf_device, buf, count);
+       ctrl = nvmf_create_ctrl(nvmf_device, buf);
        if (IS_ERR(ctrl)) {
                ret = PTR_ERR(ctrl);
                goto out_unlock;
index 9544eb6..dd8169b 100644 (file)
@@ -202,7 +202,7 @@ static LIST_HEAD(nvme_fc_lport_list);
 static DEFINE_IDA(nvme_fc_local_port_cnt);
 static DEFINE_IDA(nvme_fc_ctrl_cnt);
 
-
+static struct workqueue_struct *nvme_fc_wq;
 
 /*
  * These items are short-term. They will eventually be moved into
@@ -2054,7 +2054,7 @@ nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)
         */
        if (ctrl->ctrl.state == NVME_CTRL_CONNECTING) {
                active = atomic_xchg(&ctrl->err_work_active, 1);
-               if (!active && !schedule_work(&ctrl->err_work)) {
+               if (!active && !queue_work(nvme_fc_wq, &ctrl->err_work)) {
                        atomic_set(&ctrl->err_work_active, 0);
                        WARN_ON(1);
                }
@@ -3399,6 +3399,10 @@ static int __init nvme_fc_init_module(void)
 {
        int ret;
 
+       nvme_fc_wq = alloc_workqueue("nvme_fc_wq", WQ_MEM_RECLAIM, 0);
+       if (!nvme_fc_wq)
+               return -ENOMEM;
+
        /*
         * NOTE:
         * It is expected that in the future the kernel will combine
@@ -3416,7 +3420,7 @@ static int __init nvme_fc_init_module(void)
        ret = class_register(&fc_class);
        if (ret) {
                pr_err("couldn't register class fc\n");
-               return ret;
+               goto out_destroy_wq;
        }
 
        /*
@@ -3440,6 +3444,9 @@ out_destroy_device:
        device_destroy(&fc_class, MKDEV(0, 0));
 out_destroy_class:
        class_unregister(&fc_class);
+out_destroy_wq:
+       destroy_workqueue(nvme_fc_wq);
+
        return ret;
 }
 
@@ -3456,6 +3463,7 @@ static void __exit nvme_fc_exit_module(void)
 
        device_destroy(&fc_class, MKDEV(0, 0));
        class_unregister(&fc_class);
+       destroy_workqueue(nvme_fc_wq);
 }
 
 module_init(nvme_fc_init_module);
index 949e29e..4f20a10 100644 (file)
@@ -977,6 +977,7 @@ int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node)
        geo->csecs = 1 << ns->lba_shift;
        geo->sos = ns->ms;
        geo->ext = ns->ext;
+       geo->mdts = ns->ctrl->max_hw_sectors;
 
        dev->q = q;
        memcpy(dev->name, disk_name, DISK_NAME_LEN);
index 5c9429d..499acf0 100644 (file)
@@ -31,7 +31,7 @@ void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns,
                sprintf(disk_name, "nvme%dn%d", ctrl->instance, ns->head->instance);
        } else if (ns->head->disk) {
                sprintf(disk_name, "nvme%dc%dn%d", ctrl->subsys->instance,
-                               ctrl->cntlid, ns->head->instance);
+                               ctrl->instance, ns->head->instance);
                *flags = GENHD_FL_HIDDEN;
        } else {
                sprintf(disk_name, "nvme%dn%d", ctrl->subsys->instance,
index 3e4fb89..2a8708c 100644 (file)
@@ -1296,6 +1296,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
        switch (dev->ctrl.state) {
        case NVME_CTRL_DELETING:
                shutdown = true;
+               /* fall through */
        case NVME_CTRL_CONNECTING:
        case NVME_CTRL_RESETTING:
                dev_warn_ratelimited(dev->ctrl.device,
@@ -2280,8 +2281,6 @@ static int nvme_dev_add(struct nvme_dev *dev)
                        return ret;
                }
                dev->ctrl.tagset = &dev->tagset;
-
-               nvme_dbbuf_set(dev);
        } else {
                blk_mq_update_nr_hw_queues(&dev->tagset, dev->online_queues - 1);
 
@@ -2289,6 +2288,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
                nvme_free_queues(dev, dev->online_queues);
        }
 
+       nvme_dbbuf_set(dev);
        return 0;
 }
 
index e1824c2..f383146 100644 (file)
@@ -697,15 +697,6 @@ out_free_queues:
        return ret;
 }
 
-static void nvme_rdma_free_tagset(struct nvme_ctrl *nctrl,
-               struct blk_mq_tag_set *set)
-{
-       struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(nctrl);
-
-       blk_mq_free_tag_set(set);
-       nvme_rdma_dev_put(ctrl->device);
-}
-
 static struct blk_mq_tag_set *nvme_rdma_alloc_tagset(struct nvme_ctrl *nctrl,
                bool admin)
 {
@@ -744,24 +735,9 @@ static struct blk_mq_tag_set *nvme_rdma_alloc_tagset(struct nvme_ctrl *nctrl,
 
        ret = blk_mq_alloc_tag_set(set);
        if (ret)
-               goto out;
-
-       /*
-        * We need a reference on the device as long as the tag_set is alive,
-        * as the MRs in the request structures need a valid ib_device.
-        */
-       ret = nvme_rdma_dev_get(ctrl->device);
-       if (!ret) {
-               ret = -EINVAL;
-               goto out_free_tagset;
-       }
+               return ERR_PTR(ret);
 
        return set;
-
-out_free_tagset:
-       blk_mq_free_tag_set(set);
-out:
-       return ERR_PTR(ret);
 }
 
 static void nvme_rdma_destroy_admin_queue(struct nvme_rdma_ctrl *ctrl,
@@ -769,7 +745,7 @@ static void nvme_rdma_destroy_admin_queue(struct nvme_rdma_ctrl *ctrl,
 {
        if (remove) {
                blk_cleanup_queue(ctrl->ctrl.admin_q);
-               nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.admin_tagset);
+               blk_mq_free_tag_set(ctrl->ctrl.admin_tagset);
        }
        if (ctrl->async_event_sqe.data) {
                nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
@@ -847,7 +823,7 @@ out_cleanup_queue:
                blk_cleanup_queue(ctrl->ctrl.admin_q);
 out_free_tagset:
        if (new)
-               nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.admin_tagset);
+               blk_mq_free_tag_set(ctrl->ctrl.admin_tagset);
 out_free_async_qe:
        nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
                sizeof(struct nvme_command), DMA_TO_DEVICE);
@@ -862,7 +838,7 @@ static void nvme_rdma_destroy_io_queues(struct nvme_rdma_ctrl *ctrl,
 {
        if (remove) {
                blk_cleanup_queue(ctrl->ctrl.connect_q);
-               nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.tagset);
+               blk_mq_free_tag_set(ctrl->ctrl.tagset);
        }
        nvme_rdma_free_io_queues(ctrl);
 }
@@ -903,7 +879,7 @@ out_cleanup_connect_q:
                blk_cleanup_queue(ctrl->ctrl.connect_q);
 out_free_tag_set:
        if (new)
-               nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.tagset);
+               blk_mq_free_tag_set(ctrl->ctrl.tagset);
 out_free_io_queues:
        nvme_rdma_free_io_queues(ctrl);
        return ret;
index 97d3c77..e71502d 100644 (file)
@@ -167,6 +167,7 @@ TRACE_EVENT(nvme_async_event,
                aer_name(NVME_AER_NOTICE_NS_CHANGED),
                aer_name(NVME_AER_NOTICE_ANA),
                aer_name(NVME_AER_NOTICE_FW_ACT_STARTING),
+               aer_name(NVME_AER_NOTICE_DISC_CHANGED),
                aer_name(NVME_AER_ERROR),
                aer_name(NVME_AER_SMART),
                aer_name(NVME_AER_CSS),
index 490c8fc..5893543 100644 (file)
@@ -16,6 +16,8 @@ struct zynqmp_nvmem_data {
        struct nvmem_device *nvmem;
 };
 
+static const struct zynqmp_eemi_ops *eemi_ops;
+
 static int zynqmp_nvmem_read(void *context, unsigned int offset,
                             void *val, size_t bytes)
 {
@@ -23,9 +25,7 @@ static int zynqmp_nvmem_read(void *context, unsigned int offset,
        int idcode, version;
        struct zynqmp_nvmem_data *priv = context;
 
-       const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
-
-       if (!eemi_ops || !eemi_ops->get_chipid)
+       if (!eemi_ops->get_chipid)
                return -ENXIO;
 
        ret = eemi_ops->get_chipid(&idcode, &version);
@@ -61,6 +61,10 @@ static int zynqmp_nvmem_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
+       eemi_ops = zynqmp_pm_get_eemi_ops();
+       if (IS_ERR(eemi_ops))
+               return PTR_ERR(eemi_ops);
+
        priv->dev = dev;
        econfig.dev = dev;
        econfig.reg_read = zynqmp_nvmem_read;
index 9649cd5..6f1be80 100644 (file)
@@ -52,39 +52,25 @@ static const void *of_get_mac_addr(struct device_node *np, const char *name)
 static const void *of_get_mac_addr_nvmem(struct device_node *np)
 {
        int ret;
-       u8 mac[ETH_ALEN];
-       struct property *pp;
+       const void *mac;
+       u8 nvmem_mac[ETH_ALEN];
        struct platform_device *pdev = of_find_device_by_node(np);
 
        if (!pdev)
                return ERR_PTR(-ENODEV);
 
-       ret = nvmem_get_mac_address(&pdev->dev, &mac);
-       if (ret)
+       ret = nvmem_get_mac_address(&pdev->dev, &nvmem_mac);
+       if (ret) {
+               put_device(&pdev->dev);
                return ERR_PTR(ret);
-
-       pp = devm_kzalloc(&pdev->dev, sizeof(*pp), GFP_KERNEL);
-       if (!pp)
-               return ERR_PTR(-ENOMEM);
-
-       pp->name = "nvmem-mac-address";
-       pp->length = ETH_ALEN;
-       pp->value = devm_kmemdup(&pdev->dev, mac, ETH_ALEN, GFP_KERNEL);
-       if (!pp->value) {
-               ret = -ENOMEM;
-               goto free;
        }
 
-       ret = of_add_property(np, pp);
-       if (ret)
-               goto free;
-
-       return pp->value;
-free:
-       devm_kfree(&pdev->dev, pp->value);
-       devm_kfree(&pdev->dev, pp);
+       mac = devm_kmemdup(&pdev->dev, nvmem_mac, ETH_ALEN, GFP_KERNEL);
+       put_device(&pdev->dev);
+       if (!mac)
+               return ERR_PTR(-ENOMEM);
 
-       return ERR_PTR(ret);
+       return mac;
 }
 
 /**
index 657d642..28cdd8c 100644 (file)
@@ -10,10 +10,10 @@ obj-$(CONFIG_PCI)           += access.o bus.o probe.o host-bridge.o \
 ifdef CONFIG_PCI
 obj-$(CONFIG_PROC_FS)          += proc.o
 obj-$(CONFIG_SYSFS)            += slot.o
-obj-$(CONFIG_OF)               += of.o
 obj-$(CONFIG_ACPI)             += pci-acpi.o
 endif
 
+obj-$(CONFIG_OF)               += of.o
 obj-$(CONFIG_PCI_QUIRKS)       += quirks.o
 obj-$(CONFIG_PCIEPORTBUS)      += pcie/
 obj-$(CONFIG_HOTPLUG_PCI)      += hotplug/
index 5cb40b2..495059d 100644 (file)
@@ -23,7 +23,7 @@ void pci_add_resource_offset(struct list_head *resources, struct resource *res,
 
        entry = resource_list_create_entry(res, 0);
        if (!entry) {
-               printk(KERN_ERR "PCI: can't add host bridge window %pR\n", res);
+               pr_err("PCI: can't add host bridge window %pR\n", res);
                return;
        }
 
@@ -288,8 +288,7 @@ bool pci_bus_clip_resource(struct pci_dev *dev, int idx)
                res->end = end;
                res->flags &= ~IORESOURCE_UNSET;
                orig_res.flags &= ~IORESOURCE_UNSET;
-               pci_printk(KERN_DEBUG, dev, "%pR clipped to %pR\n",
-                                &orig_res, res);
+               pci_info(dev, "%pR clipped to %pR\n", &orig_res, res);
 
                return true;
        }
index 6ea74b1..a6ce1ee 100644 (file)
@@ -103,15 +103,32 @@ config PCIE_SPEAR13XX
          Say Y here if you want PCIe support on SPEAr13XX SoCs.
 
 config PCI_KEYSTONE
-       bool "TI Keystone PCIe controller"
-       depends on ARCH_KEYSTONE || (ARM && COMPILE_TEST)
+       bool
+
+config PCI_KEYSTONE_HOST
+       bool "PCI Keystone Host Mode"
+       depends on ARCH_KEYSTONE || ARCH_K3 || ((ARM || ARM64) && COMPILE_TEST)
        depends on PCI_MSI_IRQ_DOMAIN
        select PCIE_DW_HOST
+       select PCI_KEYSTONE
+       default y
        help
-         Say Y here if you want to enable PCI controller support on Keystone
-         SoCs. The PCI controller on Keystone is based on DesignWare hardware
-         and therefore the driver re-uses the DesignWare core functions to
-         implement the driver.
+         Enables support for the PCIe controller in the Keystone SoC to
+         work in host mode. The PCI controller on Keystone is based on
+         DesignWare hardware and therefore the driver re-uses the
+         DesignWare core functions to implement the driver.
+
+config PCI_KEYSTONE_EP
+       bool "PCI Keystone Endpoint Mode"
+       depends on ARCH_KEYSTONE || ARCH_K3 || ((ARM || ARM64) && COMPILE_TEST)
+       depends on PCI_ENDPOINT
+       select PCIE_DW_EP
+       select PCI_KEYSTONE
+       help
+         Enables support for the PCIe controller in the Keystone SoC to
+         work in endpoint mode. The PCI controller on Keystone is based
+         on DesignWare hardware and therefore the driver re-uses the
+         DesignWare core functions to implement the driver.
 
 config PCI_LAYERSCAPE
        bool "Freescale Layerscape PCIe controller"
index b5f3b83..b085dfd 100644 (file)
@@ -28,5 +28,6 @@ obj-$(CONFIG_PCIE_UNIPHIER) += pcie-uniphier.o
 # depending on whether ACPI, the DT driver, or both are enabled.
 
 ifdef CONFIG_PCI
+obj-$(CONFIG_ARM64) += pcie-al.o
 obj-$(CONFIG_ARM64) += pcie-hisi.o
 endif
index ae84a69..419451e 100644 (file)
@@ -247,6 +247,7 @@ static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)
 
        dra7xx->irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
                                                   &intx_domain_ops, pp);
+       of_node_put(pcie_intc_node);
        if (!dra7xx->irq_domain) {
                dev_err(dev, "Failed to get a INTx IRQ domain\n");
                return -ENODEV;
@@ -406,7 +407,7 @@ dra7xx_pcie_get_features(struct dw_pcie_ep *ep)
        return &dra7xx_pcie_epc_features;
 }
 
-static struct dw_pcie_ep_ops pcie_ep_ops = {
+static const struct dw_pcie_ep_ops pcie_ep_ops = {
        .ep_init = dra7xx_pcie_ep_init,
        .raise_irq = dra7xx_pcie_raise_irq,
        .get_features = dra7xx_pcie_get_features,
index 3d627f9..9b5cb5b 100644 (file)
@@ -52,6 +52,7 @@ enum imx6_pcie_variants {
 
 #define IMX6_PCIE_FLAG_IMX6_PHY                        BIT(0)
 #define IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE       BIT(1)
+#define IMX6_PCIE_FLAG_SUPPORTS_SUSPEND                BIT(2)
 
 struct imx6_pcie_drvdata {
        enum imx6_pcie_variants variant;
@@ -89,9 +90,8 @@ struct imx6_pcie {
 };
 
 /* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */
-#define PHY_PLL_LOCK_WAIT_MAX_RETRIES  2000
-#define PHY_PLL_LOCK_WAIT_USLEEP_MIN   50
 #define PHY_PLL_LOCK_WAIT_USLEEP_MAX   200
+#define PHY_PLL_LOCK_WAIT_TIMEOUT      (2000 * PHY_PLL_LOCK_WAIT_USLEEP_MAX)
 
 /* PCIe Root Complex registers (memory-mapped) */
 #define PCIE_RC_IMX6_MSI_CAP                   0x50
@@ -104,34 +104,29 @@ struct imx6_pcie {
 
 /* PCIe Port Logic registers (memory-mapped) */
 #define PL_OFFSET 0x700
-#define PCIE_PL_PFLR (PL_OFFSET + 0x08)
-#define PCIE_PL_PFLR_LINK_STATE_MASK           (0x3f << 16)
-#define PCIE_PL_PFLR_FORCE_LINK                        (1 << 15)
-#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
-#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
 
 #define PCIE_PHY_CTRL (PL_OFFSET + 0x114)
-#define PCIE_PHY_CTRL_DATA_LOC 0
-#define PCIE_PHY_CTRL_CAP_ADR_LOC 16
-#define PCIE_PHY_CTRL_CAP_DAT_LOC 17
-#define PCIE_PHY_CTRL_WR_LOC 18
-#define PCIE_PHY_CTRL_RD_LOC 19
+#define PCIE_PHY_CTRL_DATA(x)          FIELD_PREP(GENMASK(15, 0), (x))
+#define PCIE_PHY_CTRL_CAP_ADR          BIT(16)
+#define PCIE_PHY_CTRL_CAP_DAT          BIT(17)
+#define PCIE_PHY_CTRL_WR               BIT(18)
+#define PCIE_PHY_CTRL_RD               BIT(19)
 
 #define PCIE_PHY_STAT (PL_OFFSET + 0x110)
-#define PCIE_PHY_STAT_ACK_LOC 16
+#define PCIE_PHY_STAT_ACK              BIT(16)
 
 #define PCIE_LINK_WIDTH_SPEED_CONTROL  0x80C
 
 /* PHY registers (not memory-mapped) */
 #define PCIE_PHY_ATEOVRD                       0x10
-#define  PCIE_PHY_ATEOVRD_EN                   (0x1 << 2)
+#define  PCIE_PHY_ATEOVRD_EN                   BIT(2)
 #define  PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT     0
 #define  PCIE_PHY_ATEOVRD_REF_CLKDIV_MASK      0x1
 
 #define PCIE_PHY_MPLL_OVRD_IN_LO               0x11
 #define  PCIE_PHY_MPLL_MULTIPLIER_SHIFT                2
 #define  PCIE_PHY_MPLL_MULTIPLIER_MASK         0x7f
-#define  PCIE_PHY_MPLL_MULTIPLIER_OVRD         (0x1 << 9)
+#define  PCIE_PHY_MPLL_MULTIPLIER_OVRD         BIT(9)
 
 #define PCIE_PHY_RX_ASIC_OUT 0x100D
 #define PCIE_PHY_RX_ASIC_OUT_VALID     (1 << 0)
@@ -154,19 +149,19 @@ struct imx6_pcie {
 #define PCIE_PHY_CMN_REG26_ATT_MODE    0xBC
 
 #define PHY_RX_OVRD_IN_LO 0x1005
-#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
-#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3)
+#define PHY_RX_OVRD_IN_LO_RX_DATA_EN           BIT(5)
+#define PHY_RX_OVRD_IN_LO_RX_PLL_EN            BIT(3)
 
-static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, int exp_val)
+static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, bool exp_val)
 {
        struct dw_pcie *pci = imx6_pcie->pci;
-       u32 val;
+       bool val;
        u32 max_iterations = 10;
        u32 wait_counter = 0;
 
        do {
-               val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT);
-               val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1;
+               val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT) &
+                       PCIE_PHY_STAT_ACK;
                wait_counter++;
 
                if (val == exp_val)
@@ -184,27 +179,27 @@ static int pcie_phy_wait_ack(struct imx6_pcie *imx6_pcie, int addr)
        u32 val;
        int ret;
 
-       val = addr << PCIE_PHY_CTRL_DATA_LOC;
+       val = PCIE_PHY_CTRL_DATA(addr);
        dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val);
 
-       val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC);
+       val |= PCIE_PHY_CTRL_CAP_ADR;
        dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val);
 
-       ret = pcie_phy_poll_ack(imx6_pcie, 1);
+       ret = pcie_phy_poll_ack(imx6_pcie, true);
        if (ret)
                return ret;
 
-       val = addr << PCIE_PHY_CTRL_DATA_LOC;
+       val = PCIE_PHY_CTRL_DATA(addr);
        dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val);
 
-       return pcie_phy_poll_ack(imx6_pcie, 0);
+       return pcie_phy_poll_ack(imx6_pcie, false);
 }
 
 /* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
-static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, int *data)
+static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, u16 *data)
 {
        struct dw_pcie *pci = imx6_pcie->pci;
-       u32 val, phy_ctl;
+       u32 phy_ctl;
        int ret;
 
        ret = pcie_phy_wait_ack(imx6_pcie, addr);
@@ -212,23 +207,22 @@ static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, int *data)
                return ret;
 
        /* assert Read signal */
-       phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC;
+       phy_ctl = PCIE_PHY_CTRL_RD;
        dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, phy_ctl);
 
-       ret = pcie_phy_poll_ack(imx6_pcie, 1);
+       ret = pcie_phy_poll_ack(imx6_pcie, true);
        if (ret)
                return ret;
 
-       val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT);
-       *data = val & 0xffff;
+       *data = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT);
 
        /* deassert Read signal */
        dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, 0x00);
 
-       return pcie_phy_poll_ack(imx6_pcie, 0);
+       return pcie_phy_poll_ack(imx6_pcie, false);
 }
 
-static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data)
+static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, u16 data)
 {
        struct dw_pcie *pci = imx6_pcie->pci;
        u32 var;
@@ -240,41 +234,41 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data)
        if (ret)
                return ret;
 
-       var = data << PCIE_PHY_CTRL_DATA_LOC;
+       var = PCIE_PHY_CTRL_DATA(data);
        dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);
 
        /* capture data */
-       var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC);
+       var |= PCIE_PHY_CTRL_CAP_DAT;
        dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);
 
-       ret = pcie_phy_poll_ack(imx6_pcie, 1);
+       ret = pcie_phy_poll_ack(imx6_pcie, true);
        if (ret)
                return ret;
 
        /* deassert cap data */
-       var = data << PCIE_PHY_CTRL_DATA_LOC;
+       var = PCIE_PHY_CTRL_DATA(data);
        dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);
 
        /* wait for ack de-assertion */
-       ret = pcie_phy_poll_ack(imx6_pcie, 0);
+       ret = pcie_phy_poll_ack(imx6_pcie, false);
        if (ret)
                return ret;
 
        /* assert wr signal */
-       var = 0x1 << PCIE_PHY_CTRL_WR_LOC;
+       var = PCIE_PHY_CTRL_WR;
        dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);
 
        /* wait for ack */
-       ret = pcie_phy_poll_ack(imx6_pcie, 1);
+       ret = pcie_phy_poll_ack(imx6_pcie, true);
        if (ret)
                return ret;
 
        /* deassert wr signal */
-       var = data << PCIE_PHY_CTRL_DATA_LOC;
+       var = PCIE_PHY_CTRL_DATA(data);
        dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);
 
        /* wait for ack de-assertion */
-       ret = pcie_phy_poll_ack(imx6_pcie, 0);
+       ret = pcie_phy_poll_ack(imx6_pcie, false);
        if (ret)
                return ret;
 
@@ -285,7 +279,7 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data)
 
 static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie)
 {
-       u32 tmp;
+       u16 tmp;
 
        if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_IMX6_PHY))
                return;
@@ -455,7 +449,7 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
                 * reset time is too short, cannot meet the requirement.
                 * add one ~10us delay here.
                 */
-               udelay(10);
+               usleep_range(10, 100);
                regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
                                   IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
                break;
@@ -488,20 +482,14 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
 static void imx7d_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie)
 {
        u32 val;
-       unsigned int retries;
        struct device *dev = imx6_pcie->pci->dev;
 
-       for (retries = 0; retries < PHY_PLL_LOCK_WAIT_MAX_RETRIES; retries++) {
-               regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR22, &val);
-
-               if (val & IMX7D_GPR22_PCIE_PHY_PLL_LOCKED)
-                       return;
-
-               usleep_range(PHY_PLL_LOCK_WAIT_USLEEP_MIN,
-                            PHY_PLL_LOCK_WAIT_USLEEP_MAX);
-       }
-
-       dev_err(dev, "PCIe PLL lock timeout\n");
+       if (regmap_read_poll_timeout(imx6_pcie->iomuxc_gpr,
+                                    IOMUXC_GPR22, val,
+                                    val & IMX7D_GPR22_PCIE_PHY_PLL_LOCKED,
+                                    PHY_PLL_LOCK_WAIT_USLEEP_MAX,
+                                    PHY_PLL_LOCK_WAIT_TIMEOUT))
+               dev_err(dev, "PCIe PLL lock timeout\n");
 }
 
 static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
@@ -687,7 +675,7 @@ static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie)
 {
        unsigned long phy_rate = clk_get_rate(imx6_pcie->pcie_phy);
        int mult, div;
-       u32 val;
+       u16 val;
 
        if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_IMX6_PHY))
                return 0;
@@ -730,21 +718,6 @@ static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie)
        return 0;
 }
 
-static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie)
-{
-       struct dw_pcie *pci = imx6_pcie->pci;
-       struct device *dev = pci->dev;
-
-       /* check if the link is up or not */
-       if (!dw_pcie_wait_for_link(pci))
-               return 0;
-
-       dev_dbg(dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
-               dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0),
-               dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1));
-       return -ETIMEDOUT;
-}
-
 static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)
 {
        struct dw_pcie *pci = imx6_pcie->pci;
@@ -761,7 +734,7 @@ static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)
        }
 
        dev_err(dev, "Speed change timeout\n");
-       return -EINVAL;
+       return -ETIMEDOUT;
 }
 
 static void imx6_pcie_ltssm_enable(struct device *dev)
@@ -803,7 +776,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
        /* Start LTSSM. */
        imx6_pcie_ltssm_enable(dev);
 
-       ret = imx6_pcie_wait_for_link(imx6_pcie);
+       ret = dw_pcie_wait_for_link(pci);
        if (ret)
                goto err_reset_phy;
 
@@ -841,7 +814,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
                }
 
                /* Make sure link training is finished as well! */
-               ret = imx6_pcie_wait_for_link(imx6_pcie);
+               ret = dw_pcie_wait_for_link(pci);
                if (ret) {
                        dev_err(dev, "Failed to bring link up!\n");
                        goto err_reset_phy;
@@ -856,8 +829,8 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
 
 err_reset_phy:
        dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
-               dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0),
-               dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1));
+               dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0),
+               dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG1));
        imx6_pcie_reset_phy(imx6_pcie);
        return ret;
 }
@@ -993,17 +966,11 @@ static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie)
        }
 }
 
-static inline bool imx6_pcie_supports_suspend(struct imx6_pcie *imx6_pcie)
-{
-       return (imx6_pcie->drvdata->variant == IMX7D ||
-               imx6_pcie->drvdata->variant == IMX6SX);
-}
-
 static int imx6_pcie_suspend_noirq(struct device *dev)
 {
        struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
 
-       if (!imx6_pcie_supports_suspend(imx6_pcie))
+       if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND))
                return 0;
 
        imx6_pcie_pm_turnoff(imx6_pcie);
@@ -1019,7 +986,7 @@ static int imx6_pcie_resume_noirq(struct device *dev)
        struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
        struct pcie_port *pp = &imx6_pcie->pci->pp;
 
-       if (!imx6_pcie_supports_suspend(imx6_pcie))
+       if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND))
                return 0;
 
        imx6_pcie_assert_core_reset(imx6_pcie);
@@ -1249,7 +1216,8 @@ static const struct imx6_pcie_drvdata drvdata[] = {
        [IMX6SX] = {
                .variant = IMX6SX,
                .flags = IMX6_PCIE_FLAG_IMX6_PHY |
-                        IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE,
+                        IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE |
+                        IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
        },
        [IMX6QP] = {
                .variant = IMX6QP,
@@ -1258,6 +1226,7 @@ static const struct imx6_pcie_drvdata drvdata[] = {
        },
        [IMX7D] = {
                .variant = IMX7D,
+               .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
        },
        [IMX8MQ] = {
                .variant = IMX8MQ,
@@ -1279,6 +1248,7 @@ static struct platform_driver imx6_pcie_driver = {
                .of_match_table = imx6_pcie_of_match,
                .suppress_bind_attrs = true,
                .pm = &imx6_pcie_pm_ops,
+               .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },
        .probe    = imx6_pcie_probe,
        .shutdown = imx6_pcie_shutdown,
index 14f2b0b..af67725 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/gpio/consumer.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irqchip/chained_irq.h>
@@ -18,6 +19,7 @@
 #include <linux/mfd/syscon.h>
 #include <linux/msi.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/of_pci.h>
 #include <linux/phy/phy.h>
@@ -26,6 +28,7 @@
 #include <linux/resource.h>
 #include <linux/signal.h>
 
+#include "../../pci.h"
 #include "pcie-designware.h"
 
 #define PCIE_VENDORID_MASK     0xffff
 #define CFG_TYPE1                      BIT(24)
 
 #define OB_SIZE                                0x030
-#define SPACE0_REMOTE_CFG_OFFSET       0x1000
 #define OB_OFFSET_INDEX(n)             (0x200 + (8 * (n)))
 #define OB_OFFSET_HI(n)                        (0x204 + (8 * (n)))
 #define OB_ENABLEN                     BIT(0)
 #define OB_WIN_SIZE                    8       /* 8MB */
 
+#define PCIE_LEGACY_IRQ_ENABLE_SET(n)  (0x188 + (0x10 * ((n) - 1)))
+#define PCIE_LEGACY_IRQ_ENABLE_CLR(n)  (0x18c + (0x10 * ((n) - 1)))
+#define PCIE_EP_IRQ_SET                        0x64
+#define PCIE_EP_IRQ_CLR                        0x68
+#define INT_ENABLE                     BIT(0)
+
 /* IRQ register defines */
 #define IRQ_EOI                                0x050
-#define IRQ_STATUS                     0x184
-#define IRQ_ENABLE_SET                 0x188
-#define IRQ_ENABLE_CLR                 0x18c
 
 #define MSI_IRQ                                0x054
-#define MSI0_IRQ_STATUS                        0x104
-#define MSI0_IRQ_ENABLE_SET            0x108
-#define MSI0_IRQ_ENABLE_CLR            0x10c
-#define IRQ_STATUS                     0x184
+#define MSI_IRQ_STATUS(n)              (0x104 + ((n) << 4))
+#define MSI_IRQ_ENABLE_SET(n)          (0x108 + ((n) << 4))
+#define MSI_IRQ_ENABLE_CLR(n)          (0x10c + ((n) << 4))
 #define MSI_IRQ_OFFSET                 4
 
+#define IRQ_STATUS(n)                  (0x184 + ((n) << 4))
+#define IRQ_ENABLE_SET(n)              (0x188 + ((n) << 4))
+#define INTx_EN                                BIT(0)
+
 #define ERR_IRQ_STATUS                 0x1c4
 #define ERR_IRQ_ENABLE_SET             0x1c8
 #define ERR_AER                                BIT(5)  /* ECRC error */
+#define AM6_ERR_AER                    BIT(4)  /* AM6 ECRC error */
 #define ERR_AXI                                BIT(4)  /* AXI tag lookup fatal error */
 #define ERR_CORR                       BIT(3)  /* Correctable error */
 #define ERR_NONFATAL                   BIT(2)  /* Non-fatal error */
 #define ERR_IRQ_ALL                    (ERR_AER | ERR_AXI | ERR_CORR | \
                                         ERR_NONFATAL | ERR_FATAL | ERR_SYS)
 
-#define MAX_MSI_HOST_IRQS              8
 /* PCIE controller device IDs */
 #define PCIE_RC_K2HK                   0xb008
 #define PCIE_RC_K2E                    0xb009
 #define PCIE_RC_K2L                    0xb00a
 #define PCIE_RC_K2G                    0xb00b
 
+#define KS_PCIE_DEV_TYPE_MASK          (0x3 << 1)
+#define KS_PCIE_DEV_TYPE(mode)         ((mode) << 1)
+
+#define EP                             0x0
+#define LEG_EP                         0x1
+#define RC                             0x2
+
+#define EXP_CAP_ID_OFFSET              0x70
+
+#define KS_PCIE_SYSCLOCKOUTEN          BIT(0)
+
+#define AM654_PCIE_DEV_TYPE_MASK       0x3
+#define AM654_WIN_SIZE                 SZ_64K
+
+#define APP_ADDR_SPACE_0               (16 * SZ_1K)
+
 #define to_keystone_pcie(x)            dev_get_drvdata((x)->dev)
 
+struct ks_pcie_of_data {
+       enum dw_pcie_device_mode mode;
+       const struct dw_pcie_host_ops *host_ops;
+       const struct dw_pcie_ep_ops *ep_ops;
+       unsigned int version;
+};
+
 struct keystone_pcie {
        struct dw_pcie          *pci;
        /* PCI Device ID */
        u32                     device_id;
-       int                     num_legacy_host_irqs;
        int                     legacy_host_irqs[PCI_NUM_INTX];
        struct                  device_node *legacy_intc_np;
 
-       int                     num_msi_host_irqs;
-       int                     msi_host_irqs[MAX_MSI_HOST_IRQS];
+       int                     msi_host_irq;
        int                     num_lanes;
        u32                     num_viewport;
        struct phy              **phy;
@@ -101,28 +130,12 @@ struct keystone_pcie {
        struct irq_domain       *legacy_irq_domain;
        struct device_node      *np;
 
-       int error_irq;
-
        /* Application register space */
        void __iomem            *va_app_base;   /* DT 1st resource */
        struct resource         app;
+       bool                    is_am6;
 };
 
-static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset,
-                                            u32 *bit_pos)
-{
-       *reg_offset = offset % 8;
-       *bit_pos = offset >> 3;
-}
-
-static phys_addr_t ks_pcie_get_msi_addr(struct pcie_port *pp)
-{
-       struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-       struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
-
-       return ks_pcie->app.start + MSI_IRQ;
-}
-
 static u32 ks_pcie_app_readl(struct keystone_pcie *ks_pcie, u32 offset)
 {
        return readl(ks_pcie->va_app_base + offset);
@@ -134,81 +147,114 @@ static void ks_pcie_app_writel(struct keystone_pcie *ks_pcie, u32 offset,
        writel(val, ks_pcie->va_app_base + offset);
 }
 
-static void ks_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset)
+static void ks_pcie_msi_irq_ack(struct irq_data *data)
 {
-       struct dw_pcie *pci = ks_pcie->pci;
-       struct pcie_port *pp = &pci->pp;
-       struct device *dev = pci->dev;
-       u32 pending, vector;
-       int src, virq;
+       struct pcie_port *pp  = irq_data_get_irq_chip_data(data);
+       struct keystone_pcie *ks_pcie;
+       u32 irq = data->hwirq;
+       struct dw_pcie *pci;
+       u32 reg_offset;
+       u32 bit_pos;
 
-       pending = ks_pcie_app_readl(ks_pcie, MSI0_IRQ_STATUS + (offset << 4));
+       pci = to_dw_pcie_from_pp(pp);
+       ks_pcie = to_keystone_pcie(pci);
 
-       /*
-        * MSI0 status bit 0-3 shows vectors 0, 8, 16, 24, MSI1 status bit
-        * shows 1, 9, 17, 25 and so forth
-        */
-       for (src = 0; src < 4; src++) {
-               if (BIT(src) & pending) {
-                       vector = offset + (src << 3);
-                       virq = irq_linear_revmap(pp->irq_domain, vector);
-                       dev_dbg(dev, "irq: bit %d, vector %d, virq %d\n",
-                               src, vector, virq);
-                       generic_handle_irq(virq);
-               }
-       }
+       reg_offset = irq % 8;
+       bit_pos = irq >> 3;
+
+       ks_pcie_app_writel(ks_pcie, MSI_IRQ_STATUS(reg_offset),
+                          BIT(bit_pos));
+       ks_pcie_app_writel(ks_pcie, IRQ_EOI, reg_offset + MSI_IRQ_OFFSET);
 }
 
-static void ks_pcie_msi_irq_ack(int irq, struct pcie_port *pp)
+static void ks_pcie_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 {
-       u32 reg_offset, bit_pos;
+       struct pcie_port *pp = irq_data_get_irq_chip_data(data);
        struct keystone_pcie *ks_pcie;
        struct dw_pcie *pci;
+       u64 msi_target;
 
        pci = to_dw_pcie_from_pp(pp);
        ks_pcie = to_keystone_pcie(pci);
-       update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
 
-       ks_pcie_app_writel(ks_pcie, MSI0_IRQ_STATUS + (reg_offset << 4),
-                          BIT(bit_pos));
-       ks_pcie_app_writel(ks_pcie, IRQ_EOI, reg_offset + MSI_IRQ_OFFSET);
+       msi_target = ks_pcie->app.start + MSI_IRQ;
+       msg->address_lo = lower_32_bits(msi_target);
+       msg->address_hi = upper_32_bits(msi_target);
+       msg->data = data->hwirq;
+
+       dev_dbg(pci->dev, "msi#%d address_hi %#x address_lo %#x\n",
+               (int)data->hwirq, msg->address_hi, msg->address_lo);
 }
 
-static void ks_pcie_msi_set_irq(struct pcie_port *pp, int irq)
+static int ks_pcie_msi_set_affinity(struct irq_data *irq_data,
+                                   const struct cpumask *mask, bool force)
 {
-       u32 reg_offset, bit_pos;
-       struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-       struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+       return -EINVAL;
+}
 
-       update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
-       ks_pcie_app_writel(ks_pcie, MSI0_IRQ_ENABLE_SET + (reg_offset << 4),
+static void ks_pcie_msi_mask(struct irq_data *data)
+{
+       struct pcie_port *pp = irq_data_get_irq_chip_data(data);
+       struct keystone_pcie *ks_pcie;
+       u32 irq = data->hwirq;
+       struct dw_pcie *pci;
+       unsigned long flags;
+       u32 reg_offset;
+       u32 bit_pos;
+
+       raw_spin_lock_irqsave(&pp->lock, flags);
+
+       pci = to_dw_pcie_from_pp(pp);
+       ks_pcie = to_keystone_pcie(pci);
+
+       reg_offset = irq % 8;
+       bit_pos = irq >> 3;
+
+       ks_pcie_app_writel(ks_pcie, MSI_IRQ_ENABLE_CLR(reg_offset),
                           BIT(bit_pos));
+
+       raw_spin_unlock_irqrestore(&pp->lock, flags);
 }
 
-static void ks_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
+static void ks_pcie_msi_unmask(struct irq_data *data)
 {
-       u32 reg_offset, bit_pos;
-       struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-       struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+       struct pcie_port *pp = irq_data_get_irq_chip_data(data);
+       struct keystone_pcie *ks_pcie;
+       u32 irq = data->hwirq;
+       struct dw_pcie *pci;
+       unsigned long flags;
+       u32 reg_offset;
+       u32 bit_pos;
+
+       raw_spin_lock_irqsave(&pp->lock, flags);
 
-       update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
-       ks_pcie_app_writel(ks_pcie, MSI0_IRQ_ENABLE_CLR + (reg_offset << 4),
+       pci = to_dw_pcie_from_pp(pp);
+       ks_pcie = to_keystone_pcie(pci);
+
+       reg_offset = irq % 8;
+       bit_pos = irq >> 3;
+
+       ks_pcie_app_writel(ks_pcie, MSI_IRQ_ENABLE_SET(reg_offset),
                           BIT(bit_pos));
+
+       raw_spin_unlock_irqrestore(&pp->lock, flags);
 }
 
+static struct irq_chip ks_pcie_msi_irq_chip = {
+       .name = "KEYSTONE-PCI-MSI",
+       .irq_ack = ks_pcie_msi_irq_ack,
+       .irq_compose_msi_msg = ks_pcie_compose_msi_msg,
+       .irq_set_affinity = ks_pcie_msi_set_affinity,
+       .irq_mask = ks_pcie_msi_mask,
+       .irq_unmask = ks_pcie_msi_unmask,
+};
+
 static int ks_pcie_msi_host_init(struct pcie_port *pp)
 {
+       pp->msi_irq_chip = &ks_pcie_msi_irq_chip;
        return dw_pcie_allocate_domains(pp);
 }
 
-static void ks_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie)
-{
-       int i;
-
-       for (i = 0; i < PCI_NUM_INTX; i++)
-               ks_pcie_app_writel(ks_pcie, IRQ_ENABLE_SET + (i << 4), 0x1);
-}
-
 static void ks_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie,
                                      int offset)
 {
@@ -217,7 +263,7 @@ static void ks_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie,
        u32 pending;
        int virq;
 
-       pending = ks_pcie_app_readl(ks_pcie, IRQ_STATUS + (offset << 4));
+       pending = ks_pcie_app_readl(ks_pcie, IRQ_STATUS(offset));
 
        if (BIT(0) & pending) {
                virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, offset);
@@ -229,6 +275,14 @@ static void ks_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie,
        ks_pcie_app_writel(ks_pcie, IRQ_EOI, offset);
 }
 
+/*
+ * Dummy function so that DW core doesn't configure MSI
+ */
+static int ks_pcie_am654_msi_host_init(struct pcie_port *pp)
+{
+       return 0;
+}
+
 static void ks_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)
 {
        ks_pcie_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL);
@@ -255,10 +309,10 @@ static irqreturn_t ks_pcie_handle_error_irq(struct keystone_pcie *ks_pcie)
        if (reg & ERR_CORR)
                dev_dbg(dev, "Correctable Error\n");
 
-       if (reg & ERR_AXI)
+       if (!ks_pcie->is_am6 && (reg & ERR_AXI))
                dev_err(dev, "AXI tag lookup fatal Error\n");
 
-       if (reg & ERR_AER)
+       if (reg & ERR_AER || (ks_pcie->is_am6 && (reg & AM6_ERR_AER)))
                dev_err(dev, "ECRC Error\n");
 
        ks_pcie_app_writel(ks_pcie, ERR_IRQ_STATUS, reg);
@@ -356,6 +410,9 @@ static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
        dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0);
        ks_pcie_clear_dbi_mode(ks_pcie);
 
+       if (ks_pcie->is_am6)
+               return;
+
        val = ilog2(OB_WIN_SIZE);
        ks_pcie_app_writel(ks_pcie, OB_SIZE, val);
 
@@ -445,68 +502,33 @@ static int ks_pcie_link_up(struct dw_pcie *pci)
        return (val == PORT_LOGIC_LTSSM_STATE_L0);
 }
 
-static void ks_pcie_initiate_link_train(struct keystone_pcie *ks_pcie)
+static void ks_pcie_stop_link(struct dw_pcie *pci)
 {
+       struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
        u32 val;
 
        /* Disable Link training */
        val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
        val &= ~LTSSM_EN_VAL;
        ks_pcie_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
-
-       /* Initiate Link Training */
-       val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
-       ks_pcie_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
 }
 
-/**
- * ks_pcie_dw_host_init() - initialize host for v3_65 dw hardware
- *
- * Ioremap the register resources, initialize legacy irq domain
- * and call dw_pcie_v3_65_host_init() API to initialize the Keystone
- * PCI host controller.
- */
-static int __init ks_pcie_dw_host_init(struct keystone_pcie *ks_pcie)
+static int ks_pcie_start_link(struct dw_pcie *pci)
 {
-       struct dw_pcie *pci = ks_pcie->pci;
-       struct pcie_port *pp = &pci->pp;
+       struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
        struct device *dev = pci->dev;
-       struct platform_device *pdev = to_platform_device(dev);
-       struct resource *res;
-
-       /* Index 0 is the config reg. space address */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       pci->dbi_base = devm_pci_remap_cfg_resource(dev, res);
-       if (IS_ERR(pci->dbi_base))
-               return PTR_ERR(pci->dbi_base);
-
-       /*
-        * We set these same and is used in pcie rd/wr_other_conf
-        * functions
-        */
-       pp->va_cfg0_base = pci->dbi_base + SPACE0_REMOTE_CFG_OFFSET;
-       pp->va_cfg1_base = pp->va_cfg0_base;
-
-       /* Index 1 is the application reg. space address */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       ks_pcie->va_app_base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(ks_pcie->va_app_base))
-               return PTR_ERR(ks_pcie->va_app_base);
-
-       ks_pcie->app = *res;
+       u32 val;
 
-       /* Create legacy IRQ domain */
-       ks_pcie->legacy_irq_domain =
-                       irq_domain_add_linear(ks_pcie->legacy_intc_np,
-                                             PCI_NUM_INTX,
-                                             &ks_pcie_legacy_irq_domain_ops,
-                                             NULL);
-       if (!ks_pcie->legacy_irq_domain) {
-               dev_err(dev, "Failed to add irq domain for legacy irqs\n");
-               return -EINVAL;
+       if (dw_pcie_link_up(pci)) {
+               dev_dbg(dev, "link is already up\n");
+               return 0;
        }
 
-       return dw_pcie_host_init(pp);
+       /* Initiate Link Training */
+       val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
+       ks_pcie_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
+
+       return 0;
 }
 
 static void ks_pcie_quirk(struct pci_dev *dev)
@@ -552,34 +574,16 @@ static void ks_pcie_quirk(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, ks_pcie_quirk);
 
-static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
-{
-       struct dw_pcie *pci = ks_pcie->pci;
-       struct device *dev = pci->dev;
-
-       if (dw_pcie_link_up(pci)) {
-               dev_info(dev, "Link already up\n");
-               return 0;
-       }
-
-       ks_pcie_initiate_link_train(ks_pcie);
-
-       /* check if the link is up or not */
-       if (!dw_pcie_wait_for_link(pci))
-               return 0;
-
-       dev_err(dev, "phy link never came up\n");
-       return -ETIMEDOUT;
-}
-
 static void ks_pcie_msi_irq_handler(struct irq_desc *desc)
 {
-       unsigned int irq = irq_desc_get_irq(desc);
+       unsigned int irq = desc->irq_data.hwirq;
        struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
-       u32 offset = irq - ks_pcie->msi_host_irqs[0];
+       u32 offset = irq - ks_pcie->msi_host_irq;
        struct dw_pcie *pci = ks_pcie->pci;
+       struct pcie_port *pp = &pci->pp;
        struct device *dev = pci->dev;
        struct irq_chip *chip = irq_desc_get_chip(desc);
+       u32 vector, virq, reg, pos;
 
        dev_dbg(dev, "%s, irq %d\n", __func__, irq);
 
@@ -589,7 +593,23 @@ static void ks_pcie_msi_irq_handler(struct irq_desc *desc)
         * ack operation.
         */
        chained_irq_enter(chip, desc);
-       ks_pcie_handle_msi_irq(ks_pcie, offset);
+
+       reg = ks_pcie_app_readl(ks_pcie, MSI_IRQ_STATUS(offset));
+       /*
+        * MSI0 status bit 0-3 shows vectors 0, 8, 16, 24, MSI1 status bit
+        * shows 1, 9, 17, 25 and so forth
+        */
+       for (pos = 0; pos < 4; pos++) {
+               if (!(reg & BIT(pos)))
+                       continue;
+
+               vector = offset + (pos << 3);
+               virq = irq_linear_revmap(pp->irq_domain, vector);
+               dev_dbg(dev, "irq: bit %d, vector %d, virq %d\n", pos, vector,
+                       virq);
+               generic_handle_irq(virq);
+       }
+
        chained_irq_exit(chip, desc);
 }
 
@@ -622,89 +642,119 @@ static void ks_pcie_legacy_irq_handler(struct irq_desc *desc)
        chained_irq_exit(chip, desc);
 }
 
-static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie,
-                                          char *controller, int *num_irqs)
+static int ks_pcie_config_msi_irq(struct keystone_pcie *ks_pcie)
 {
-       int temp, max_host_irqs, legacy = 1, *host_irqs;
        struct device *dev = ks_pcie->pci->dev;
-       struct device_node *np_pcie = dev->of_node, **np_temp;
-
-       if (!strcmp(controller, "msi-interrupt-controller"))
-               legacy = 0;
+       struct device_node *np = ks_pcie->np;
+       struct device_node *intc_np;
+       struct irq_data *irq_data;
+       int irq_count, irq, ret, i;
 
-       if (legacy) {
-               np_temp = &ks_pcie->legacy_intc_np;
-               max_host_irqs = PCI_NUM_INTX;
-               host_irqs = &ks_pcie->legacy_host_irqs[0];
-       } else {
-               np_temp = &ks_pcie->msi_intc_np;
-               max_host_irqs = MAX_MSI_HOST_IRQS;
-               host_irqs =  &ks_pcie->msi_host_irqs[0];
-       }
+       if (!IS_ENABLED(CONFIG_PCI_MSI))
+               return 0;
 
-       /* interrupt controller is in a child node */
-       *np_temp = of_get_child_by_name(np_pcie, controller);
-       if (!(*np_temp)) {
-               dev_err(dev, "Node for %s is absent\n", controller);
+       intc_np = of_get_child_by_name(np, "msi-interrupt-controller");
+       if (!intc_np) {
+               if (ks_pcie->is_am6)
+                       return 0;
+               dev_warn(dev, "msi-interrupt-controller node is absent\n");
                return -EINVAL;
        }
 
-       temp = of_irq_count(*np_temp);
-       if (!temp) {
-               dev_err(dev, "No IRQ entries in %s\n", controller);
-               of_node_put(*np_temp);
-               return -EINVAL;
+       irq_count = of_irq_count(intc_np);
+       if (!irq_count) {
+               dev_err(dev, "No IRQ entries in msi-interrupt-controller\n");
+               ret = -EINVAL;
+               goto err;
        }
 
-       if (temp > max_host_irqs)
-               dev_warn(dev, "Too many %s interrupts defined %u\n",
-                       (legacy ? "legacy" : "MSI"), temp);
-
-       /*
-        * support upto max_host_irqs. In dt from index 0 to 3 (legacy) or 0 to
-        * 7 (MSI)
-        */
-       for (temp = 0; temp < max_host_irqs; temp++) {
-               host_irqs[temp] = irq_of_parse_and_map(*np_temp, temp);
-               if (!host_irqs[temp])
-                       break;
-       }
+       for (i = 0; i < irq_count; i++) {
+               irq = irq_of_parse_and_map(intc_np, i);
+               if (!irq) {
+                       ret = -EINVAL;
+                       goto err;
+               }
 
-       of_node_put(*np_temp);
+               if (!ks_pcie->msi_host_irq) {
+                       irq_data = irq_get_irq_data(irq);
+                       if (!irq_data) {
+                               ret = -EINVAL;
+                               goto err;
+                       }
+                       ks_pcie->msi_host_irq = irq_data->hwirq;
+               }
 
-       if (temp) {
-               *num_irqs = temp;
-               return 0;
+               irq_set_chained_handler_and_data(irq, ks_pcie_msi_irq_handler,
+                                                ks_pcie);
        }
 
-       return -EINVAL;
+       of_node_put(intc_np);
+       return 0;
+
+err:
+       of_node_put(intc_np);
+       return ret;
 }
 
-static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie)
+static int ks_pcie_config_legacy_irq(struct keystone_pcie *ks_pcie)
 {
-       int i;
+       struct device *dev = ks_pcie->pci->dev;
+       struct irq_domain *legacy_irq_domain;
+       struct device_node *np = ks_pcie->np;
+       struct device_node *intc_np;
+       int irq_count, irq, ret = 0, i;
+
+       intc_np = of_get_child_by_name(np, "legacy-interrupt-controller");
+       if (!intc_np) {
+               /*
+                * Since legacy interrupts are modeled as edge-interrupts in
+                * AM6, keep it disabled for now.
+                */
+               if (ks_pcie->is_am6)
+                       return 0;
+               dev_warn(dev, "legacy-interrupt-controller node is absent\n");
+               return -EINVAL;
+       }
 
-       /* Legacy IRQ */
-       for (i = 0; i < ks_pcie->num_legacy_host_irqs; i++) {
-               irq_set_chained_handler_and_data(ks_pcie->legacy_host_irqs[i],
+       irq_count = of_irq_count(intc_np);
+       if (!irq_count) {
+               dev_err(dev, "No IRQ entries in legacy-interrupt-controller\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       for (i = 0; i < irq_count; i++) {
+               irq = irq_of_parse_and_map(intc_np, i);
+               if (!irq) {
+                       ret = -EINVAL;
+                       goto err;
+               }
+               ks_pcie->legacy_host_irqs[i] = irq;
+
+               irq_set_chained_handler_and_data(irq,
                                                 ks_pcie_legacy_irq_handler,
                                                 ks_pcie);
        }
-       ks_pcie_enable_legacy_irqs(ks_pcie);
 
-       /* MSI IRQ */
-       if (IS_ENABLED(CONFIG_PCI_MSI)) {
-               for (i = 0; i < ks_pcie->num_msi_host_irqs; i++) {
-                       irq_set_chained_handler_and_data(ks_pcie->msi_host_irqs[i],
-                                                        ks_pcie_msi_irq_handler,
-                                                        ks_pcie);
-               }
+       legacy_irq_domain =
+               irq_domain_add_linear(intc_np, PCI_NUM_INTX,
+                                     &ks_pcie_legacy_irq_domain_ops, NULL);
+       if (!legacy_irq_domain) {
+               dev_err(dev, "Failed to add irq domain for legacy irqs\n");
+               ret = -EINVAL;
+               goto err;
        }
+       ks_pcie->legacy_irq_domain = legacy_irq_domain;
+
+       for (i = 0; i < PCI_NUM_INTX; i++)
+               ks_pcie_app_writel(ks_pcie, IRQ_ENABLE_SET(i), INTx_EN);
 
-       if (ks_pcie->error_irq > 0)
-               ks_pcie_enable_error_irq(ks_pcie);
+err:
+       of_node_put(intc_np);
+       return ret;
 }
 
+#ifdef CONFIG_ARM
 /*
  * When a PCI device does not exist during config cycles, keystone host gets a
  * bus error instead of returning 0xffffffff. This handler always returns 0
@@ -724,6 +774,7 @@ static int ks_pcie_fault(unsigned long addr, unsigned int fsr,
 
        return 0;
 }
+#endif
 
 static int __init ks_pcie_init_id(struct keystone_pcie *ks_pcie)
 {
@@ -742,8 +793,10 @@ static int __init ks_pcie_init_id(struct keystone_pcie *ks_pcie)
        if (ret)
                return ret;
 
+       dw_pcie_dbi_ro_wr_en(pci);
        dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, id & PCIE_VENDORID_MASK);
        dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, id >> PCIE_DEVICEID_SHIFT);
+       dw_pcie_dbi_ro_wr_dis(pci);
 
        return 0;
 }
@@ -754,11 +807,18 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)
        struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
        int ret;
 
+       ret = ks_pcie_config_legacy_irq(ks_pcie);
+       if (ret)
+               return ret;
+
+       ret = ks_pcie_config_msi_irq(ks_pcie);
+       if (ret)
+               return ret;
+
        dw_pcie_setup_rc(pp);
 
-       ks_pcie_establish_link(ks_pcie);
+       ks_pcie_stop_link(pci);
        ks_pcie_setup_rc_app_regs(ks_pcie);
-       ks_pcie_setup_interrupts(ks_pcie);
        writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8),
                        pci->dbi_base + PCI_IO_BASE);
 
@@ -766,12 +826,17 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)
        if (ret < 0)
                return ret;
 
+#ifdef CONFIG_ARM
        /*
         * PCIe access errors that result into OCP errors are caught by ARM as
         * "External aborts"
         */
        hook_fault_code(17, ks_pcie_fault, SIGBUS, 0,
                        "Asynchronous external abort");
+#endif
+
+       ks_pcie_start_link(pci);
+       dw_pcie_wait_for_link(pci);
 
        return 0;
 }
@@ -780,14 +845,15 @@ static const struct dw_pcie_host_ops ks_pcie_host_ops = {
        .rd_other_conf = ks_pcie_rd_other_conf,
        .wr_other_conf = ks_pcie_wr_other_conf,
        .host_init = ks_pcie_host_init,
-       .msi_set_irq = ks_pcie_msi_set_irq,
-       .msi_clear_irq = ks_pcie_msi_clear_irq,
-       .get_msi_addr = ks_pcie_get_msi_addr,
        .msi_host_init = ks_pcie_msi_host_init,
-       .msi_irq_ack = ks_pcie_msi_irq_ack,
        .scan_bus = ks_pcie_v3_65_scan_bus,
 };
 
+static const struct dw_pcie_host_ops ks_pcie_am654_host_ops = {
+       .host_init = ks_pcie_host_init,
+       .msi_host_init = ks_pcie_am654_msi_host_init,
+};
+
 static irqreturn_t ks_pcie_err_irq_handler(int irq, void *priv)
 {
        struct keystone_pcie *ks_pcie = priv;
@@ -801,41 +867,17 @@ static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,
        struct dw_pcie *pci = ks_pcie->pci;
        struct pcie_port *pp = &pci->pp;
        struct device *dev = &pdev->dev;
+       struct resource *res;
        int ret;
 
-       ret = ks_pcie_get_irq_controller_info(ks_pcie,
-                                       "legacy-interrupt-controller",
-                                       &ks_pcie->num_legacy_host_irqs);
-       if (ret)
-               return ret;
-
-       if (IS_ENABLED(CONFIG_PCI_MSI)) {
-               ret = ks_pcie_get_irq_controller_info(ks_pcie,
-                                               "msi-interrupt-controller",
-                                               &ks_pcie->num_msi_host_irqs);
-               if (ret)
-                       return ret;
-       }
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
+       pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res);
+       if (IS_ERR(pp->va_cfg0_base))
+               return PTR_ERR(pp->va_cfg0_base);
 
-       /*
-        * Index 0 is the platform interrupt for error interrupt
-        * from RC.  This is optional.
-        */
-       ks_pcie->error_irq = irq_of_parse_and_map(ks_pcie->np, 0);
-       if (ks_pcie->error_irq <= 0)
-               dev_info(dev, "no error IRQ defined\n");
-       else {
-               ret = request_irq(ks_pcie->error_irq, ks_pcie_err_irq_handler,
-                                 IRQF_SHARED, "pcie-error-irq", ks_pcie);
-               if (ret < 0) {
-                       dev_err(dev, "failed to request error IRQ %d\n",
-                               ks_pcie->error_irq);
-                       return ret;
-               }
-       }
+       pp->va_cfg1_base = pp->va_cfg0_base;
 
-       pp->ops = &ks_pcie_host_ops;
-       ret = ks_pcie_dw_host_init(ks_pcie);
+       ret = dw_pcie_host_init(pp);
        if (ret) {
                dev_err(dev, "failed to initialize host\n");
                return ret;
@@ -844,18 +886,139 @@ static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,
        return 0;
 }
 
-static const struct of_device_id ks_pcie_of_match[] = {
-       {
-               .type = "pci",
-               .compatible = "ti,keystone-pcie",
-       },
-       { },
-};
+static u32 ks_pcie_am654_read_dbi2(struct dw_pcie *pci, void __iomem *base,
+                                  u32 reg, size_t size)
+{
+       struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+       u32 val;
+
+       ks_pcie_set_dbi_mode(ks_pcie);
+       dw_pcie_read(base + reg, size, &val);
+       ks_pcie_clear_dbi_mode(ks_pcie);
+       return val;
+}
+
+static void ks_pcie_am654_write_dbi2(struct dw_pcie *pci, void __iomem *base,
+                                    u32 reg, size_t size, u32 val)
+{
+       struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+
+       ks_pcie_set_dbi_mode(ks_pcie);
+       dw_pcie_write(base + reg, size, val);
+       ks_pcie_clear_dbi_mode(ks_pcie);
+}
 
 static const struct dw_pcie_ops ks_pcie_dw_pcie_ops = {
+       .start_link = ks_pcie_start_link,
+       .stop_link = ks_pcie_stop_link,
        .link_up = ks_pcie_link_up,
+       .read_dbi2 = ks_pcie_am654_read_dbi2,
+       .write_dbi2 = ks_pcie_am654_write_dbi2,
+};
+
+static void ks_pcie_am654_ep_init(struct dw_pcie_ep *ep)
+{
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       int flags;
+
+       ep->page_size = AM654_WIN_SIZE;
+       flags = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_32;
+       dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_0, APP_ADDR_SPACE_0 - 1);
+       dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, flags);
+}
+
+static void ks_pcie_am654_raise_legacy_irq(struct keystone_pcie *ks_pcie)
+{
+       struct dw_pcie *pci = ks_pcie->pci;
+       u8 int_pin;
+
+       int_pin = dw_pcie_readb_dbi(pci, PCI_INTERRUPT_PIN);
+       if (int_pin == 0 || int_pin > 4)
+               return;
+
+       ks_pcie_app_writel(ks_pcie, PCIE_LEGACY_IRQ_ENABLE_SET(int_pin),
+                          INT_ENABLE);
+       ks_pcie_app_writel(ks_pcie, PCIE_EP_IRQ_SET, INT_ENABLE);
+       mdelay(1);
+       ks_pcie_app_writel(ks_pcie, PCIE_EP_IRQ_CLR, INT_ENABLE);
+       ks_pcie_app_writel(ks_pcie, PCIE_LEGACY_IRQ_ENABLE_CLR(int_pin),
+                          INT_ENABLE);
+}
+
+static int ks_pcie_am654_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
+                                  enum pci_epc_irq_type type,
+                                  u16 interrupt_num)
+{
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+
+       switch (type) {
+       case PCI_EPC_IRQ_LEGACY:
+               ks_pcie_am654_raise_legacy_irq(ks_pcie);
+               break;
+       case PCI_EPC_IRQ_MSI:
+               dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
+               break;
+       default:
+               dev_err(pci->dev, "UNKNOWN IRQ type\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct pci_epc_features ks_pcie_am654_epc_features = {
+       .linkup_notifier = false,
+       .msi_capable = true,
+       .msix_capable = false,
+       .reserved_bar = 1 << BAR_0 | 1 << BAR_1,
+       .bar_fixed_64bit = 1 << BAR_0,
+       .bar_fixed_size[2] = SZ_1M,
+       .bar_fixed_size[3] = SZ_64K,
+       .bar_fixed_size[4] = 256,
+       .bar_fixed_size[5] = SZ_1M,
+       .align = SZ_1M,
 };
 
+static const struct pci_epc_features*
+ks_pcie_am654_get_features(struct dw_pcie_ep *ep)
+{
+       return &ks_pcie_am654_epc_features;
+}
+
+static const struct dw_pcie_ep_ops ks_pcie_am654_ep_ops = {
+       .ep_init = ks_pcie_am654_ep_init,
+       .raise_irq = ks_pcie_am654_raise_irq,
+       .get_features = &ks_pcie_am654_get_features,
+};
+
+static int __init ks_pcie_add_pcie_ep(struct keystone_pcie *ks_pcie,
+                                     struct platform_device *pdev)
+{
+       int ret;
+       struct dw_pcie_ep *ep;
+       struct resource *res;
+       struct device *dev = &pdev->dev;
+       struct dw_pcie *pci = ks_pcie->pci;
+
+       ep = &pci->ep;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
+       if (!res)
+               return -EINVAL;
+
+       ep->phys_base = res->start;
+       ep->addr_size = resource_size(res);
+
+       ret = dw_pcie_ep_init(ep);
+       if (ret) {
+               dev_err(dev, "failed to initialize endpoint\n");
+               return ret;
+       }
+
+       return 0;
+}
+
 static void ks_pcie_disable_phy(struct keystone_pcie *ks_pcie)
 {
        int num_lanes = ks_pcie->num_lanes;
@@ -873,6 +1036,10 @@ static int ks_pcie_enable_phy(struct keystone_pcie *ks_pcie)
        int num_lanes = ks_pcie->num_lanes;
 
        for (i = 0; i < num_lanes; i++) {
+               ret = phy_reset(ks_pcie->phy[i]);
+               if (ret < 0)
+                       goto err_phy;
+
                ret = phy_init(ks_pcie->phy[i]);
                if (ret < 0)
                        goto err_phy;
@@ -895,20 +1062,161 @@ err_phy:
        return ret;
 }
 
+static int ks_pcie_set_mode(struct device *dev)
+{
+       struct device_node *np = dev->of_node;
+       struct regmap *syscon;
+       u32 val;
+       u32 mask;
+       int ret = 0;
+
+       syscon = syscon_regmap_lookup_by_phandle(np, "ti,syscon-pcie-mode");
+       if (IS_ERR(syscon))
+               return 0;
+
+       mask = KS_PCIE_DEV_TYPE_MASK | KS_PCIE_SYSCLOCKOUTEN;
+       val = KS_PCIE_DEV_TYPE(RC) | KS_PCIE_SYSCLOCKOUTEN;
+
+       ret = regmap_update_bits(syscon, 0, mask, val);
+       if (ret) {
+               dev_err(dev, "failed to set pcie mode\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int ks_pcie_am654_set_mode(struct device *dev,
+                                 enum dw_pcie_device_mode mode)
+{
+       struct device_node *np = dev->of_node;
+       struct regmap *syscon;
+       u32 val;
+       u32 mask;
+       int ret = 0;
+
+       syscon = syscon_regmap_lookup_by_phandle(np, "ti,syscon-pcie-mode");
+       if (IS_ERR(syscon))
+               return 0;
+
+       mask = AM654_PCIE_DEV_TYPE_MASK;
+
+       switch (mode) {
+       case DW_PCIE_RC_TYPE:
+               val = RC;
+               break;
+       case DW_PCIE_EP_TYPE:
+               val = EP;
+               break;
+       default:
+               dev_err(dev, "INVALID device type %d\n", mode);
+               return -EINVAL;
+       }
+
+       ret = regmap_update_bits(syscon, 0, mask, val);
+       if (ret) {
+               dev_err(dev, "failed to set pcie mode\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static void ks_pcie_set_link_speed(struct dw_pcie *pci, int link_speed)
+{
+       u32 val;
+
+       dw_pcie_dbi_ro_wr_en(pci);
+
+       val = dw_pcie_readl_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKCAP);
+       if ((val & PCI_EXP_LNKCAP_SLS) != link_speed) {
+               val &= ~((u32)PCI_EXP_LNKCAP_SLS);
+               val |= link_speed;
+               dw_pcie_writel_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKCAP,
+                                  val);
+       }
+
+       val = dw_pcie_readl_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKCTL2);
+       if ((val & PCI_EXP_LNKCAP_SLS) != link_speed) {
+               val &= ~((u32)PCI_EXP_LNKCAP_SLS);
+               val |= link_speed;
+               dw_pcie_writel_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKCTL2,
+                                  val);
+       }
+
+       dw_pcie_dbi_ro_wr_dis(pci);
+}
+
+static const struct ks_pcie_of_data ks_pcie_rc_of_data = {
+       .host_ops = &ks_pcie_host_ops,
+       .version = 0x365A,
+};
+
+static const struct ks_pcie_of_data ks_pcie_am654_rc_of_data = {
+       .host_ops = &ks_pcie_am654_host_ops,
+       .mode = DW_PCIE_RC_TYPE,
+       .version = 0x490A,
+};
+
+static const struct ks_pcie_of_data ks_pcie_am654_ep_of_data = {
+       .ep_ops = &ks_pcie_am654_ep_ops,
+       .mode = DW_PCIE_EP_TYPE,
+       .version = 0x490A,
+};
+
+static const struct of_device_id ks_pcie_of_match[] = {
+       {
+               .type = "pci",
+               .data = &ks_pcie_rc_of_data,
+               .compatible = "ti,keystone-pcie",
+       },
+       {
+               .data = &ks_pcie_am654_rc_of_data,
+               .compatible = "ti,am654-pcie-rc",
+       },
+       {
+               .data = &ks_pcie_am654_ep_of_data,
+               .compatible = "ti,am654-pcie-ep",
+       },
+       { },
+};
+
 static int __init ks_pcie_probe(struct platform_device *pdev)
 {
+       const struct dw_pcie_host_ops *host_ops;
+       const struct dw_pcie_ep_ops *ep_ops;
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
+       const struct ks_pcie_of_data *data;
+       const struct of_device_id *match;
+       enum dw_pcie_device_mode mode;
        struct dw_pcie *pci;
        struct keystone_pcie *ks_pcie;
        struct device_link **link;
+       struct gpio_desc *gpiod;
+       void __iomem *atu_base;
+       struct resource *res;
+       unsigned int version;
+       void __iomem *base;
        u32 num_viewport;
        struct phy **phy;
+       int link_speed;
        u32 num_lanes;
        char name[10];
        int ret;
+       int irq;
        int i;
 
+       match = of_match_device(of_match_ptr(ks_pcie_of_match), dev);
+       data = (struct ks_pcie_of_data *)match->data;
+       if (!data)
+               return -EINVAL;
+
+       version = data->version;
+       host_ops = data->host_ops;
+       ep_ops = data->ep_ops;
+       mode = data->mode;
+
        ks_pcie = devm_kzalloc(dev, sizeof(*ks_pcie), GFP_KERNEL);
        if (!ks_pcie)
                return -ENOMEM;
@@ -917,12 +1225,38 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
        if (!pci)
                return -ENOMEM;
 
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "app");
+       ks_pcie->va_app_base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(ks_pcie->va_app_base))
+               return PTR_ERR(ks_pcie->va_app_base);
+
+       ks_pcie->app = *res;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbics");
+       base = devm_pci_remap_cfg_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       if (of_device_is_compatible(np, "ti,am654-pcie-rc"))
+               ks_pcie->is_am6 = true;
+
+       pci->dbi_base = base;
+       pci->dbi_base2 = base;
        pci->dev = dev;
        pci->ops = &ks_pcie_dw_pcie_ops;
+       pci->version = version;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(dev, "missing IRQ resource: %d\n", irq);
+               return irq;
+       }
 
-       ret = of_property_read_u32(np, "num-viewport", &num_viewport);
+       ret = request_irq(irq, ks_pcie_err_irq_handler, IRQF_SHARED,
+                         "ks-pcie-error-irq", ks_pcie);
        if (ret < 0) {
-               dev_err(dev, "unable to read *num-viewport* property\n");
+               dev_err(dev, "failed to request error IRQ %d\n",
+                       irq);
                return ret;
        }
 
@@ -960,9 +1294,17 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
        ks_pcie->pci = pci;
        ks_pcie->link = link;
        ks_pcie->num_lanes = num_lanes;
-       ks_pcie->num_viewport = num_viewport;
        ks_pcie->phy = phy;
 
+       gpiod = devm_gpiod_get_optional(dev, "reset",
+                                       GPIOD_OUT_LOW);
+       if (IS_ERR(gpiod)) {
+               ret = PTR_ERR(gpiod);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev, "Failed to get reset GPIO\n");
+               goto err_link;
+       }
+
        ret = ks_pcie_enable_phy(ks_pcie);
        if (ret) {
                dev_err(dev, "failed to enable phy\n");
@@ -977,9 +1319,79 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
                goto err_get_sync;
        }
 
-       ret = ks_pcie_add_pcie_port(ks_pcie, pdev);
-       if (ret < 0)
-               goto err_get_sync;
+       if (pci->version >= 0x480A) {
+               res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "atu");
+               atu_base = devm_ioremap_resource(dev, res);
+               if (IS_ERR(atu_base)) {
+                       ret = PTR_ERR(atu_base);
+                       goto err_get_sync;
+               }
+
+               pci->atu_base = atu_base;
+
+               ret = ks_pcie_am654_set_mode(dev, mode);
+               if (ret < 0)
+                       goto err_get_sync;
+       } else {
+               ret = ks_pcie_set_mode(dev);
+               if (ret < 0)
+                       goto err_get_sync;
+       }
+
+       link_speed = of_pci_get_max_link_speed(np);
+       if (link_speed < 0)
+               link_speed = 2;
+
+       ks_pcie_set_link_speed(pci, link_speed);
+
+       switch (mode) {
+       case DW_PCIE_RC_TYPE:
+               if (!IS_ENABLED(CONFIG_PCI_KEYSTONE_HOST)) {
+                       ret = -ENODEV;
+                       goto err_get_sync;
+               }
+
+               ret = of_property_read_u32(np, "num-viewport", &num_viewport);
+               if (ret < 0) {
+                       dev_err(dev, "unable to read *num-viewport* property\n");
+                       return ret;
+               }
+
+               /*
+                * "Power Sequencing and Reset Signal Timings" table in
+                * PCI EXPRESS CARD ELECTROMECHANICAL SPECIFICATION, REV. 2.0
+                * indicates PERST# should be deasserted after minimum of 100us
+                * once REFCLK is stable. The REFCLK to the connector in RC
+                * mode is selected while enabling the PHY. So deassert PERST#
+                * after 100 us.
+                */
+               if (gpiod) {
+                       usleep_range(100, 200);
+                       gpiod_set_value_cansleep(gpiod, 1);
+               }
+
+               ks_pcie->num_viewport = num_viewport;
+               pci->pp.ops = host_ops;
+               ret = ks_pcie_add_pcie_port(ks_pcie, pdev);
+               if (ret < 0)
+                       goto err_get_sync;
+               break;
+       case DW_PCIE_EP_TYPE:
+               if (!IS_ENABLED(CONFIG_PCI_KEYSTONE_EP)) {
+                       ret = -ENODEV;
+                       goto err_get_sync;
+               }
+
+               pci->ep.ops = ep_ops;
+               ret = ks_pcie_add_pcie_ep(ks_pcie, pdev);
+               if (ret < 0)
+                       goto err_get_sync;
+               break;
+       default:
+               dev_err(dev, "INVALID device type %d\n", mode);
+       }
+
+       ks_pcie_enable_error_irq(ks_pcie);
 
        return 0;
 
index a42c9c3..be61d96 100644 (file)
@@ -79,7 +79,7 @@ static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
        }
 }
 
-static struct dw_pcie_ep_ops pcie_ep_ops = {
+static const struct dw_pcie_ep_ops pcie_ep_ops = {
        .ep_init = ls_pcie_ep_init,
        .raise_irq = ls_pcie_ep_raise_irq,
        .get_features = ls_pcie_ep_get_features,
index ce45bde..3a5fa26 100644 (file)
@@ -201,6 +201,7 @@ static int ls_pcie_msi_host_init(struct pcie_port *pp)
                return -EINVAL;
        }
 
+       of_node_put(msi_node);
        return 0;
 }
 
diff --git a/drivers/pci/controller/dwc/pcie-al.c b/drivers/pci/controller/dwc/pcie-al.c
new file mode 100644 (file)
index 0000000..3ab58f0
--- /dev/null
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe host controller driver for Amazon's Annapurna Labs IP (used in chips
+ * such as Graviton and Alpine)
+ *
+ * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Author: Jonathan Chocron <jonnyc@amazon.com>
+ */
+
+#include <linux/pci.h>
+#include <linux/pci-ecam.h>
+#include <linux/pci-acpi.h>
+#include "../../pci.h"
+
+#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
+
+struct al_pcie_acpi  {
+       void __iomem *dbi_base;
+};
+
+static void __iomem *al_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
+                                    int where)
+{
+       struct pci_config_window *cfg = bus->sysdata;
+       struct al_pcie_acpi *pcie = cfg->priv;
+       void __iomem *dbi_base = pcie->dbi_base;
+
+       if (bus->number == cfg->busr.start) {
+               /*
+                * The DW PCIe core doesn't filter out transactions to other
+                * devices/functions on the root bus num, so we do this here.
+                */
+               if (PCI_SLOT(devfn) > 0)
+                       return NULL;
+               else
+                       return dbi_base + where;
+       }
+
+       return pci_ecam_map_bus(bus, devfn, where);
+}
+
+static int al_pcie_init(struct pci_config_window *cfg)
+{
+       struct device *dev = cfg->parent;
+       struct acpi_device *adev = to_acpi_device(dev);
+       struct acpi_pci_root *root = acpi_driver_data(adev);
+       struct al_pcie_acpi *al_pcie;
+       struct resource *res;
+       int ret;
+
+       al_pcie = devm_kzalloc(dev, sizeof(*al_pcie), GFP_KERNEL);
+       if (!al_pcie)
+               return -ENOMEM;
+
+       res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
+       if (!res)
+               return -ENOMEM;
+
+       ret = acpi_get_rc_resources(dev, "AMZN0001", root->segment, res);
+       if (ret) {
+               dev_err(dev, "can't get rc dbi base address for SEG %d\n",
+                       root->segment);
+               return ret;
+       }
+
+       dev_dbg(dev, "Root port dbi res: %pR\n", res);
+
+       al_pcie->dbi_base = devm_pci_remap_cfg_resource(dev, res);
+       if (IS_ERR(al_pcie->dbi_base)) {
+               long err = PTR_ERR(al_pcie->dbi_base);
+
+               dev_err(dev, "couldn't remap dbi base %pR (err:%ld)\n",
+                       res, err);
+               return err;
+       }
+
+       cfg->priv = al_pcie;
+
+       return 0;
+}
+
+struct pci_ecam_ops al_pcie_ops = {
+       .bus_shift    = 20,
+       .init         =  al_pcie_init,
+       .pci_ops      = {
+               .map_bus    = al_pcie_map_bus,
+               .read       = pci_generic_config_read,
+               .write      = pci_generic_config_write,
+       }
+};
+
+#endif /* defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) */
index dba83ab..d00252b 100644 (file)
@@ -444,7 +444,7 @@ static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
        return 0;
 }
 
-static struct dw_pcie_ep_ops pcie_ep_ops = {
+static const struct dw_pcie_ep_ops pcie_ep_ops = {
        .ep_init = artpec6_pcie_ep_init,
        .raise_irq = artpec6_pcie_raise_irq,
 };
index 24f5a77..2bf5a35 100644 (file)
@@ -46,16 +46,19 @@ static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie *pci, u8 cap_ptr,
        u8 cap_id, next_cap_ptr;
        u16 reg;
 
+       if (!cap_ptr)
+               return 0;
+
        reg = dw_pcie_readw_dbi(pci, cap_ptr);
-       next_cap_ptr = (reg & 0xff00) >> 8;
        cap_id = (reg & 0x00ff);
 
-       if (!next_cap_ptr || cap_id > PCI_CAP_ID_MAX)
+       if (cap_id > PCI_CAP_ID_MAX)
                return 0;
 
        if (cap_id == cap)
                return cap_ptr;
 
+       next_cap_ptr = (reg & 0xff00) >> 8;
        return __dw_pcie_ep_find_next_cap(pci, next_cap_ptr, cap);
 }
 
@@ -67,9 +70,6 @@ static u8 dw_pcie_ep_find_capability(struct dw_pcie *pci, u8 cap)
        reg = dw_pcie_readw_dbi(pci, PCI_CAPABILITY_LIST);
        next_cap_ptr = (reg & 0x00ff);
 
-       if (!next_cap_ptr)
-               return 0;
-
        return __dw_pcie_ep_find_next_cap(pci, next_cap_ptr, cap);
 }
 
@@ -397,6 +397,7 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
 {
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
        struct pci_epc *epc = ep->epc;
+       unsigned int aligned_offset;
        u16 msg_ctrl, msg_data;
        u32 msg_addr_lower, msg_addr_upper, reg;
        u64 msg_addr;
@@ -422,13 +423,15 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
                reg = ep->msi_cap + PCI_MSI_DATA_32;
                msg_data = dw_pcie_readw_dbi(pci, reg);
        }
-       msg_addr = ((u64) msg_addr_upper) << 32 | msg_addr_lower;
+       aligned_offset = msg_addr_lower & (epc->mem->page_size - 1);
+       msg_addr = ((u64)msg_addr_upper) << 32 |
+                       (msg_addr_lower & ~aligned_offset);
        ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr,
                                  epc->mem->page_size);
        if (ret)
                return ret;
 
-       writel(msg_data | (interrupt_num - 1), ep->msi_mem);
+       writel(msg_data | (interrupt_num - 1), ep->msi_mem + aligned_offset);
 
        dw_pcie_ep_unmap_addr(epc, func_no, ep->msi_mem_phys);
 
@@ -504,10 +507,32 @@ void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
        pci_epc_mem_exit(epc);
 }
 
+static unsigned int dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int cap)
+{
+       u32 header;
+       int pos = PCI_CFG_SPACE_SIZE;
+
+       while (pos) {
+               header = dw_pcie_readl_dbi(pci, pos);
+               if (PCI_EXT_CAP_ID(header) == cap)
+                       return pos;
+
+               pos = PCI_EXT_CAP_NEXT(header);
+               if (!pos)
+                       break;
+       }
+
+       return 0;
+}
+
 int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 {
+       int i;
        int ret;
+       u32 reg;
        void *addr;
+       unsigned int nbars;
+       unsigned int offset;
        struct pci_epc *epc;
        struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
        struct device *dev = pci->dev;
@@ -517,10 +542,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
                dev_err(dev, "dbi_base/dbi_base2 is not populated\n");
                return -EINVAL;
        }
-       if (pci->iatu_unroll_enabled && !pci->atu_base) {
-               dev_err(dev, "atu_base is not populated\n");
-               return -EINVAL;
-       }
 
        ret = of_property_read_u32(np, "num-ib-windows", &ep->num_ib_windows);
        if (ret < 0) {
@@ -595,6 +616,18 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 
        ep->msix_cap = dw_pcie_ep_find_capability(pci, PCI_CAP_ID_MSIX);
 
+       offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
+       if (offset) {
+               reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
+               nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >>
+                       PCI_REBAR_CTRL_NBAR_SHIFT;
+
+               dw_pcie_dbi_ro_wr_en(pci);
+               for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL)
+                       dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0);
+               dw_pcie_dbi_ro_wr_dis(pci);
+       }
+
        dw_pcie_setup(pci);
 
        return 0;
index 25087d3..77db325 100644 (file)
@@ -126,18 +126,12 @@ static void dw_pci_setup_msi_msg(struct irq_data *d, struct msi_msg *msg)
        struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
        u64 msi_target;
 
-       if (pp->ops->get_msi_addr)
-               msi_target = pp->ops->get_msi_addr(pp);
-       else
-               msi_target = (u64)pp->msi_data;
+       msi_target = (u64)pp->msi_data;
 
        msg->address_lo = lower_32_bits(msi_target);
        msg->address_hi = upper_32_bits(msi_target);
 
-       if (pp->ops->get_msi_data)
-               msg->data = pp->ops->get_msi_data(pp, d->hwirq);
-       else
-               msg->data = d->hwirq;
+       msg->data = d->hwirq;
 
        dev_dbg(pci->dev, "msi#%d address_hi %#x address_lo %#x\n",
                (int)d->hwirq, msg->address_hi, msg->address_lo);
@@ -157,17 +151,13 @@ static void dw_pci_bottom_mask(struct irq_data *d)
 
        raw_spin_lock_irqsave(&pp->lock, flags);
 
-       if (pp->ops->msi_clear_irq) {
-               pp->ops->msi_clear_irq(pp, d->hwirq);
-       } else {
-               ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
-               res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
-               bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
+       ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
+       res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
+       bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
 
-               pp->irq_mask[ctrl] |= BIT(bit);
-               dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4,
-                                   pp->irq_mask[ctrl]);
-       }
+       pp->irq_mask[ctrl] |= BIT(bit);
+       dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4,
+                           pp->irq_mask[ctrl]);
 
        raw_spin_unlock_irqrestore(&pp->lock, flags);
 }
@@ -180,17 +170,13 @@ static void dw_pci_bottom_unmask(struct irq_data *d)
 
        raw_spin_lock_irqsave(&pp->lock, flags);
 
-       if (pp->ops->msi_set_irq) {
-               pp->ops->msi_set_irq(pp, d->hwirq);
-       } else {
-               ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
-               res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
-               bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
+       ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
+       res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
+       bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
 
-               pp->irq_mask[ctrl] &= ~BIT(bit);
-               dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4,
-                                   pp->irq_mask[ctrl]);
-       }
+       pp->irq_mask[ctrl] &= ~BIT(bit);
+       dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4,
+                           pp->irq_mask[ctrl]);
 
        raw_spin_unlock_irqrestore(&pp->lock, flags);
 }
@@ -199,20 +185,12 @@ static void dw_pci_bottom_ack(struct irq_data *d)
 {
        struct pcie_port *pp  = irq_data_get_irq_chip_data(d);
        unsigned int res, bit, ctrl;
-       unsigned long flags;
 
        ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
        res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
        bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
 
-       raw_spin_lock_irqsave(&pp->lock, flags);
-
        dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + res, 4, BIT(bit));
-
-       if (pp->ops->msi_irq_ack)
-               pp->ops->msi_irq_ack(d->hwirq, pp);
-
-       raw_spin_unlock_irqrestore(&pp->lock, flags);
 }
 
 static struct irq_chip dw_pci_msi_bottom_irq_chip = {
@@ -245,7 +223,7 @@ static int dw_pcie_irq_domain_alloc(struct irq_domain *domain,
 
        for (i = 0; i < nr_irqs; i++)
                irq_domain_set_info(domain, virq + i, bit + i,
-                                   &dw_pci_msi_bottom_irq_chip,
+                                   pp->msi_irq_chip,
                                    pp, handle_edge_irq,
                                    NULL, NULL);
 
@@ -298,25 +276,31 @@ int dw_pcie_allocate_domains(struct pcie_port *pp)
 
 void dw_pcie_free_msi(struct pcie_port *pp)
 {
-       irq_set_chained_handler(pp->msi_irq, NULL);
-       irq_set_handler_data(pp->msi_irq, NULL);
+       if (pp->msi_irq) {
+               irq_set_chained_handler(pp->msi_irq, NULL);
+               irq_set_handler_data(pp->msi_irq, NULL);
+       }
 
        irq_domain_remove(pp->msi_domain);
        irq_domain_remove(pp->irq_domain);
+
+       if (pp->msi_page)
+               __free_page(pp->msi_page);
 }
 
 void dw_pcie_msi_init(struct pcie_port *pp)
 {
        struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
        struct device *dev = pci->dev;
-       struct page *page;
        u64 msi_target;
 
-       page = alloc_page(GFP_KERNEL);
-       pp->msi_data = dma_map_page(dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
+       pp->msi_page = alloc_page(GFP_KERNEL);
+       pp->msi_data = dma_map_page(dev, pp->msi_page, 0, PAGE_SIZE,
+                                   DMA_FROM_DEVICE);
        if (dma_mapping_error(dev, pp->msi_data)) {
                dev_err(dev, "Failed to map MSI data\n");
-               __free_page(page);
+               __free_page(pp->msi_page);
+               pp->msi_page = NULL;
                return;
        }
        msi_target = (u64)pp->msi_data;
@@ -335,7 +319,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
        struct device_node *np = dev->of_node;
        struct platform_device *pdev = to_platform_device(dev);
        struct resource_entry *win, *tmp;
-       struct pci_bus *bus, *child;
+       struct pci_bus *child;
        struct pci_host_bridge *bridge;
        struct resource *cfg_res;
        int ret;
@@ -352,7 +336,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
                dev_err(dev, "Missing *config* reg space\n");
        }
 
-       bridge = pci_alloc_host_bridge(0);
+       bridge = devm_pci_alloc_host_bridge(dev, 0);
        if (!bridge)
                return -ENOMEM;
 
@@ -363,7 +347,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 
        ret = devm_request_pci_bus_resources(dev, &bridge->windows);
        if (ret)
-               goto error;
+               return ret;
 
        /* Get the I/O and memory ranges from DT */
        resource_list_for_each_entry_safe(win, tmp, &bridge->windows) {
@@ -407,8 +391,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
                                                resource_size(pp->cfg));
                if (!pci->dbi_base) {
                        dev_err(dev, "Error with ioremap\n");
-                       ret = -ENOMEM;
-                       goto error;
+                       return -ENOMEM;
                }
        }
 
@@ -419,8 +402,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
                                        pp->cfg0_base, pp->cfg0_size);
                if (!pp->va_cfg0_base) {
                        dev_err(dev, "Error with ioremap in function\n");
-                       ret = -ENOMEM;
-                       goto error;
+                       return -ENOMEM;
                }
        }
 
@@ -430,8 +412,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
                                                pp->cfg1_size);
                if (!pp->va_cfg1_base) {
                        dev_err(dev, "Error with ioremap\n");
-                       ret = -ENOMEM;
-                       goto error;
+                       return -ENOMEM;
                }
        }
 
@@ -439,7 +420,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
        if (ret)
                pci->num_viewport = 2;
 
-       if (IS_ENABLED(CONFIG_PCI_MSI) && pci_msi_enabled()) {
+       if (pci_msi_enabled()) {
                /*
                 * If a specific SoC driver needs to change the
                 * default number of vectors, it needs to implement
@@ -454,14 +435,16 @@ int dw_pcie_host_init(struct pcie_port *pp)
                            pp->num_vectors == 0) {
                                dev_err(dev,
                                        "Invalid number of vectors\n");
-                               goto error;
+                               return -EINVAL;
                        }
                }
 
                if (!pp->ops->msi_host_init) {
+                       pp->msi_irq_chip = &dw_pci_msi_bottom_irq_chip;
+
                        ret = dw_pcie_allocate_domains(pp);
                        if (ret)
-                               goto error;
+                               return ret;
 
                        if (pp->msi_irq)
                                irq_set_chained_handler_and_data(pp->msi_irq,
@@ -470,14 +453,14 @@ int dw_pcie_host_init(struct pcie_port *pp)
                } else {
                        ret = pp->ops->msi_host_init(pp);
                        if (ret < 0)
-                               goto error;
+                               return ret;
                }
        }
 
        if (pp->ops->host_init) {
                ret = pp->ops->host_init(pp);
                if (ret)
-                       goto error;
+                       goto err_free_msi;
        }
 
        pp->root_bus_nr = pp->busn->start;
@@ -491,24 +474,25 @@ int dw_pcie_host_init(struct pcie_port *pp)
 
        ret = pci_scan_root_bus_bridge(bridge);
        if (ret)
-               goto error;
+               goto err_free_msi;
 
-       bus = bridge->bus;
+       pp->root_bus = bridge->bus;
 
        if (pp->ops->scan_bus)
                pp->ops->scan_bus(pp);
 
-       pci_bus_size_bridges(bus);
-       pci_bus_assign_resources(bus);
+       pci_bus_size_bridges(pp->root_bus);
+       pci_bus_assign_resources(pp->root_bus);
 
-       list_for_each_entry(child, &bus->children, node)
+       list_for_each_entry(child, &pp->root_bus->children, node)
                pcie_bus_configure_settings(child);
 
-       pci_bus_add_devices(bus);
+       pci_bus_add_devices(pp->root_bus);
        return 0;
 
-error:
-       pci_free_host_bridge(bridge);
+err_free_msi:
+       if (pci_msi_enabled() && !pp->ops->msi_host_init)
+               dw_pcie_free_msi(pp);
        return ret;
 }
 
@@ -628,17 +612,6 @@ static struct pci_ops dw_pcie_ops = {
        .write = dw_pcie_wr_conf,
 };
 
-static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci)
-{
-       u32 val;
-
-       val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT);
-       if (val == 0xffffffff)
-               return 1;
-
-       return 0;
-}
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
        u32 val, ctrl, num_ctrls;
@@ -646,17 +619,19 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
 
        dw_pcie_setup(pci);
 
-       num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
-
-       /* Initialize IRQ Status array */
-       for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
-               pp->irq_mask[ctrl] = ~0;
-               dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK +
-                                       (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
-                                   4, pp->irq_mask[ctrl]);
-               dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE +
-                                       (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
-                                   4, ~0);
+       if (!pp->ops->msi_host_init) {
+               num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
+
+               /* Initialize IRQ Status array */
+               for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
+                       pp->irq_mask[ctrl] = ~0;
+                       dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK +
+                                           (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
+                                           4, pp->irq_mask[ctrl]);
+                       dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE +
+                                           (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
+                                           4, ~0);
+               }
        }
 
        /* Setup RC BARs */
@@ -690,14 +665,6 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
         * we should not program the ATU here.
         */
        if (!pp->ops->rd_other_conf) {
-               /* Get iATU unroll support */
-               pci->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pci);
-               dev_dbg(pci->dev, "iATU unroll: %s\n",
-                       pci->iatu_unroll_enabled ? "enabled" : "disabled");
-
-               if (pci->iatu_unroll_enabled && !pci->atu_base)
-                       pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
-
                dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0,
                                          PCIE_ATU_TYPE_MEM, pp->mem_base,
                                          pp->mem_bus_addr, pp->mem_size);
index 932dbd0..b58fdcb 100644 (file)
@@ -106,7 +106,7 @@ dw_plat_pcie_get_features(struct dw_pcie_ep *ep)
        return &dw_plat_pcie_epc_features;
 }
 
-static struct dw_pcie_ep_ops pcie_ep_ops = {
+static const struct dw_pcie_ep_ops pcie_ep_ops = {
        .ep_init = dw_plat_pcie_ep_init,
        .raise_irq = dw_plat_pcie_ep_raise_irq,
        .get_features = dw_plat_pcie_get_features,
index 31f6331..9d7c51c 100644 (file)
 
 #include "pcie-designware.h"
 
-/* PCIe Port Logic registers */
-#define PLR_OFFSET                     0x700
-#define PCIE_PHY_DEBUG_R1              (PLR_OFFSET + 0x2c)
-#define PCIE_PHY_DEBUG_R1_LINK_UP      (0x1 << 4)
-#define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING     (0x1 << 29)
-
 int dw_pcie_read(void __iomem *addr, int size, u32 *val)
 {
        if (!IS_ALIGNED((uintptr_t)addr, size)) {
@@ -89,6 +83,37 @@ void __dw_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
                dev_err(pci->dev, "Write DBI address failed\n");
 }
 
+u32 __dw_pcie_read_dbi2(struct dw_pcie *pci, void __iomem *base, u32 reg,
+                       size_t size)
+{
+       int ret;
+       u32 val;
+
+       if (pci->ops->read_dbi2)
+               return pci->ops->read_dbi2(pci, base, reg, size);
+
+       ret = dw_pcie_read(base + reg, size, &val);
+       if (ret)
+               dev_err(pci->dev, "read DBI address failed\n");
+
+       return val;
+}
+
+void __dw_pcie_write_dbi2(struct dw_pcie *pci, void __iomem *base, u32 reg,
+                         size_t size, u32 val)
+{
+       int ret;
+
+       if (pci->ops->write_dbi2) {
+               pci->ops->write_dbi2(pci, base, reg, size, val);
+               return;
+       }
+
+       ret = dw_pcie_write(base + reg, size, val);
+       if (ret)
+               dev_err(pci->dev, "write DBI address failed\n");
+}
+
 static u32 dw_pcie_readl_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg)
 {
        u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
@@ -334,9 +359,20 @@ int dw_pcie_link_up(struct dw_pcie *pci)
        if (pci->ops->link_up)
                return pci->ops->link_up(pci);
 
-       val = readl(pci->dbi_base + PCIE_PHY_DEBUG_R1);
-       return ((val & PCIE_PHY_DEBUG_R1_LINK_UP) &&
-               (!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING)));
+       val = readl(pci->dbi_base + PCIE_PORT_DEBUG1);
+       return ((val & PCIE_PORT_DEBUG1_LINK_UP) &&
+               (!(val & PCIE_PORT_DEBUG1_LINK_IN_TRAINING)));
+}
+
+static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci)
+{
+       u32 val;
+
+       val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT);
+       if (val == 0xffffffff)
+               return 1;
+
+       return 0;
 }
 
 void dw_pcie_setup(struct dw_pcie *pci)
@@ -347,6 +383,16 @@ void dw_pcie_setup(struct dw_pcie *pci)
        struct device *dev = pci->dev;
        struct device_node *np = dev->of_node;
 
+       if (pci->version >= 0x480A || (!pci->version &&
+                                      dw_pcie_iatu_unroll_enabled(pci))) {
+               pci->iatu_unroll_enabled = true;
+               if (!pci->atu_base)
+                       pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
+       }
+       dev_dbg(pci->dev, "iATU unroll: %s\n", pci->iatu_unroll_enabled ?
+               "enabled" : "disabled");
+
+
        ret = of_property_read_u32(np, "num-lanes", &lanes);
        if (ret)
                lanes = 0;
index 377f4c0..b8993f2 100644 (file)
@@ -41,6 +41,9 @@
 #define PCIE_PORT_DEBUG0               0x728
 #define PORT_LOGIC_LTSSM_STATE_MASK    0x1f
 #define PORT_LOGIC_LTSSM_STATE_L0      0x11
+#define PCIE_PORT_DEBUG1               0x72C
+#define PCIE_PORT_DEBUG1_LINK_UP               BIT(4)
+#define PCIE_PORT_DEBUG1_LINK_IN_TRAINING      BIT(29)
 
 #define PCIE_LINK_WIDTH_SPEED_CONTROL  0x80C
 #define PORT_LOGIC_SPEED_CHANGE                BIT(17)
@@ -145,14 +148,9 @@ struct dw_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 (*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);
-       u32 (*get_msi_data)(struct pcie_port *pp, int pos);
        void (*scan_bus)(struct pcie_port *pp);
        void (*set_num_vectors)(struct pcie_port *pp);
        int (*msi_host_init)(struct pcie_port *pp);
-       void (*msi_irq_ack)(int irq, struct pcie_port *pp);
 };
 
 struct pcie_port {
@@ -179,8 +177,11 @@ struct pcie_port {
        struct irq_domain       *irq_domain;
        struct irq_domain       *msi_domain;
        dma_addr_t              msi_data;
+       struct page             *msi_page;
+       struct irq_chip         *msi_irq_chip;
        u32                     num_vectors;
        u32                     irq_mask[MAX_MSI_CTRLS];
+       struct pci_bus          *root_bus;
        raw_spinlock_t          lock;
        DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
 };
@@ -200,7 +201,7 @@ struct dw_pcie_ep_ops {
 
 struct dw_pcie_ep {
        struct pci_epc          *epc;
-       struct dw_pcie_ep_ops   *ops;
+       const struct dw_pcie_ep_ops *ops;
        phys_addr_t             phys_base;
        size_t                  addr_size;
        size_t                  page_size;
@@ -222,6 +223,10 @@ struct dw_pcie_ops {
                            size_t size);
        void    (*write_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg,
                             size_t size, u32 val);
+       u32     (*read_dbi2)(struct dw_pcie *pcie, void __iomem *base, u32 reg,
+                            size_t size);
+       void    (*write_dbi2)(struct dw_pcie *pcie, void __iomem *base, u32 reg,
+                             size_t size, u32 val);
        int     (*link_up)(struct dw_pcie *pcie);
        int     (*start_link)(struct dw_pcie *pcie);
        void    (*stop_link)(struct dw_pcie *pcie);
@@ -238,6 +243,7 @@ struct dw_pcie {
        struct pcie_port        pp;
        struct dw_pcie_ep       ep;
        const struct dw_pcie_ops *ops;
+       unsigned int            version;
 };
 
 #define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp)
@@ -252,6 +258,10 @@ u32 __dw_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
                       size_t size);
 void __dw_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
                         size_t size, u32 val);
+u32 __dw_pcie_read_dbi2(struct dw_pcie *pci, void __iomem *base, u32 reg,
+                       size_t size);
+void __dw_pcie_write_dbi2(struct dw_pcie *pci, void __iomem *base, u32 reg,
+                         size_t size, u32 val);
 int dw_pcie_link_up(struct dw_pcie *pci);
 int dw_pcie_wait_for_link(struct dw_pcie *pci);
 void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index,
@@ -295,12 +305,12 @@ static inline u8 dw_pcie_readb_dbi(struct dw_pcie *pci, u32 reg)
 
 static inline void dw_pcie_writel_dbi2(struct dw_pcie *pci, u32 reg, u32 val)
 {
-       __dw_pcie_write_dbi(pci, pci->dbi_base2, reg, 0x4, val);
+       __dw_pcie_write_dbi2(pci, pci->dbi_base2, reg, 0x4, val);
 }
 
 static inline u32 dw_pcie_readl_dbi2(struct dw_pcie *pci, u32 reg)
 {
-       return __dw_pcie_read_dbi(pci, pci->dbi_base2, reg, 0x4);
+       return __dw_pcie_read_dbi2(pci, pci->dbi_base2, reg, 0x4);
 }
 
 static inline void dw_pcie_writel_atu(struct dw_pcie *pci, u32 reg, u32 val)
index a7f7035..0ed235d 100644 (file)
@@ -1129,25 +1129,8 @@ err_deinit:
        return ret;
 }
 
-static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
-                                u32 *val)
-{
-       struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-
-       /* the device class is not reported correctly from the register */
-       if (where == PCI_CLASS_REVISION && size == 4) {
-               *val = readl(pci->dbi_base + PCI_CLASS_REVISION);
-               *val &= 0xff;   /* keep revision id */
-               *val |= PCI_CLASS_BRIDGE_PCI << 16;
-               return PCIBIOS_SUCCESSFUL;
-       }
-
-       return dw_pcie_read(pci->dbi_base + where, size, val);
-}
-
 static const struct dw_pcie_host_ops qcom_pcie_dw_ops = {
        .host_init = qcom_pcie_host_init,
-       .rd_own_conf = qcom_pcie_rd_own_conf,
 };
 
 /* Qcom IP rev.: 2.1.0 Synopsys IP rev.: 4.01a */
@@ -1309,6 +1292,12 @@ static const struct of_device_id qcom_pcie_match[] = {
        { }
 };
 
+static void qcom_fixup_class(struct pci_dev *dev)
+{
+       dev->class = PCI_CLASS_BRIDGE_PCI << 8;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, PCI_ANY_ID, qcom_fixup_class);
+
 static struct platform_driver qcom_pcie_driver = {
        .probe = qcom_pcie_probe,
        .driver = {
index d5dc402..3f30ee4 100644 (file)
@@ -270,6 +270,7 @@ static int uniphier_pcie_config_legacy_irq(struct pcie_port *pp)
        struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
        struct device_node *np = pci->dev->of_node;
        struct device_node *np_intc;
+       int ret = 0;
 
        np_intc = of_get_child_by_name(np, "legacy-interrupt-controller");
        if (!np_intc) {
@@ -280,20 +281,24 @@ static int uniphier_pcie_config_legacy_irq(struct pcie_port *pp)
        pp->irq = irq_of_parse_and_map(np_intc, 0);
        if (!pp->irq) {
                dev_err(pci->dev, "Failed to get an IRQ entry in legacy-interrupt-controller\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out_put_node;
        }
 
        priv->legacy_irq_domain = irq_domain_add_linear(np_intc, PCI_NUM_INTX,
                                                &uniphier_intx_domain_ops, pp);
        if (!priv->legacy_irq_domain) {
                dev_err(pci->dev, "Failed to get INTx domain\n");
-               return -ENODEV;
+               ret = -ENODEV;
+               goto out_put_node;
        }
 
        irq_set_chained_handler_and_data(pp->irq, uniphier_pcie_irq_handler,
                                         pp);
 
-       return 0;
+out_put_node:
+       of_node_put(np_intc);
+       return ret;
 }
 
 static int uniphier_pcie_host_init(struct pcie_port *pp)
index eb58dfd..134e030 100644 (file)
@@ -794,6 +794,7 @@ static int advk_pcie_init_irq_domain(struct advk_pcie *pcie)
        struct device_node *node = dev->of_node;
        struct device_node *pcie_intc_node;
        struct irq_chip *irq_chip;
+       int ret = 0;
 
        pcie_intc_node =  of_get_next_child(node, NULL);
        if (!pcie_intc_node) {
@@ -806,8 +807,8 @@ static int advk_pcie_init_irq_domain(struct advk_pcie *pcie)
        irq_chip->name = devm_kasprintf(dev, GFP_KERNEL, "%s-irq",
                                        dev_name(dev));
        if (!irq_chip->name) {
-               of_node_put(pcie_intc_node);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto out_put_node;
        }
 
        irq_chip->irq_mask = advk_pcie_irq_mask;
@@ -819,11 +820,13 @@ static int advk_pcie_init_irq_domain(struct advk_pcie *pcie)
                                      &advk_pcie_irq_domain_ops, pcie);
        if (!pcie->irq_domain) {
                dev_err(dev, "Failed to get a INTx IRQ domain\n");
-               of_node_put(pcie_intc_node);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto out_put_node;
        }
 
-       return 0;
+out_put_node:
+       of_node_put(pcie_intc_node);
+       return ret;
 }
 
 static void advk_pcie_remove_irq_domain(struct advk_pcie *pcie)
index dea3ec7..75a2fb9 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Simple, generic PCI host controller driver targetting firmware-initialised
+ * Simple, generic PCI host controller driver targeting firmware-initialised
  * systems and virtual machines (e.g. the PCI emulation provided by kvmtool).
  *
  * Copyright (C) 2014 ARM Limited
index 95441a3..82acd61 100644 (file)
@@ -1486,6 +1486,21 @@ static void hv_pci_assign_slots(struct hv_pcibus_device *hbus)
        }
 }
 
+/*
+ * Remove entries in sysfs pci slot directory.
+ */
+static void hv_pci_remove_slots(struct hv_pcibus_device *hbus)
+{
+       struct hv_pci_dev *hpdev;
+
+       list_for_each_entry(hpdev, &hbus->children, list_entry) {
+               if (!hpdev->pci_slot)
+                       continue;
+               pci_destroy_slot(hpdev->pci_slot);
+               hpdev->pci_slot = NULL;
+       }
+}
+
 /**
  * create_root_hv_pci_bus() - Expose a new root PCI bus
  * @hbus:      Root PCI bus, as understood by this driver
@@ -1761,6 +1776,10 @@ static void pci_devices_present_work(struct work_struct *work)
                hpdev = list_first_entry(&removed, struct hv_pci_dev,
                                         list_entry);
                list_del(&hpdev->list_entry);
+
+               if (hpdev->pci_slot)
+                       pci_destroy_slot(hpdev->pci_slot);
+
                put_pcichild(hpdev);
        }
 
@@ -1900,6 +1919,9 @@ static void hv_eject_device_work(struct work_struct *work)
                         sizeof(*ejct_pkt), (unsigned long)&ctxt.pkt,
                         VM_PKT_DATA_INBAND, 0);
 
+       /* For the get_pcichild() in hv_pci_eject_device() */
+       put_pcichild(hpdev);
+       /* For the two refs got in new_pcichild_device() */
        put_pcichild(hpdev);
        put_pcichild(hpdev);
        put_hvpcibus(hpdev->hbus);
@@ -2677,6 +2699,7 @@ static int hv_pci_remove(struct hv_device *hdev)
                pci_lock_rescan_remove();
                pci_stop_root_bus(hbus->pci_bus);
                pci_remove_root_bus(hbus->pci_bus);
+               hv_pci_remove_slots(hbus);
                pci_unlock_rescan_remove();
                hbus->state = hv_pcibus_removed;
        }
index f4f53d0..464ba25 100644 (file)
@@ -231,9 +231,9 @@ struct tegra_msi {
        struct msi_controller chip;
        DECLARE_BITMAP(used, INT_PCI_MSI_NR);
        struct irq_domain *domain;
-       unsigned long pages;
        struct mutex lock;
-       u64 phys;
+       void *virt;
+       dma_addr_t phys;
        int irq;
 };
 
@@ -1536,7 +1536,7 @@ static int tegra_pcie_msi_setup(struct tegra_pcie *pcie)
        err = platform_get_irq_byname(pdev, "msi");
        if (err < 0) {
                dev_err(dev, "failed to get IRQ: %d\n", err);
-               goto err;
+               goto free_irq_domain;
        }
 
        msi->irq = err;
@@ -1545,17 +1545,35 @@ static int tegra_pcie_msi_setup(struct tegra_pcie *pcie)
                          tegra_msi_irq_chip.name, pcie);
        if (err < 0) {
                dev_err(dev, "failed to request IRQ: %d\n", err);
-               goto err;
+               goto free_irq_domain;
+       }
+
+       /* Though the PCIe controller can address >32-bit address space, to
+        * facilitate endpoints that support only 32-bit MSI target address,
+        * the mask is set to 32-bit to make sure that MSI target address is
+        * always a 32-bit address
+        */
+       err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+       if (err < 0) {
+               dev_err(dev, "failed to set DMA coherent mask: %d\n", err);
+               goto free_irq;
+       }
+
+       msi->virt = dma_alloc_attrs(dev, PAGE_SIZE, &msi->phys, GFP_KERNEL,
+                                   DMA_ATTR_NO_KERNEL_MAPPING);
+       if (!msi->virt) {
+               dev_err(dev, "failed to allocate DMA memory for MSI\n");
+               err = -ENOMEM;
+               goto free_irq;
        }
 
-       /* setup AFI/FPCI range */
-       msi->pages = __get_free_pages(GFP_KERNEL, 0);
-       msi->phys = virt_to_phys((void *)msi->pages);
        host->msi = &msi->chip;
 
        return 0;
 
-err:
+free_irq:
+       free_irq(msi->irq, pcie);
+free_irq_domain:
        irq_domain_remove(msi->domain);
        return err;
 }
@@ -1592,7 +1610,8 @@ static void tegra_pcie_msi_teardown(struct tegra_pcie *pcie)
        struct tegra_msi *msi = &pcie->msi;
        unsigned int i, irq;
 
-       free_pages(msi->pages, 0);
+       dma_free_attrs(pcie->dev, PAGE_SIZE, msi->virt, msi->phys,
+                      DMA_ATTR_NO_KERNEL_MAPPING);
 
        if (msi->irq > 0)
                free_irq(msi->irq, pcie);
index cb3401a..0a3f61b 100644 (file)
@@ -367,7 +367,7 @@ static void iproc_msi_handler(struct irq_desc *desc)
 
                /*
                 * Now go read the tail pointer again to see if there are new
-                * oustanding events that came in during the above window.
+                * outstanding events that came in during the above window.
                 */
        } while (true);
 
index c20fd6b..e3ca464 100644 (file)
 #define APB_ERR_EN_SHIFT               0
 #define APB_ERR_EN                     BIT(APB_ERR_EN_SHIFT)
 
+#define CFG_RD_SUCCESS                 0
+#define CFG_RD_UR                      1
+#define CFG_RD_CRS                     2
+#define CFG_RD_CA                      3
 #define CFG_RETRY_STATUS               0xffff0001
 #define CFG_RETRY_STATUS_TIMEOUT_US    500000 /* 500 milliseconds */
 
@@ -289,6 +293,9 @@ enum iproc_pcie_reg {
        IPROC_PCIE_IARR4,
        IPROC_PCIE_IMAP4,
 
+       /* config read status */
+       IPROC_PCIE_CFG_RD_STATUS,
+
        /* link status */
        IPROC_PCIE_LINK_STATUS,
 
@@ -350,6 +357,7 @@ static const u16 iproc_pcie_reg_paxb_v2[] = {
        [IPROC_PCIE_IMAP3]              = 0xe08,
        [IPROC_PCIE_IARR4]              = 0xe68,
        [IPROC_PCIE_IMAP4]              = 0xe70,
+       [IPROC_PCIE_CFG_RD_STATUS]      = 0xee0,
        [IPROC_PCIE_LINK_STATUS]        = 0xf0c,
        [IPROC_PCIE_APB_ERR_EN]         = 0xf40,
 };
@@ -474,10 +482,12 @@ static void __iomem *iproc_pcie_map_ep_cfg_reg(struct iproc_pcie *pcie,
        return (pcie->base + offset);
 }
 
-static unsigned int iproc_pcie_cfg_retry(void __iomem *cfg_data_p)
+static unsigned int iproc_pcie_cfg_retry(struct iproc_pcie *pcie,
+                                        void __iomem *cfg_data_p)
 {
        int timeout = CFG_RETRY_STATUS_TIMEOUT_US;
        unsigned int data;
+       u32 status;
 
        /*
         * As per PCIe spec r3.1, sec 2.3.2, CRS Software Visibility only
@@ -498,6 +508,15 @@ static unsigned int iproc_pcie_cfg_retry(void __iomem *cfg_data_p)
         */
        data = readl(cfg_data_p);
        while (data == CFG_RETRY_STATUS && timeout--) {
+               /*
+                * CRS state is set in CFG_RD status register
+                * This will handle the case where CFG_RETRY_STATUS is
+                * valid config data.
+                */
+               status = iproc_pcie_read_reg(pcie, IPROC_PCIE_CFG_RD_STATUS);
+               if (status != CFG_RD_CRS)
+                       return data;
+
                udelay(1);
                data = readl(cfg_data_p);
        }
@@ -576,7 +595,7 @@ static int iproc_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
        if (!cfg_data_p)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
-       data = iproc_pcie_cfg_retry(cfg_data_p);
+       data = iproc_pcie_cfg_retry(pcie, cfg_data_p);
 
        *val = data;
        if (size <= 2)
@@ -936,8 +955,25 @@ static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr,
                        resource_size_t window_size =
                                ob_map->window_sizes[size_idx] * SZ_1M;
 
-                       if (size < window_size)
-                               continue;
+                       /*
+                        * Keep iterating until we reach the last window and
+                        * with the minimal window size at index zero. In this
+                        * case, we take a compromise by mapping it using the
+                        * minimum window size that can be supported
+                        */
+                       if (size < window_size) {
+                               if (size_idx > 0 || window_idx > 0)
+                                       continue;
+
+                               /*
+                                * For the corner case of reaching the minimal
+                                * window size that can be supported on the
+                                * last window
+                                */
+                               axi_addr = ALIGN_DOWN(axi_addr, window_size);
+                               pci_addr = ALIGN_DOWN(pci_addr, window_size);
+                               size = window_size;
+                       }
 
                        if (!IS_ALIGNED(axi_addr, window_size) ||
                            !IS_ALIGNED(pci_addr, window_size)) {
@@ -1146,11 +1182,43 @@ err_ib:
        return ret;
 }
 
+static int iproc_pcie_add_dma_range(struct device *dev,
+                                   struct list_head *resources,
+                                   struct of_pci_range *range)
+{
+       struct resource *res;
+       struct resource_entry *entry, *tmp;
+       struct list_head *head = resources;
+
+       res = devm_kzalloc(dev, sizeof(struct resource), GFP_KERNEL);
+       if (!res)
+               return -ENOMEM;
+
+       resource_list_for_each_entry(tmp, resources) {
+               if (tmp->res->start < range->cpu_addr)
+                       head = &tmp->node;
+       }
+
+       res->start = range->cpu_addr;
+       res->end = res->start + range->size - 1;
+
+       entry = resource_list_create_entry(res, 0);
+       if (!entry)
+               return -ENOMEM;
+
+       entry->offset = res->start - range->cpu_addr;
+       resource_list_add(entry, head);
+
+       return 0;
+}
+
 static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie)
 {
+       struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
        struct of_pci_range range;
        struct of_pci_range_parser parser;
        int ret;
+       LIST_HEAD(resources);
 
        /* Get the dma-ranges from DT */
        ret = of_pci_dma_range_parser_init(&parser, pcie->dev->of_node);
@@ -1158,13 +1226,23 @@ static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie)
                return ret;
 
        for_each_of_pci_range(&parser, &range) {
+               ret = iproc_pcie_add_dma_range(pcie->dev,
+                                              &resources,
+                                              &range);
+               if (ret)
+                       goto out;
                /* Each range entry corresponds to an inbound mapping region */
                ret = iproc_pcie_setup_ib(pcie, &range, IPROC_PCIE_IB_MAP_MEM);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
+       list_splice_init(&resources, &host->dma_ranges);
+
        return 0;
+out:
+       pci_free_resource_list(&resources);
+       return ret;
 }
 
 static int iproce_pcie_get_msi(struct iproc_pcie *pcie,
@@ -1320,14 +1398,18 @@ static int iproc_pcie_msi_enable(struct iproc_pcie *pcie)
        if (pcie->need_msi_steer) {
                ret = iproc_pcie_msi_steer(pcie, msi_node);
                if (ret)
-                       return ret;
+                       goto out_put_node;
        }
 
        /*
         * If another MSI controller is being used, the call below should fail
         * but that is okay
         */
-       return iproc_msi_init(pcie, msi_node);
+       ret = iproc_msi_init(pcie, msi_node);
+
+out_put_node:
+       of_node_put(msi_node);
+       return ret;
 }
 
 static void iproc_pcie_msi_disable(struct iproc_pcie *pcie)
@@ -1347,7 +1429,6 @@ static int iproc_pcie_rev_init(struct iproc_pcie *pcie)
                break;
        case IPROC_PCIE_PAXB:
                regs = iproc_pcie_reg_paxb;
-               pcie->iproc_cfg_read = true;
                pcie->has_apb_err_disable = true;
                if (pcie->need_ob_cfg) {
                        pcie->ob_map = paxb_ob_map;
@@ -1356,6 +1437,7 @@ static int iproc_pcie_rev_init(struct iproc_pcie *pcie)
                break;
        case IPROC_PCIE_PAXB_V2:
                regs = iproc_pcie_reg_paxb_v2;
+               pcie->iproc_cfg_read = true;
                pcie->has_apb_err_disable = true;
                if (pcie->need_ob_cfg) {
                        pcie->ob_map = paxb_v2_ob_map;
index 0b6c728..80601e1 100644 (file)
@@ -578,6 +578,7 @@ static int mtk_pcie_init_irq_domain(struct mtk_pcie_port *port,
 
        port->irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
                                                 &intx_domain_ops, port);
+       of_node_put(pcie_intc_node);
        if (!port->irq_domain) {
                dev_err(dev, "failed to get INTx IRQ domain\n");
                return -ENODEV;
@@ -915,49 +916,29 @@ static int mtk_pcie_parse_port(struct mtk_pcie *pcie,
 
        /* sys_ck might be divided into the following parts in some chips */
        snprintf(name, sizeof(name), "ahb_ck%d", slot);
-       port->ahb_ck = devm_clk_get(dev, name);
-       if (IS_ERR(port->ahb_ck)) {
-               if (PTR_ERR(port->ahb_ck) == -EPROBE_DEFER)
-                       return -EPROBE_DEFER;
-
-               port->ahb_ck = NULL;
-       }
+       port->ahb_ck = devm_clk_get_optional(dev, name);
+       if (IS_ERR(port->ahb_ck))
+               return PTR_ERR(port->ahb_ck);
 
        snprintf(name, sizeof(name), "axi_ck%d", slot);
-       port->axi_ck = devm_clk_get(dev, name);
-       if (IS_ERR(port->axi_ck)) {
-               if (PTR_ERR(port->axi_ck) == -EPROBE_DEFER)
-                       return -EPROBE_DEFER;
-
-               port->axi_ck = NULL;
-       }
+       port->axi_ck = devm_clk_get_optional(dev, name);
+       if (IS_ERR(port->axi_ck))
+               return PTR_ERR(port->axi_ck);
 
        snprintf(name, sizeof(name), "aux_ck%d", slot);
-       port->aux_ck = devm_clk_get(dev, name);
-       if (IS_ERR(port->aux_ck)) {
-               if (PTR_ERR(port->aux_ck) == -EPROBE_DEFER)
-                       return -EPROBE_DEFER;
-
-               port->aux_ck = NULL;
-       }
+       port->aux_ck = devm_clk_get_optional(dev, name);
+       if (IS_ERR(port->aux_ck))
+               return PTR_ERR(port->aux_ck);
 
        snprintf(name, sizeof(name), "obff_ck%d", slot);
-       port->obff_ck = devm_clk_get(dev, name);
-       if (IS_ERR(port->obff_ck)) {
-               if (PTR_ERR(port->obff_ck) == -EPROBE_DEFER)
-                       return -EPROBE_DEFER;
-
-               port->obff_ck = NULL;
-       }
+       port->obff_ck = devm_clk_get_optional(dev, name);
+       if (IS_ERR(port->obff_ck))
+               return PTR_ERR(port->obff_ck);
 
        snprintf(name, sizeof(name), "pipe_ck%d", slot);
-       port->pipe_ck = devm_clk_get(dev, name);
-       if (IS_ERR(port->pipe_ck)) {
-               if (PTR_ERR(port->pipe_ck) == -EPROBE_DEFER)
-                       return -EPROBE_DEFER;
-
-               port->pipe_ck = NULL;
-       }
+       port->pipe_ck = devm_clk_get_optional(dev, name);
+       if (IS_ERR(port->pipe_ck))
+               return PTR_ERR(port->pipe_ck);
 
        snprintf(name, sizeof(name), "pcie-rst%d", slot);
        port->reset = devm_reset_control_get_optional_exclusive(dev, name);
index c8febb0..f6a669a 100644 (file)
 
 /* Transfer control */
 #define PCIETCTLR              0x02000
-#define  CFINIT                        1
+#define  DL_DOWN               BIT(3)
+#define  CFINIT                        BIT(0)
 #define PCIETSTR               0x02004
-#define  DATA_LINK_ACTIVE      1
+#define  DATA_LINK_ACTIVE      BIT(0)
 #define PCIEERRFR              0x02020
 #define  UNSUPPORTED_REQUEST   BIT(4)
 #define PCIEMSIFR              0x02044
 #define PCIEMSIALR             0x02048
-#define  MSIFE                 1
+#define  MSIFE                 BIT(0)
 #define PCIEMSIAUR             0x0204c
 #define PCIEMSIIER             0x02050
 
@@ -94,6 +95,7 @@
 #define MACCTLR                        0x011058
 #define  SPEED_CHANGE          BIT(24)
 #define  SCRAMBLE_DISABLE      BIT(27)
+#define PMSR                   0x01105c
 #define MACS2R                 0x011078
 #define MACCGSPSETR            0x011084
 #define  SPCNGRSN              BIT(31)
@@ -152,14 +154,13 @@ struct rcar_pcie {
        struct                  rcar_msi msi;
 };
 
-static void rcar_pci_write_reg(struct rcar_pcie *pcie, unsigned long val,
-                              unsigned long reg)
+static void rcar_pci_write_reg(struct rcar_pcie *pcie, u32 val,
+                              unsigned int reg)
 {
        writel(val, pcie->base + reg);
 }
 
-static unsigned long rcar_pci_read_reg(struct rcar_pcie *pcie,
-                                      unsigned long reg)
+static u32 rcar_pci_read_reg(struct rcar_pcie *pcie, unsigned int reg)
 {
        return readl(pcie->base + reg);
 }
@@ -171,7 +172,7 @@ enum {
 
 static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data)
 {
-       int shift = 8 * (where & 3);
+       unsigned int shift = BITS_PER_BYTE * (where & 3);
        u32 val = rcar_pci_read_reg(pcie, where & ~3);
 
        val &= ~(mask << shift);
@@ -181,7 +182,7 @@ static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data)
 
 static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)
 {
-       int shift = 8 * (where & 3);
+       unsigned int shift = BITS_PER_BYTE * (where & 3);
        u32 val = rcar_pci_read_reg(pcie, where & ~3);
 
        return val >> shift;
@@ -192,7 +193,7 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
                unsigned char access_type, struct pci_bus *bus,
                unsigned int devfn, int where, u32 *data)
 {
-       int dev, func, reg, index;
+       unsigned int dev, func, reg, index;
 
        dev = PCI_SLOT(devfn);
        func = PCI_FUNC(devfn);
@@ -281,12 +282,12 @@ static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
        }
 
        if (size == 1)
-               *val = (*val >> (8 * (where & 3))) & 0xff;
+               *val = (*val >> (BITS_PER_BYTE * (where & 3))) & 0xff;
        else if (size == 2)
-               *val = (*val >> (8 * (where & 2))) & 0xffff;
+               *val = (*val >> (BITS_PER_BYTE * (where & 2))) & 0xffff;
 
-       dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08lx\n",
-               bus->number, devfn, where, size, (unsigned long)*val);
+       dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08x\n",
+               bus->number, devfn, where, size, *val);
 
        return ret;
 }
@@ -296,23 +297,24 @@ static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
                                int where, int size, u32 val)
 {
        struct rcar_pcie *pcie = bus->sysdata;
-       int shift, ret;
+       unsigned int shift;
        u32 data;
+       int ret;
 
        ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_READ,
                                      bus, devfn, where, &data);
        if (ret != PCIBIOS_SUCCESSFUL)
                return ret;
 
-       dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08lx\n",
-               bus->number, devfn, where, size, (unsigned long)val);
+       dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08x\n",
+               bus->number, devfn, where, size, val);
 
        if (size == 1) {
-               shift = 8 * (where & 3);
+               shift = BITS_PER_BYTE * (where & 3);
                data &= ~(0xff << shift);
                data |= ((val & 0xff) << shift);
        } else if (size == 2) {
-               shift = 8 * (where & 2);
+               shift = BITS_PER_BYTE * (where & 2);
                data &= ~(0xffff << shift);
                data |= ((val & 0xffff) << shift);
        } else
@@ -507,10 +509,10 @@ static int phy_wait_for_ack(struct rcar_pcie *pcie)
 }
 
 static void phy_write_reg(struct rcar_pcie *pcie,
-                                unsigned int rate, unsigned int addr,
-                                unsigned int lane, unsigned int data)
+                         unsigned int rate, u32 addr,
+                         unsigned int lane, u32 data)
 {
-       unsigned long phyaddr;
+       u32 phyaddr;
 
        phyaddr = WRITE_CMD |
                ((rate & 1) << RATE_POS) |
@@ -738,15 +740,15 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
 
        while (reg) {
                unsigned int index = find_first_bit(&reg, 32);
-               unsigned int irq;
+               unsigned int msi_irq;
 
                /* clear the interrupt */
                rcar_pci_write_reg(pcie, 1 << index, PCIEMSIFR);
 
-               irq = irq_find_mapping(msi->domain, index);
-               if (irq) {
+               msi_irq = irq_find_mapping(msi->domain, index);
+               if (msi_irq) {
                        if (test_bit(index, msi->used))
-                               generic_handle_irq(irq);
+                               generic_handle_irq(msi_irq);
                        else
                                dev_info(dev, "unhandled MSI\n");
                } else {
@@ -890,7 +892,7 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
 {
        struct device *dev = pcie->dev;
        struct rcar_msi *msi = &pcie->msi;
-       unsigned long base;
+       phys_addr_t base;
        int err, i;
 
        mutex_init(&msi->lock);
@@ -929,10 +931,14 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
 
        /* setup MSI data target */
        msi->pages = __get_free_pages(GFP_KERNEL, 0);
+       if (!msi->pages) {
+               err = -ENOMEM;
+               goto err;
+       }
        base = virt_to_phys((void *)msi->pages);
 
-       rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
-       rcar_pci_write_reg(pcie, 0, PCIEMSIAUR);
+       rcar_pci_write_reg(pcie, lower_32_bits(base) | MSIFE, PCIEMSIALR);
+       rcar_pci_write_reg(pcie, upper_32_bits(base), PCIEMSIAUR);
 
        /* enable all MSI interrupts */
        rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
@@ -1118,7 +1124,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct rcar_pcie *pcie;
-       unsigned int data;
+       u32 data;
        int err;
        int (*phy_init_fn)(struct rcar_pcie *);
        struct pci_host_bridge *bridge;
@@ -1130,6 +1136,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
        pcie = pci_host_bridge_priv(bridge);
 
        pcie->dev = dev;
+       platform_set_drvdata(pdev, pcie);
 
        err = pci_parse_request_of_pci_ranges(dev, &pcie->resources, NULL);
        if (err)
@@ -1221,10 +1228,28 @@ err_free_bridge:
        return err;
 }
 
+static int rcar_pcie_resume_noirq(struct device *dev)
+{
+       struct rcar_pcie *pcie = dev_get_drvdata(dev);
+
+       if (rcar_pci_read_reg(pcie, PMSR) &&
+           !(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN))
+               return 0;
+
+       /* Re-establish the PCIe link */
+       rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
+       return rcar_pcie_wait_for_dl(pcie);
+}
+
+static const struct dev_pm_ops rcar_pcie_pm_ops = {
+       .resume_noirq = rcar_pcie_resume_noirq,
+};
+
 static struct platform_driver rcar_pcie_driver = {
        .driver = {
                .name = "rcar-pcie",
                .of_match_table = rcar_pcie_of_match,
+               .pm = &rcar_pcie_pm_ops,
                .suppress_bind_attrs = true,
        },
        .probe = rcar_pcie_probe,
index a5d799e..d743b0a 100644 (file)
@@ -350,7 +350,7 @@ static void rockchip_pcie_ep_assert_intx(struct rockchip_pcie_ep *ep, u8 fn,
        struct rockchip_pcie *rockchip = &ep->rockchip;
        u32 r = ep->max_regions - 1;
        u32 offset;
-       u16 status;
+       u32 status;
        u8 msg_code;
 
        if (unlikely(ep->irq_pci_addr != ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR ||
index 1372d27..8d20f17 100644 (file)
@@ -724,6 +724,7 @@ static int rockchip_pcie_init_irq_domain(struct rockchip_pcie *rockchip)
 
        rockchip->irq_domain = irq_domain_add_linear(intc, PCI_NUM_INTX,
                                                    &intx_domain_ops, rockchip);
+       of_node_put(intc);
        if (!rockchip->irq_domain) {
                dev_err(dev, "failed to get a INTx IRQ domain\n");
                return -EINVAL;
index 81538d7..3b031f0 100644 (file)
@@ -438,11 +438,10 @@ static const struct irq_domain_ops legacy_domain_ops = {
 #ifdef CONFIG_PCI_MSI
 static struct irq_chip nwl_msi_irq_chip = {
        .name = "nwl_pcie:msi",
-       .irq_enable = unmask_msi_irq,
-       .irq_disable = mask_msi_irq,
-       .irq_mask = mask_msi_irq,
-       .irq_unmask = unmask_msi_irq,
-
+       .irq_enable = pci_msi_unmask_irq,
+       .irq_disable = pci_msi_mask_irq,
+       .irq_mask = pci_msi_mask_irq,
+       .irq_unmask = pci_msi_unmask_irq,
 };
 
 static struct msi_domain_info nwl_msi_domain_info = {
index 9bd1a35..5bf3af3 100644 (file)
@@ -336,14 +336,19 @@ static const struct irq_domain_ops msi_domain_ops = {
  * xilinx_pcie_enable_msi - Enable MSI support
  * @port: PCIe port information
  */
-static void xilinx_pcie_enable_msi(struct xilinx_pcie_port *port)
+static int xilinx_pcie_enable_msi(struct xilinx_pcie_port *port)
 {
        phys_addr_t msg_addr;
 
        port->msi_pages = __get_free_pages(GFP_KERNEL, 0);
+       if (!port->msi_pages)
+               return -ENOMEM;
+
        msg_addr = virt_to_phys((void *)port->msi_pages);
        pcie_write(port, 0x0, XILINX_PCIE_REG_MSIBASE1);
        pcie_write(port, msg_addr, XILINX_PCIE_REG_MSIBASE2);
+
+       return 0;
 }
 
 /* INTx Functions */
@@ -498,6 +503,7 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port)
        struct device *dev = port->dev;
        struct device_node *node = dev->of_node;
        struct device_node *pcie_intc_node;
+       int ret;
 
        /* Setup INTx */
        pcie_intc_node = of_get_next_child(node, NULL);
@@ -526,7 +532,9 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port)
                        return -ENODEV;
                }
 
-               xilinx_pcie_enable_msi(port);
+               ret = xilinx_pcie_enable_msi(port);
+               if (ret)
+                       return ret;
        }
 
        return 0;
index d0b91da..2780698 100644 (file)
@@ -438,7 +438,7 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
        epc_features = epf_test->epc_features;
 
        base = pci_epf_alloc_space(epf, sizeof(struct pci_epf_test_reg),
-                                  test_reg_bar);
+                                  test_reg_bar, epc_features->align);
        if (!base) {
                dev_err(dev, "Failed to allocated register space\n");
                return -ENOMEM;
@@ -453,7 +453,8 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
                if (!!(epc_features->reserved_bar & (1 << bar)))
                        continue;
 
-               base = pci_epf_alloc_space(epf, bar_size[bar], bar);
+               base = pci_epf_alloc_space(epf, bar_size[bar], bar,
+                                          epc_features->align);
                if (!base)
                        dev_err(dev, "Failed to allocate space for BAR%d\n",
                                bar);
@@ -591,6 +592,11 @@ static int __init pci_epf_test_init(void)
 
        kpcitest_workqueue = alloc_workqueue("kpcitest",
                                             WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
+       if (!kpcitest_workqueue) {
+               pr_err("Failed to allocate the kpcitest work queue\n");
+               return -ENOMEM;
+       }
+
        ret = pci_epf_register_driver(&test_driver);
        if (ret) {
                pr_err("Failed to register pci epf test driver --> %d\n", ret);
index 8bfdcd2..fb1306d 100644 (file)
@@ -109,10 +109,12 @@ EXPORT_SYMBOL_GPL(pci_epf_free_space);
  * pci_epf_alloc_space() - allocate memory for the PCI EPF register space
  * @size: the size of the memory that has to be allocated
  * @bar: the BAR number corresponding to the allocated register space
+ * @align: alignment size for the allocation region
  *
  * Invoke to allocate memory for the PCI EPF register space.
  */
-void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar)
+void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
+                         size_t align)
 {
        void *space;
        struct device *dev = epf->epc->dev.parent;
@@ -120,7 +122,11 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar)
 
        if (size < 128)
                size = 128;
-       size = roundup_pow_of_two(size);
+
+       if (align)
+               size = ALIGN(size, align);
+       else
+               size = roundup_pow_of_two(size);
 
        space = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
        if (!space) {
index 506e1d9..8c51a04 100644 (file)
 
 #include "../pcie/portdrv.h"
 
-#define MY_NAME        "pciehp"
-
 extern bool pciehp_poll_mode;
 extern int pciehp_poll_time;
-extern bool pciehp_debug;
-
-#define dbg(format, arg...)                                            \
-do {                                                                   \
-       if (pciehp_debug)                                               \
-               printk(KERN_DEBUG "%s: " format, MY_NAME, ## arg);      \
-} while (0)
-#define err(format, arg...)                                            \
-       printk(KERN_ERR "%s: " format, MY_NAME, ## arg)
-#define info(format, arg...)                                           \
-       printk(KERN_INFO "%s: " format, MY_NAME, ## arg)
-#define warn(format, arg...)                                           \
-       printk(KERN_WARNING "%s: " format, MY_NAME, ## arg)
 
+/*
+ * Set CONFIG_DYNAMIC_DEBUG=y and boot with 'dyndbg="file pciehp* +p"' to
+ * enable debug messages.
+ */
 #define ctrl_dbg(ctrl, format, arg...)                                 \
-       do {                                                            \
-               if (pciehp_debug)                                       \
-                       dev_printk(KERN_DEBUG, &ctrl->pcie->device,     \
-                                       format, ## arg);                \
-       } while (0)
+       pci_dbg(ctrl->pcie->port, format, ## arg)
 #define ctrl_err(ctrl, format, arg...)                                 \
-       dev_err(&ctrl->pcie->device, format, ## arg)
+       pci_err(ctrl->pcie->port, format, ## arg)
 #define ctrl_info(ctrl, format, arg...)                                        \
-       dev_info(&ctrl->pcie->device, format, ## arg)
+       pci_info(ctrl->pcie->port, format, ## arg)
 #define ctrl_warn(ctrl, format, arg...)                                        \
-       dev_warn(&ctrl->pcie->device, format, ## arg)
+       pci_warn(ctrl->pcie->port, format, ## arg)
 
 #define SLOT_NAME_SIZE 10
 
index fc5366b..6ad0d86 100644 (file)
@@ -17,6 +17,9 @@
  *   Dely Sy <dely.l.sy@intel.com>"
  */
 
+#define pr_fmt(fmt) "pciehp: " fmt
+#define dev_fmt pr_fmt
+
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -27,7 +30,6 @@
 #include "../pci.h"
 
 /* Global variables */
-bool pciehp_debug;
 bool pciehp_poll_mode;
 int pciehp_poll_time;
 
@@ -35,15 +37,11 @@ int pciehp_poll_time;
  * not really modular, but the easiest way to keep compat with existing
  * bootargs behaviour is to continue using module_param here.
  */
-module_param(pciehp_debug, bool, 0644);
 module_param(pciehp_poll_mode, bool, 0644);
 module_param(pciehp_poll_time, int, 0644);
-MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
 MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
 MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
 
-#define PCIE_MODULE_NAME "pciehp"
-
 static int set_attention_status(struct hotplug_slot *slot, u8 value);
 static int get_power_status(struct hotplug_slot *slot, u8 *value);
 static int get_latch_status(struct hotplug_slot *slot, u8 *value);
@@ -182,14 +180,14 @@ static int pciehp_probe(struct pcie_device *dev)
 
        if (!dev->port->subordinate) {
                /* Can happen if we run out of bus numbers during probe */
-               dev_err(&dev->device,
+               pci_err(dev->port,
                        "Hotplug bridge without secondary bus, ignoring\n");
                return -ENODEV;
        }
 
        ctrl = pcie_init(dev);
        if (!ctrl) {
-               dev_err(&dev->device, "Controller initialization failed\n");
+               pci_err(dev->port, "Controller initialization failed\n");
                return -ENODEV;
        }
        set_service_data(dev, ctrl);
@@ -307,7 +305,7 @@ static int pciehp_runtime_resume(struct pcie_device *dev)
 #endif /* PM */
 
 static struct pcie_port_service_driver hpdriver_portdrv = {
-       .name           = PCIE_MODULE_NAME,
+       .name           = "pciehp",
        .port_type      = PCIE_ANY_PORT,
        .service        = PCIE_PORT_SERVICE_HP,
 
@@ -328,9 +326,9 @@ int __init pcie_hp_init(void)
        int retval = 0;
 
        retval = pcie_port_service_register(&hpdriver_portdrv);
-       dbg("pcie_port_service_register = %d\n", retval);
+       pr_debug("pcie_port_service_register = %d\n", retval);
        if (retval)
-               dbg("Failure to register service\n");
+               pr_debug("Failure to register service\n");
 
        return retval;
 }
index 905282a..631ced0 100644 (file)
@@ -13,6 +13,8 @@
  *
  */
 
+#define dev_fmt(fmt) "pciehp: " fmt
+
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pm_runtime.h>
index 6a2365c..bd990e3 100644 (file)
@@ -12,6 +12,8 @@
  * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com>
  */
 
+#define dev_fmt(fmt) "pciehp: " fmt
+
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/jiffies.h>
@@ -46,7 +48,7 @@ static inline int pciehp_request_irq(struct controller *ctrl)
 
        /* Installs the interrupt handler */
        retval = request_threaded_irq(irq, pciehp_isr, pciehp_ist,
-                                     IRQF_SHARED, MY_NAME, ctrl);
+                                     IRQF_SHARED, "pciehp", ctrl);
        if (retval)
                ctrl_err(ctrl, "Cannot get irq %d for the hotplug controller\n",
                         irq);
@@ -232,8 +234,8 @@ static bool pci_bus_check_dev(struct pci_bus *bus, int devfn)
                delay -= step;
        } while (delay > 0);
 
-       if (count > 1 && pciehp_debug)
-               printk(KERN_DEBUG "pci %04x:%02x:%02x.%d id reading try %d times with interval %d ms to get %08x\n",
+       if (count > 1)
+               pr_debug("pci %04x:%02x:%02x.%d id reading try %d times with interval %d ms to get %08x\n",
                        pci_domain_nr(bus), bus->number, PCI_SLOT(devfn),
                        PCI_FUNC(devfn), count, step, l);
 
@@ -822,14 +824,11 @@ static inline void dbg_ctrl(struct controller *ctrl)
        struct pci_dev *pdev = ctrl->pcie->port;
        u16 reg16;
 
-       if (!pciehp_debug)
-               return;
-
-       ctrl_info(ctrl, "Slot Capabilities      : 0x%08x\n", ctrl->slot_cap);
+       ctrl_dbg(ctrl, "Slot Capabilities      : 0x%08x\n", ctrl->slot_cap);
        pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &reg16);
-       ctrl_info(ctrl, "Slot Status            : 0x%04x\n", reg16);
+       ctrl_dbg(ctrl, "Slot Status            : 0x%04x\n", reg16);
        pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &reg16);
-       ctrl_info(ctrl, "Slot Control           : 0x%04x\n", reg16);
+       ctrl_dbg(ctrl, "Slot Control           : 0x%04x\n", reg16);
 }
 
 #define FLAG(x, y)     (((x) & (y)) ? '+' : '-')
index b9c1396..d17f3bf 100644 (file)
@@ -13,6 +13,8 @@
  *
  */
 
+#define dev_fmt(fmt) "pciehp: " fmt
+
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
index e2356a9..182f9e3 100644 (file)
@@ -51,6 +51,7 @@ static struct device_node *find_vio_slot_node(char *drc_name)
                if (rc == 0)
                        break;
        }
+       of_node_put(parent);
 
        return dn;
 }
@@ -71,6 +72,7 @@ static struct device_node *find_php_slot_pci_node(char *drc_name,
        return np;
 }
 
+/* Returns a device_node with its reference count incremented */
 static struct device_node *find_dlpar_node(char *drc_name, int *node_type)
 {
        struct device_node *dn;
@@ -306,6 +308,7 @@ int dlpar_add_slot(char *drc_name)
                        rc = dlpar_add_phb(drc_name, dn);
                        break;
        }
+       of_node_put(dn);
 
        printk(KERN_INFO "%s: slot %s added\n", DLPAR_MODULE_NAME, drc_name);
 exit:
@@ -439,6 +442,7 @@ int dlpar_remove_slot(char *drc_name)
                        rc = dlpar_remove_pci_slot(drc_name, dn);
                        break;
        }
+       of_node_put(dn);
        vm_unmap_aliases();
 
        printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name);
index 5282aa3..93b4a94 100644 (file)
@@ -21,6 +21,7 @@
 /* free up the memory used by a slot */
 void dealloc_slot_struct(struct slot *slot)
 {
+       of_node_put(slot->dn);
        kfree(slot->name);
        kfree(slot);
 }
@@ -36,7 +37,7 @@ struct slot *alloc_slot_struct(struct device_node *dn,
        slot->name = kstrdup(drc_name, GFP_KERNEL);
        if (!slot->name)
                goto error_slot;
-       slot->dn = dn;
+       slot->dn = of_node_get(dn);
        slot->index = drc_index;
        slot->power_domain = power_domain;
        slot->hotplug_slot.ops = &rpaphp_hotplug_slot_ops;
index 7398682..e039b74 100644 (file)
@@ -1338,7 +1338,7 @@ irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev,
                                          struct msi_desc *desc)
 {
        return (irq_hw_number_t)desc->msi_attrib.entry_nr |
-               PCI_DEVID(dev->bus->number, dev->devfn) << 11 |
+               pci_dev_id(dev) << 11 |
                (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27;
 }
 
@@ -1508,7 +1508,7 @@ static int get_msi_id_cb(struct pci_dev *pdev, u16 alias, void *data)
 u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev)
 {
        struct device_node *of_node;
-       u32 rid = PCI_DEVID(pdev->bus->number, pdev->devfn);
+       u32 rid = pci_dev_id(pdev);
 
        pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
 
@@ -1531,7 +1531,7 @@ u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev)
 struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev)
 {
        struct irq_domain *dom;
-       u32 rid = PCI_DEVID(pdev->bus->number, pdev->devfn);
+       u32 rid = pci_dev_id(pdev);
 
        pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
        dom = of_msi_map_get_device_domain(&pdev->dev, rid);
index 3d32da1..73d5ade 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of_pci.h>
 #include "pci.h"
 
+#ifdef CONFIG_PCI
 void pci_set_of_node(struct pci_dev *dev)
 {
        if (!dev->bus->dev.of_node)
@@ -31,10 +32,16 @@ void pci_release_of_node(struct pci_dev *dev)
 
 void pci_set_bus_of_node(struct pci_bus *bus)
 {
-       if (bus->self == NULL)
-               bus->dev.of_node = pcibios_get_phb_of_node(bus);
-       else
-               bus->dev.of_node = of_node_get(bus->self->dev.of_node);
+       struct device_node *node;
+
+       if (bus->self == NULL) {
+               node = pcibios_get_phb_of_node(bus);
+       } else {
+               node = of_node_get(bus->self->dev.of_node);
+               if (node && of_property_read_bool(node, "external-facing"))
+                       bus->self->untrusted = true;
+       }
+       bus->dev.of_node = node;
 }
 
 void pci_release_bus_of_node(struct pci_bus *bus)
@@ -196,27 +203,6 @@ int of_get_pci_domain_nr(struct device_node *node)
 }
 EXPORT_SYMBOL_GPL(of_get_pci_domain_nr);
 
-/**
- * This function will try to find the limitation of link speed by finding
- * a property called "max-link-speed" of the given device node.
- *
- * @node: device tree node with the max link speed information
- *
- * Returns the associated max link speed from DT, or a negative value if the
- * required property is not found or is invalid.
- */
-int of_pci_get_max_link_speed(struct device_node *node)
-{
-       u32 max_link_speed;
-
-       if (of_property_read_u32(node, "max-link-speed", &max_link_speed) ||
-           max_link_speed > 4)
-               return -EINVAL;
-
-       return max_link_speed;
-}
-EXPORT_SYMBOL_GPL(of_pci_get_max_link_speed);
-
 /**
  * of_pci_check_probe_only - Setup probe only mode if linux,pci-probe-only
  *                           is present and valid
@@ -537,3 +523,25 @@ int pci_parse_request_of_pci_ranges(struct device *dev,
        return err;
 }
 
+#endif /* CONFIG_PCI */
+
+/**
+ * This function will try to find the limitation of link speed by finding
+ * a property called "max-link-speed" of the given device node.
+ *
+ * @node: device tree node with the max link speed information
+ *
+ * Returns the associated max link speed from DT, or a negative value if the
+ * required property is not found or is invalid.
+ */
+int of_pci_get_max_link_speed(struct device_node *node)
+{
+       u32 max_link_speed;
+
+       if (of_property_read_u32(node, "max-link-speed", &max_link_speed) ||
+           max_link_speed > 4)
+               return -EINVAL;
+
+       return max_link_speed;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_max_link_speed);
index c52298d..742928d 100644 (file)
@@ -274,6 +274,30 @@ static void seq_buf_print_bus_devfn(struct seq_buf *buf, struct pci_dev *pdev)
        seq_buf_printf(buf, "%s;", pci_name(pdev));
 }
 
+/*
+ * If we can't find a common upstream bridge take a look at the root
+ * complex and compare it to a whitelist of known good hardware.
+ */
+static bool root_complex_whitelist(struct pci_dev *dev)
+{
+       struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
+       struct pci_dev *root = pci_get_slot(host->bus, PCI_DEVFN(0, 0));
+       unsigned short vendor, device;
+
+       if (!root)
+               return false;
+
+       vendor = root->vendor;
+       device = root->device;
+       pci_dev_put(root);
+
+       /* AMD ZEN host bridges can do peer to peer */
+       if (vendor == PCI_VENDOR_ID_AMD && device == 0x1450)
+               return true;
+
+       return false;
+}
+
 /*
  * Find the distance through the nearest common upstream bridge between
  * two PCI devices.
@@ -317,13 +341,13 @@ static void seq_buf_print_bus_devfn(struct seq_buf *buf, struct pci_dev *pdev)
  * In this case, a list of all infringing bridge addresses will be
  * populated in acs_list (assuming it's non-null) for printk purposes.
  */
-static int upstream_bridge_distance(struct pci_dev *a,
-                                   struct pci_dev *b,
+static int upstream_bridge_distance(struct pci_dev *provider,
+                                   struct pci_dev *client,
                                    struct seq_buf *acs_list)
 {
+       struct pci_dev *a = provider, *b = client, *bb;
        int dist_a = 0;
        int dist_b = 0;
-       struct pci_dev *bb = NULL;
        int acs_cnt = 0;
 
        /*
@@ -354,6 +378,14 @@ static int upstream_bridge_distance(struct pci_dev *a,
                dist_a++;
        }
 
+       /*
+        * Allow the connection if both devices are on a whitelisted root
+        * complex, but add an arbitary large value to the distance.
+        */
+       if (root_complex_whitelist(provider) &&
+           root_complex_whitelist(client))
+               return 0x1000 + dist_a + dist_b;
+
        return -1;
 
 check_b_path_acs:
index e1949f7..c5e1a09 100644 (file)
@@ -119,7 +119,7 @@ phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
 }
 
 static acpi_status decode_type0_hpx_record(union acpi_object *record,
-                                          struct hotplug_params *hpx)
+                                          struct hpp_type0 *hpx0)
 {
        int i;
        union acpi_object *fields = record->package.elements;
@@ -132,16 +132,14 @@ static acpi_status decode_type0_hpx_record(union acpi_object *record,
                for (i = 2; i < 6; i++)
                        if (fields[i].type != ACPI_TYPE_INTEGER)
                                return AE_ERROR;
-               hpx->t0 = &hpx->type0_data;
-               hpx->t0->revision        = revision;
-               hpx->t0->cache_line_size = fields[2].integer.value;
-               hpx->t0->latency_timer   = fields[3].integer.value;
-               hpx->t0->enable_serr     = fields[4].integer.value;
-               hpx->t0->enable_perr     = fields[5].integer.value;
+               hpx0->revision        = revision;
+               hpx0->cache_line_size = fields[2].integer.value;
+               hpx0->latency_timer   = fields[3].integer.value;
+               hpx0->enable_serr     = fields[4].integer.value;
+               hpx0->enable_perr     = fields[5].integer.value;
                break;
        default:
-               printk(KERN_WARNING
-                      "%s: Type 0 Revision %d record not supported\n",
+               pr_warn("%s: Type 0 Revision %d record not supported\n",
                       __func__, revision);
                return AE_ERROR;
        }
@@ -149,7 +147,7 @@ static acpi_status decode_type0_hpx_record(union acpi_object *record,
 }
 
 static acpi_status decode_type1_hpx_record(union acpi_object *record,
-                                          struct hotplug_params *hpx)
+                                          struct hpp_type1 *hpx1)
 {
        int i;
        union acpi_object *fields = record->package.elements;
@@ -162,15 +160,13 @@ static acpi_status decode_type1_hpx_record(union acpi_object *record,
                for (i = 2; i < 5; i++)
                        if (fields[i].type != ACPI_TYPE_INTEGER)
                                return AE_ERROR;
-               hpx->t1 = &hpx->type1_data;
-               hpx->t1->revision      = revision;
-               hpx->t1->max_mem_read  = fields[2].integer.value;
-               hpx->t1->avg_max_split = fields[3].integer.value;
-               hpx->t1->tot_max_split = fields[4].integer.value;
+               hpx1->revision      = revision;
+               hpx1->max_mem_read  = fields[2].integer.value;
+               hpx1->avg_max_split = fields[3].integer.value;
+               hpx1->tot_max_split = fields[4].integer.value;
                break;
        default:
-               printk(KERN_WARNING
-                      "%s: Type 1 Revision %d record not supported\n",
+               pr_warn("%s: Type 1 Revision %d record not supported\n",
                       __func__, revision);
                return AE_ERROR;
        }
@@ -178,7 +174,7 @@ static acpi_status decode_type1_hpx_record(union acpi_object *record,
 }
 
 static acpi_status decode_type2_hpx_record(union acpi_object *record,
-                                          struct hotplug_params *hpx)
+                                          struct hpp_type2 *hpx2)
 {
        int i;
        union acpi_object *fields = record->package.elements;
@@ -191,45 +187,102 @@ static acpi_status decode_type2_hpx_record(union acpi_object *record,
                for (i = 2; i < 18; i++)
                        if (fields[i].type != ACPI_TYPE_INTEGER)
                                return AE_ERROR;
-               hpx->t2 = &hpx->type2_data;
-               hpx->t2->revision      = revision;
-               hpx->t2->unc_err_mask_and      = fields[2].integer.value;
-               hpx->t2->unc_err_mask_or       = fields[3].integer.value;
-               hpx->t2->unc_err_sever_and     = fields[4].integer.value;
-               hpx->t2->unc_err_sever_or      = fields[5].integer.value;
-               hpx->t2->cor_err_mask_and      = fields[6].integer.value;
-               hpx->t2->cor_err_mask_or       = fields[7].integer.value;
-               hpx->t2->adv_err_cap_and       = fields[8].integer.value;
-               hpx->t2->adv_err_cap_or        = fields[9].integer.value;
-               hpx->t2->pci_exp_devctl_and    = fields[10].integer.value;
-               hpx->t2->pci_exp_devctl_or     = fields[11].integer.value;
-               hpx->t2->pci_exp_lnkctl_and    = fields[12].integer.value;
-               hpx->t2->pci_exp_lnkctl_or     = fields[13].integer.value;
-               hpx->t2->sec_unc_err_sever_and = fields[14].integer.value;
-               hpx->t2->sec_unc_err_sever_or  = fields[15].integer.value;
-               hpx->t2->sec_unc_err_mask_and  = fields[16].integer.value;
-               hpx->t2->sec_unc_err_mask_or   = fields[17].integer.value;
+               hpx2->revision      = revision;
+               hpx2->unc_err_mask_and      = fields[2].integer.value;
+               hpx2->unc_err_mask_or       = fields[3].integer.value;
+               hpx2->unc_err_sever_and     = fields[4].integer.value;
+               hpx2->unc_err_sever_or      = fields[5].integer.value;
+               hpx2->cor_err_mask_and      = fields[6].integer.value;
+               hpx2->cor_err_mask_or       = fields[7].integer.value;
+               hpx2->adv_err_cap_and       = fields[8].integer.value;
+               hpx2->adv_err_cap_or        = fields[9].integer.value;
+               hpx2->pci_exp_devctl_and    = fields[10].integer.value;
+               hpx2->pci_exp_devctl_or     = fields[11].integer.value;
+               hpx2->pci_exp_lnkctl_and    = fields[12].integer.value;
+               hpx2->pci_exp_lnkctl_or     = fields[13].integer.value;
+               hpx2->sec_unc_err_sever_and = fields[14].integer.value;
+               hpx2->sec_unc_err_sever_or  = fields[15].integer.value;
+               hpx2->sec_unc_err_mask_and  = fields[16].integer.value;
+               hpx2->sec_unc_err_mask_or   = fields[17].integer.value;
                break;
        default:
-               printk(KERN_WARNING
-                      "%s: Type 2 Revision %d record not supported\n",
+               pr_warn("%s: Type 2 Revision %d record not supported\n",
                       __func__, revision);
                return AE_ERROR;
        }
        return AE_OK;
 }
 
-static acpi_status acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx)
+static void parse_hpx3_register(struct hpx_type3 *hpx3_reg,
+                               union acpi_object *reg_fields)
+{
+       hpx3_reg->device_type            = reg_fields[0].integer.value;
+       hpx3_reg->function_type          = reg_fields[1].integer.value;
+       hpx3_reg->config_space_location  = reg_fields[2].integer.value;
+       hpx3_reg->pci_exp_cap_id         = reg_fields[3].integer.value;
+       hpx3_reg->pci_exp_cap_ver        = reg_fields[4].integer.value;
+       hpx3_reg->pci_exp_vendor_id      = reg_fields[5].integer.value;
+       hpx3_reg->dvsec_id               = reg_fields[6].integer.value;
+       hpx3_reg->dvsec_rev              = reg_fields[7].integer.value;
+       hpx3_reg->match_offset           = reg_fields[8].integer.value;
+       hpx3_reg->match_mask_and         = reg_fields[9].integer.value;
+       hpx3_reg->match_value            = reg_fields[10].integer.value;
+       hpx3_reg->reg_offset             = reg_fields[11].integer.value;
+       hpx3_reg->reg_mask_and           = reg_fields[12].integer.value;
+       hpx3_reg->reg_mask_or            = reg_fields[13].integer.value;
+}
+
+static acpi_status program_type3_hpx_record(struct pci_dev *dev,
+                                          union acpi_object *record,
+                                          const struct hotplug_program_ops *hp_ops)
+{
+       union acpi_object *fields = record->package.elements;
+       u32 desc_count, expected_length, revision;
+       union acpi_object *reg_fields;
+       struct hpx_type3 hpx3;
+       int i;
+
+       revision = fields[1].integer.value;
+       switch (revision) {
+       case 1:
+               desc_count = fields[2].integer.value;
+               expected_length = 3 + desc_count * 14;
+
+               if (record->package.count != expected_length)
+                       return AE_ERROR;
+
+               for (i = 2; i < expected_length; i++)
+                       if (fields[i].type != ACPI_TYPE_INTEGER)
+                               return AE_ERROR;
+
+               for (i = 0; i < desc_count; i++) {
+                       reg_fields = fields + 3 + i * 14;
+                       parse_hpx3_register(&hpx3, reg_fields);
+                       hp_ops->program_type3(dev, &hpx3);
+               }
+
+               break;
+       default:
+               printk(KERN_WARNING
+                       "%s: Type 3 Revision %d record not supported\n",
+                       __func__, revision);
+               return AE_ERROR;
+       }
+       return AE_OK;
+}
+
+static acpi_status acpi_run_hpx(struct pci_dev *dev, acpi_handle handle,
+                               const struct hotplug_program_ops *hp_ops)
 {
        acpi_status status;
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
        union acpi_object *package, *record, *fields;
+       struct hpp_type0 hpx0;
+       struct hpp_type1 hpx1;
+       struct hpp_type2 hpx2;
        u32 type;
        int i;
 
-       /* Clear the return buffer with zeros */
-       memset(hpx, 0, sizeof(struct hotplug_params));
-
        status = acpi_evaluate_object(handle, "_HPX", NULL, &buffer);
        if (ACPI_FAILURE(status))
                return status;
@@ -257,22 +310,33 @@ static acpi_status acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx)
                type = fields[0].integer.value;
                switch (type) {
                case 0:
-                       status = decode_type0_hpx_record(record, hpx);
+                       memset(&hpx0, 0, sizeof(hpx0));
+                       status = decode_type0_hpx_record(record, &hpx0);
                        if (ACPI_FAILURE(status))
                                goto exit;
+                       hp_ops->program_type0(dev, &hpx0);
                        break;
                case 1:
-                       status = decode_type1_hpx_record(record, hpx);
+                       memset(&hpx1, 0, sizeof(hpx1));
+                       status = decode_type1_hpx_record(record, &hpx1);
                        if (ACPI_FAILURE(status))
                                goto exit;
+                       hp_ops->program_type1(dev, &hpx1);
                        break;
                case 2:
-                       status = decode_type2_hpx_record(record, hpx);
+                       memset(&hpx2, 0, sizeof(hpx2));
+                       status = decode_type2_hpx_record(record, &hpx2);
+                       if (ACPI_FAILURE(status))
+                               goto exit;
+                       hp_ops->program_type2(dev, &hpx2);
+                       break;
+               case 3:
+                       status = program_type3_hpx_record(dev, record, hp_ops);
                        if (ACPI_FAILURE(status))
                                goto exit;
                        break;
                default:
-                       printk(KERN_ERR "%s: Type %d record not supported\n",
+                       pr_err("%s: Type %d record not supported\n",
                               __func__, type);
                        status = AE_ERROR;
                        goto exit;
@@ -283,14 +347,16 @@ static acpi_status acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx)
        return status;
 }
 
-static acpi_status acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
+static acpi_status acpi_run_hpp(struct pci_dev *dev, acpi_handle handle,
+                               const struct hotplug_program_ops *hp_ops)
 {
        acpi_status status;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *package, *fields;
+       struct hpp_type0 hpp0;
        int i;
 
-       memset(hpp, 0, sizeof(struct hotplug_params));
+       memset(&hpp0, 0, sizeof(hpp0));
 
        status = acpi_evaluate_object(handle, "_HPP", NULL, &buffer);
        if (ACPI_FAILURE(status))
@@ -311,12 +377,13 @@ static acpi_status acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
                }
        }
 
-       hpp->t0 = &hpp->type0_data;
-       hpp->t0->revision        = 1;
-       hpp->t0->cache_line_size = fields[0].integer.value;
-       hpp->t0->latency_timer   = fields[1].integer.value;
-       hpp->t0->enable_serr     = fields[2].integer.value;
-       hpp->t0->enable_perr     = fields[3].integer.value;
+       hpp0.revision        = 1;
+       hpp0.cache_line_size = fields[0].integer.value;
+       hpp0.latency_timer   = fields[1].integer.value;
+       hpp0.enable_serr     = fields[2].integer.value;
+       hpp0.enable_perr     = fields[3].integer.value;
+
+       hp_ops->program_type0(dev, &hpp0);
 
 exit:
        kfree(buffer.pointer);
@@ -328,7 +395,8 @@ exit:
  * @dev - the pci_dev for which we want parameters
  * @hpp - allocated by the caller
  */
-int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp)
+int pci_acpi_program_hp_params(struct pci_dev *dev,
+                              const struct hotplug_program_ops *hp_ops)
 {
        acpi_status status;
        acpi_handle handle, phandle;
@@ -351,10 +419,10 @@ int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp)
         * this pci dev.
         */
        while (handle) {
-               status = acpi_run_hpx(handle, hpp);
+               status = acpi_run_hpx(dev, handle, hp_ops);
                if (ACPI_SUCCESS(status))
                        return 0;
-               status = acpi_run_hpp(handle, hpp);
+               status = acpi_run_hpp(dev, handle, hp_ops);
                if (ACPI_SUCCESS(status))
                        return 0;
                if (acpi_is_root_bridge(handle))
@@ -366,7 +434,6 @@ int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp)
        }
        return -ENODEV;
 }
-EXPORT_SYMBOL_GPL(pci_get_hp_params);
 
 /**
  * pciehp_is_native - Check whether a hotplug port is handled by the OS
index 66f8a59..e408099 100644 (file)
@@ -66,20 +66,18 @@ static int __init pci_stub_init(void)
                                &class, &class_mask);
 
                if (fields < 2) {
-                       printk(KERN_WARNING
-                              "pci-stub: invalid id string \"%s\"\n", id);
+                       pr_warn("pci-stub: invalid ID string \"%s\"\n", id);
                        continue;
                }
 
-               printk(KERN_INFO
-                      "pci-stub: add %04X:%04X sub=%04X:%04X cls=%08X/%08X\n",
+               pr_info("pci-stub: add %04X:%04X sub=%04X:%04X cls=%08X/%08X\n",
                       vendor, device, subvendor, subdevice, class, class_mask);
 
                rc = pci_add_dynid(&stub_driver, vendor, device,
                                   subvendor, subdevice, class, class_mask, 0);
                if (rc)
-                       printk(KERN_WARNING
-                              "pci-stub: failed to add dynamic id (%d)\n", rc);
+                       pr_warn("pci-stub: failed to add dynamic ID (%d)\n",
+                               rc);
        }
 
        return 0;
index 25794c2..6d27475 100644 (file)
@@ -1111,8 +1111,7 @@ legacy_io_err:
        kfree(b->legacy_io);
        b->legacy_io = NULL;
 kzalloc_err:
-       printk(KERN_WARNING "pci: warning: could not create legacy I/O port and ISA memory resources to sysfs\n");
-       return;
+       dev_warn(&b->dev, "could not create legacy I/O port and ISA memory resources in sysfs\n");
 }
 
 void pci_remove_legacy_files(struct pci_bus *b)
index 766f577..8abc843 100644 (file)
@@ -197,8 +197,8 @@ EXPORT_SYMBOL_GPL(pci_ioremap_wc_bar);
 
 /**
  * pci_dev_str_match_path - test if a path string matches a device
- * @dev:    the PCI device to test
- * @path:   string to match the device against
+ * @dev: the PCI device to test
+ * @path: string to match the device against
  * @endptr: pointer to the string after the match
  *
  * Test if a string (typically from a kernel parameter) formatted as a
@@ -280,8 +280,8 @@ free_and_exit:
 
 /**
  * pci_dev_str_match - test if a string matches a device
- * @dev:    the PCI device to test
- * @p:      string to match the device against
+ * @dev: the PCI device to test
+ * @p: string to match the device against
  * @endptr: pointer to the string after the match
  *
  * Test if a string (typically from a kernel parameter) matches a specified
@@ -341,7 +341,7 @@ static int pci_dev_str_match(struct pci_dev *dev, const char *p,
        } else {
                /*
                 * PCI Bus, Device, Function IDs are specified
-                *  (optionally, may include a path of devfns following it)
+                * (optionally, may include a path of devfns following it)
                 */
                ret = pci_dev_str_match_path(dev, p, &p);
                if (ret < 0)
@@ -425,7 +425,7 @@ static int __pci_bus_find_cap_start(struct pci_bus *bus,
  * Tell if a device supports a given PCI capability.
  * Returns the address of the requested capability structure within the
  * device's PCI configuration space or 0 in case the device does not
- * support it.  Possible values for @cap:
+ * support it.  Possible values for @cap include:
  *
  *  %PCI_CAP_ID_PM           Power Management
  *  %PCI_CAP_ID_AGP          Accelerated Graphics Port
@@ -450,11 +450,11 @@ EXPORT_SYMBOL(pci_find_capability);
 
 /**
  * pci_bus_find_capability - query for devices' capabilities
- * @bus:   the PCI bus to query
+ * @bus: the PCI bus to query
  * @devfn: PCI device to query
- * @cap:   capability code
+ * @cap: capability code
  *
- * Like pci_find_capability() but works for pci devices that do not have a
+ * Like pci_find_capability() but works for PCI devices that do not have a
  * pci_dev structure set up yet.
  *
  * Returns the address of the requested capability structure within the
@@ -535,7 +535,7 @@ EXPORT_SYMBOL_GPL(pci_find_next_ext_capability);
  *
  * Returns the address of the requested extended capability structure
  * within the device's PCI configuration space or 0 if the device does
- * not support it.  Possible values for @cap:
+ * not support it.  Possible values for @cap include:
  *
  *  %PCI_EXT_CAP_ID_ERR                Advanced Error Reporting
  *  %PCI_EXT_CAP_ID_VC         Virtual Channel
@@ -618,12 +618,13 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
 EXPORT_SYMBOL_GPL(pci_find_ht_capability);
 
 /**
- * pci_find_parent_resource - return resource region of parent bus of given region
+ * pci_find_parent_resource - return resource region of parent bus of given
+ *                           region
  * @dev: PCI device structure contains resources to be searched
  * @res: child resource record for which parent is sought
  *
- *  For given resource region of given device, return the resource
- *  region of parent bus the given region is contained in.
+ * For given resource region of given device, return the resource region of
+ * parent bus the given region is contained in.
  */
 struct resource *pci_find_parent_resource(const struct pci_dev *dev,
                                          struct resource *res)
@@ -800,7 +801,7 @@ static inline bool platform_pci_bridge_d3(struct pci_dev *dev)
 
 /**
  * pci_raw_set_power_state - Use PCI PM registers to set the power state of
- *                           given PCI device
+ *                          given PCI device
  * @dev: PCI device to handle.
  * @state: PCI power state (D0, D1, D2, D3hot) to put the device into.
  *
@@ -826,7 +827,8 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
        if (state < PCI_D0 || state > PCI_D3hot)
                return -EINVAL;
 
-       /* Validate current state:
+       /*
+        * Validate current state:
         * Can enter D0 from any state, but if we can only go deeper
         * to sleep if we're already in a low power state
         */
@@ -837,14 +839,15 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
                return -EINVAL;
        }
 
-       /* check if this device supports the desired state */
+       /* Check if this device supports the desired state */
        if ((state == PCI_D1 && !dev->d1_support)
           || (state == PCI_D2 && !dev->d2_support))
                return -EIO;
 
        pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
 
-       /* If we're (effectively) in D3, force entire word to 0.
+       /*
+        * If we're (effectively) in D3, force entire word to 0.
         * This doesn't affect PME_Status, disables PME_En, and
         * sets PowerState to 0.
         */
@@ -867,11 +870,13 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
                break;
        }
 
-       /* enter specified state */
+       /* Enter specified state */
        pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
 
-       /* Mandatory power management transition delays */
-       /* see PCI PM 1.1 5.6.1 table 18 */
+       /*
+        * Mandatory power management transition delays; see PCI PM 1.1
+        * 5.6.1 table 18
+        */
        if (state == PCI_D3hot || dev->current_state == PCI_D3hot)
                pci_dev_d3_sleep(dev);
        else if (state == PCI_D2 || dev->current_state == PCI_D2)
@@ -1085,16 +1090,18 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 {
        int error;
 
-       /* bound the state we're entering */
+       /* Bound the state we're entering */
        if (state > PCI_D3cold)
                state = PCI_D3cold;
        else if (state < PCI_D0)
                state = PCI_D0;
        else if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev))
+
                /*
-                * If the device or the parent bridge do not support PCI PM,
-                * ignore the request if we're doing anything other than putting
-                * it into D0 (which would only happen on boot).
+                * If the device or the parent bridge do not support PCI
+                * PM, ignore the request if we're doing anything other
+                * than putting it into D0 (which would only happen on
+                * boot).
                 */
                return 0;
 
@@ -1104,8 +1111,10 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 
        __pci_start_power_transition(dev, state);
 
-       /* This device is quirked not to be put into D3, so
-          don't put it in D3 */
+       /*
+        * This device is quirked not to be put into D3, so don't put it in
+        * D3
+        */
        if (state >= PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3))
                return 0;
 
@@ -1127,12 +1136,11 @@ EXPORT_SYMBOL(pci_set_power_state);
  * pci_choose_state - Choose the power state of a PCI device
  * @dev: PCI device to be suspended
  * @state: target sleep state for the whole system. This is the value
- *     that is passed to suspend() function.
+ *        that is passed to suspend() function.
  *
  * Returns PCI power state suitable for given device and given system
  * message.
  */
-
 pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
 {
        pci_power_t ret;
@@ -1310,8 +1318,9 @@ static void pci_restore_ltr_state(struct pci_dev *dev)
 }
 
 /**
- * pci_save_state - save the PCI configuration space of a device before suspending
- * @dev: - PCI device that we're dealing with
+ * pci_save_state - save the PCI configuration space of a device before
+ *                 suspending
+ * @dev: PCI device that we're dealing with
  */
 int pci_save_state(struct pci_dev *dev)
 {
@@ -1422,7 +1431,7 @@ static void pci_restore_rebar_state(struct pci_dev *pdev)
 
 /**
  * pci_restore_state - Restore the saved state of a PCI device
- * @dev: PCI device that we're dealing with
+ * @dev: PCI device that we're dealing with
  */
 void pci_restore_state(struct pci_dev *dev)
 {
@@ -1599,8 +1608,8 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
  * pci_reenable_device - Resume abandoned device
  * @dev: PCI device to be resumed
  *
- *  Note this function is a backend of pci_default_resume and is not supposed
- *  to be called by normal code, write proper resume handler and use it instead.
+ * NOTE: This function is a backend of pci_default_resume() and is not supposed
+ * to be called by normal code, write proper resume handler and use it instead.
  */
 int pci_reenable_device(struct pci_dev *dev)
 {
@@ -1675,9 +1684,9 @@ static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
  * pci_enable_device_io - Initialize a device for use with IO space
  * @dev: PCI device to be initialized
  *
- *  Initialize device before it's used by a driver. Ask low-level code
- *  to enable I/O resources. Wake up the device if it was suspended.
- *  Beware, this function can fail.
+ * Initialize device before it's used by a driver. Ask low-level code
+ * to enable I/O resources. Wake up the device if it was suspended.
+ * Beware, this function can fail.
  */
 int pci_enable_device_io(struct pci_dev *dev)
 {
@@ -1689,9 +1698,9 @@ EXPORT_SYMBOL(pci_enable_device_io);
  * pci_enable_device_mem - Initialize a device for use with Memory space
  * @dev: PCI device to be initialized
  *
- *  Initialize device before it's used by a driver. Ask low-level code
- *  to enable Memory resources. Wake up the device if it was suspended.
- *  Beware, this function can fail.
+ * Initialize device before it's used by a driver. Ask low-level code
+ * to enable Memory resources. Wake up the device if it was suspended.
+ * Beware, this function can fail.
  */
 int pci_enable_device_mem(struct pci_dev *dev)
 {
@@ -1703,12 +1712,12 @@ EXPORT_SYMBOL(pci_enable_device_mem);
  * pci_enable_device - Initialize device before it's used by a driver.
  * @dev: PCI device to be initialized
  *
- *  Initialize device before it's used by a driver. Ask low-level code
- *  to enable I/O and memory. Wake up the device if it was suspended.
- *  Beware, this function can fail.
+ * Initialize device before it's used by a driver. Ask low-level code
+ * to enable I/O and memory. Wake up the device if it was suspended.
+ * Beware, this function can fail.
  *
- *  Note we don't actually enable the device many times if we call
- *  this function repeatedly (we just increment the count).
+ * Note we don't actually enable the device many times if we call
+ * this function repeatedly (we just increment the count).
  */
 int pci_enable_device(struct pci_dev *dev)
 {
@@ -1717,8 +1726,8 @@ int pci_enable_device(struct pci_dev *dev)
 EXPORT_SYMBOL(pci_enable_device);
 
 /*
- * Managed PCI resources.  This manages device on/off, intx/msi/msix
- * on/off and BAR regions.  pci_dev itself records msi/msix status, so
+ * Managed PCI resources.  This manages device on/off, INTx/MSI/MSI-X
+ * on/off and BAR regions.  pci_dev itself records MSI/MSI-X status, so
  * there's no need to track it separately.  pci_devres is initialized
  * when a device is enabled using managed PCI device enable interface.
  */
@@ -1836,7 +1845,8 @@ int __weak pcibios_add_device(struct pci_dev *dev)
 }
 
 /**
- * pcibios_release_device - provide arch specific hooks when releasing device dev
+ * pcibios_release_device - provide arch specific hooks when releasing
+ *                         device dev
  * @dev: the PCI device being released
  *
  * Permits the platform to provide architecture specific functionality when
@@ -1927,8 +1937,7 @@ EXPORT_SYMBOL(pci_disable_device);
  * @dev: the PCIe device reset
  * @state: Reset state to enter into
  *
- *
- * Sets the PCIe reset state for the device. This is the default
+ * Set the PCIe reset state for the device. This is the default
  * implementation. Architecture implementations can override this.
  */
 int __weak pcibios_set_pcie_reset_state(struct pci_dev *dev,
@@ -1942,7 +1951,6 @@ int __weak pcibios_set_pcie_reset_state(struct pci_dev *dev,
  * @dev: the PCIe device reset
  * @state: Reset state to enter into
  *
- *
  * Sets the PCI reset state for the device.
  */
 int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
@@ -2339,7 +2347,8 @@ static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup)
 }
 
 /**
- * pci_prepare_to_sleep - prepare PCI device for system-wide transition into a sleep state
+ * pci_prepare_to_sleep - prepare PCI device for system-wide transition
+ *                       into a sleep state
  * @dev: Device to handle.
  *
  * Choose the power state appropriate for the device depending on whether
@@ -2367,7 +2376,8 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
 EXPORT_SYMBOL(pci_prepare_to_sleep);
 
 /**
- * pci_back_from_sleep - turn PCI device on during system-wide transition into working state
+ * pci_back_from_sleep - turn PCI device on during system-wide transition
+ *                      into working state
  * @dev: Device to handle.
  *
  * Disable device's system wake-up capability and put it into D0.
@@ -2777,14 +2787,14 @@ void pci_pm_init(struct pci_dev *dev)
                        dev->d2_support = true;
 
                if (dev->d1_support || dev->d2_support)
-                       pci_printk(KERN_DEBUG, dev, "supports%s%s\n",
+                       pci_info(dev, "supports%s%s\n",
                                   dev->d1_support ? " D1" : "",
                                   dev->d2_support ? " D2" : "");
        }
 
        pmc &= PCI_PM_CAP_PME_MASK;
        if (pmc) {
-               pci_printk(KERN_DEBUG, dev, "PME# supported from%s%s%s%s%s\n",
+               pci_info(dev, "PME# supported from%s%s%s%s%s\n",
                         (pmc & PCI_PM_CAP_PME_D0) ? " D0" : "",
                         (pmc & PCI_PM_CAP_PME_D1) ? " D1" : "",
                         (pmc & PCI_PM_CAP_PME_D2) ? " D2" : "",
@@ -2952,16 +2962,16 @@ static int pci_ea_read(struct pci_dev *dev, int offset)
        res->flags = flags;
 
        if (bei <= PCI_EA_BEI_BAR5)
-               pci_printk(KERN_DEBUG, dev, "BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",
+               pci_info(dev, "BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",
                           bei, res, prop);
        else if (bei == PCI_EA_BEI_ROM)
-               pci_printk(KERN_DEBUG, dev, "ROM: %pR (from Enhanced Allocation, properties %#02x)\n",
+               pci_info(dev, "ROM: %pR (from Enhanced Allocation, properties %#02x)\n",
                           res, prop);
        else if (bei >= PCI_EA_BEI_VF_BAR0 && bei <= PCI_EA_BEI_VF_BAR5)
-               pci_printk(KERN_DEBUG, dev, "VF BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",
+               pci_info(dev, "VF BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",
                           bei - PCI_EA_BEI_VF_BAR0, res, prop);
        else
-               pci_printk(KERN_DEBUG, dev, "BEI %d res: %pR (from Enhanced Allocation, properties %#02x)\n",
+               pci_info(dev, "BEI %d res: %pR (from Enhanced Allocation, properties %#02x)\n",
                           bei, res, prop);
 
 out:
@@ -3005,7 +3015,7 @@ static void pci_add_saved_cap(struct pci_dev *pci_dev,
 
 /**
  * _pci_add_cap_save_buffer - allocate buffer for saving given
- *                            capability registers
+ *                           capability registers
  * @dev: the PCI device
  * @cap: the capability to allocate the buffer for
  * @extended: Standard or Extended capability ID
@@ -3186,7 +3196,7 @@ static void pci_disable_acs_redir(struct pci_dev *dev)
 }
 
 /**
- * pci_std_enable_acs - enable ACS on devices using standard ACS capabilites
+ * pci_std_enable_acs - enable ACS on devices using standard ACS capabilities
  * @dev: the PCI device
  */
 static void pci_std_enable_acs(struct pci_dev *dev)
@@ -3609,13 +3619,14 @@ u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp)
 EXPORT_SYMBOL_GPL(pci_common_swizzle);
 
 /**
- *     pci_release_region - Release a PCI bar
- *     @pdev: PCI device whose resources were previously reserved by pci_request_region
- *     @bar: BAR to release
+ * pci_release_region - Release a PCI bar
+ * @pdev: PCI device whose resources were previously reserved by
+ *       pci_request_region()
+ * @bar: BAR to release
  *
- *     Releases the PCI I/O and memory resources previously reserved by a
- *     successful call to pci_request_region.  Call this function only
- *     after all use of the PCI regions has ceased.
+ * Releases the PCI I/O and memory resources previously reserved by a
+ * successful call to pci_request_region().  Call this function only
+ * after all use of the PCI regions has ceased.
  */
 void pci_release_region(struct pci_dev *pdev, int bar)
 {
@@ -3637,23 +3648,23 @@ void pci_release_region(struct pci_dev *pdev, int bar)
 EXPORT_SYMBOL(pci_release_region);
 
 /**
- *     __pci_request_region - Reserved PCI I/O and memory resource
- *     @pdev: PCI device whose resources are to be reserved
- *     @bar: BAR to be reserved
- *     @res_name: Name to be associated with resource.
- *     @exclusive: whether the region access is exclusive or not
+ * __pci_request_region - Reserved PCI I/O and memory resource
+ * @pdev: PCI device whose resources are to be reserved
+ * @bar: BAR to be reserved
+ * @res_name: Name to be associated with resource.
+ * @exclusive: whether the region access is exclusive or not
  *
- *     Mark the PCI region associated with PCI device @pdev BR @bar as
- *     being reserved by owner @res_name.  Do not access any
- *     address inside the PCI regions unless this call returns
- *     successfully.
+ * Mark the PCI region associated with PCI device @pdev BAR @bar as
+ * being reserved by owner @res_name.  Do not access any
+ * address inside the PCI regions unless this call returns
+ * successfully.
  *
- *     If @exclusive is set, then the region is marked so that userspace
- *     is explicitly not allowed to map the resource via /dev/mem or
- *     sysfs MMIO access.
+ * If @exclusive is set, then the region is marked so that userspace
+ * is explicitly not allowed to map the resource via /dev/mem or
+ * sysfs MMIO access.
  *
- *     Returns 0 on success, or %EBUSY on error.  A warning
- *     message is also printed on failure.
+ * Returns 0 on success, or %EBUSY on error.  A warning
+ * message is also printed on failure.
  */
 static int __pci_request_region(struct pci_dev *pdev, int bar,
                                const char *res_name, int exclusive)
@@ -3687,18 +3698,18 @@ err_out:
 }
 
 /**
- *     pci_request_region - Reserve PCI I/O and memory resource
- *     @pdev: PCI device whose resources are to be reserved
- *     @bar: BAR to be reserved
- *     @res_name: Name to be associated with resource
+ * pci_request_region - Reserve PCI I/O and memory resource
+ * @pdev: PCI device whose resources are to be reserved
+ * @bar: BAR to be reserved
+ * @res_name: Name to be associated with resource
  *
- *     Mark the PCI region associated with PCI device @pdev BAR @bar as
- *     being reserved by owner @res_name.  Do not access any
- *     address inside the PCI regions unless this call returns
- *     successfully.
+ * Mark the PCI region associated with PCI device @pdev BAR @bar as
+ * being reserved by owner @res_name.  Do not access any
+ * address inside the PCI regions unless this call returns
+ * successfully.
  *
- *     Returns 0 on success, or %EBUSY on error.  A warning
- *     message is also printed on failure.
+ * Returns 0 on success, or %EBUSY on error.  A warning
+ * message is also printed on failure.
  */
 int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
 {
@@ -3706,31 +3717,6 @@ int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
 }
 EXPORT_SYMBOL(pci_request_region);
 
-/**
- *     pci_request_region_exclusive - Reserved PCI I/O and memory resource
- *     @pdev: PCI device whose resources are to be reserved
- *     @bar: BAR to be reserved
- *     @res_name: Name to be associated with resource.
- *
- *     Mark the PCI region associated with PCI device @pdev BR @bar as
- *     being reserved by owner @res_name.  Do not access any
- *     address inside the PCI regions unless this call returns
- *     successfully.
- *
- *     Returns 0 on success, or %EBUSY on error.  A warning
- *     message is also printed on failure.
- *
- *     The key difference that _exclusive makes it that userspace is
- *     explicitly not allowed to map the resource via /dev/mem or
- *     sysfs.
- */
-int pci_request_region_exclusive(struct pci_dev *pdev, int bar,
-                                const char *res_name)
-{
-       return __pci_request_region(pdev, bar, res_name, IORESOURCE_EXCLUSIVE);
-}
-EXPORT_SYMBOL(pci_request_region_exclusive);
-
 /**
  * pci_release_selected_regions - Release selected PCI I/O and memory resources
  * @pdev: PCI device whose resources were previously reserved
@@ -3791,12 +3777,13 @@ int pci_request_selected_regions_exclusive(struct pci_dev *pdev, int bars,
 EXPORT_SYMBOL(pci_request_selected_regions_exclusive);
 
 /**
- *     pci_release_regions - Release reserved PCI I/O and memory resources
- *     @pdev: PCI device whose resources were previously reserved by pci_request_regions
+ * pci_release_regions - Release reserved PCI I/O and memory resources
+ * @pdev: PCI device whose resources were previously reserved by
+ *       pci_request_regions()
  *
- *     Releases all PCI I/O and memory resources previously reserved by a
- *     successful call to pci_request_regions.  Call this function only
- *     after all use of the PCI regions has ceased.
+ * Releases all PCI I/O and memory resources previously reserved by a
+ * successful call to pci_request_regions().  Call this function only
+ * after all use of the PCI regions has ceased.
  */
 
 void pci_release_regions(struct pci_dev *pdev)
@@ -3806,17 +3793,17 @@ void pci_release_regions(struct pci_dev *pdev)
 EXPORT_SYMBOL(pci_release_regions);
 
 /**
- *     pci_request_regions - Reserved PCI I/O and memory resources
- *     @pdev: PCI device whose resources are to be reserved
- *     @res_name: Name to be associated with resource.
+ * pci_request_regions - Reserve PCI I/O and memory resources
+ * @pdev: PCI device whose resources are to be reserved
+ * @res_name: Name to be associated with resource.
  *
- *     Mark all PCI regions associated with PCI device @pdev as
- *     being reserved by owner @res_name.  Do not access any
- *     address inside the PCI regions unless this call returns
- *     successfully.
+ * Mark all PCI regions associated with PCI device @pdev as
+ * being reserved by owner @res_name.  Do not access any
+ * address inside the PCI regions unless this call returns
+ * successfully.
  *
- *     Returns 0 on success, or %EBUSY on error.  A warning
- *     message is also printed on failure.
+ * Returns 0 on success, or %EBUSY on error.  A warning
+ * message is also printed on failure.
  */
 int pci_request_regions(struct pci_dev *pdev, const char *res_name)
 {
@@ -3825,20 +3812,19 @@ int pci_request_regions(struct pci_dev *pdev, const char *res_name)
 EXPORT_SYMBOL(pci_request_regions);
 
 /**
- *     pci_request_regions_exclusive - Reserved PCI I/O and memory resources
- *     @pdev: PCI device whose resources are to be reserved
- *     @res_name: Name to be associated with resource.
+ * pci_request_regions_exclusive - Reserve PCI I/O and memory resources
+ * @pdev: PCI device whose resources are to be reserved
+ * @res_name: Name to be associated with resource.
  *
- *     Mark all PCI regions associated with PCI device @pdev as
- *     being reserved by owner @res_name.  Do not access any
- *     address inside the PCI regions unless this call returns
- *     successfully.
+ * Mark all PCI regions associated with PCI device @pdev as being reserved
+ * by owner @res_name.  Do not access any address inside the PCI regions
+ * unless this call returns successfully.
  *
- *     pci_request_regions_exclusive() will mark the region so that
- *     /dev/mem and the sysfs MMIO access will not be allowed.
+ * pci_request_regions_exclusive() will mark the region so that /dev/mem
+ * and the sysfs MMIO access will not be allowed.
  *
- *     Returns 0 on success, or %EBUSY on error.  A warning
- *     message is also printed on failure.
+ * Returns 0 on success, or %EBUSY on error.  A warning message is also
+ * printed on failure.
  */
 int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
 {
@@ -3849,7 +3835,7 @@ EXPORT_SYMBOL(pci_request_regions_exclusive);
 
 /*
  * Record the PCI IO range (expressed as CPU physical address + size).
- * Return a negative value if an error has occured, zero otherwise
+ * Return a negative value if an error has occurred, zero otherwise
  */
 int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
                        resource_size_t size)
@@ -3905,14 +3891,14 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
 }
 
 /**
- *     pci_remap_iospace - Remap the memory mapped I/O space
- *     @res: Resource describing the I/O space
- *     @phys_addr: physical address of range to be mapped
+ * pci_remap_iospace - Remap the memory mapped I/O space
+ * @res: Resource describing the I/O space
+ * @phys_addr: physical address of range to be mapped
  *
- *     Remap the memory mapped I/O space described by the @res
- *     and the CPU physical address @phys_addr into virtual address space.
- *     Only architectures that have memory mapped IO functions defined
- *     (and the PCI_IOBASE value defined) should call this function.
+ * Remap the memory mapped I/O space described by the @res and the CPU
+ * physical address @phys_addr into virtual address space.  Only
+ * architectures that have memory mapped IO functions defined (and the
+ * PCI_IOBASE value defined) should call this function.
  */
 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
 {
@@ -3928,8 +3914,10 @@ int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
        return ioremap_page_range(vaddr, vaddr + resource_size(res), phys_addr,
                                  pgprot_device(PAGE_KERNEL));
 #else
-       /* this architecture does not have memory mapped I/O space,
-          so this function should never be called */
+       /*
+        * This architecture does not have memory mapped I/O space,
+        * so this function should never be called
+        */
        WARN_ONCE(1, "This architecture does not support memory mapped I/O\n");
        return -ENODEV;
 #endif
@@ -3937,12 +3925,12 @@ int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
 EXPORT_SYMBOL(pci_remap_iospace);
 
 /**
- *     pci_unmap_iospace - Unmap the memory mapped I/O space
- *     @res: resource to be unmapped
+ * pci_unmap_iospace - Unmap the memory mapped I/O space
+ * @res: resource to be unmapped
  *
- *     Unmap the CPU virtual address @res from virtual address space.
- *     Only architectures that have memory mapped IO functions defined
- *     (and the PCI_IOBASE value defined) should call this function.
+ * Unmap the CPU virtual address @res from virtual address space.  Only
+ * architectures that have memory mapped IO functions defined (and the
+ * PCI_IOBASE value defined) should call this function.
  */
 void pci_unmap_iospace(struct resource *res)
 {
@@ -4185,7 +4173,7 @@ int pci_set_cacheline_size(struct pci_dev *dev)
        if (cacheline_size == pci_cache_line_size)
                return 0;
 
-       pci_printk(KERN_DEBUG, dev, "cache line size of %d is not supported\n",
+       pci_info(dev, "cache line size of %d is not supported\n",
                   pci_cache_line_size << 2);
 
        return -EINVAL;
@@ -4288,7 +4276,7 @@ EXPORT_SYMBOL(pci_clear_mwi);
  * @pdev: the PCI device to operate on
  * @enable: boolean: whether to enable or disable PCI INTx
  *
- * Enables/disables PCI INTx for device dev
+ * Enables/disables PCI INTx for device @pdev
  */
 void pci_intx(struct pci_dev *pdev, int enable)
 {
@@ -4364,9 +4352,8 @@ done:
  * pci_check_and_mask_intx - mask INTx on pending interrupt
  * @dev: the PCI device to operate on
  *
- * Check if the device dev has its INTx line asserted, mask it and
- * return true in that case. False is returned if no interrupt was
- * pending.
+ * Check if the device dev has its INTx line asserted, mask it and return
+ * true in that case. False is returned if no interrupt was pending.
  */
 bool pci_check_and_mask_intx(struct pci_dev *dev)
 {
@@ -4378,9 +4365,9 @@ EXPORT_SYMBOL_GPL(pci_check_and_mask_intx);
  * pci_check_and_unmask_intx - unmask INTx if no interrupt is pending
  * @dev: the PCI device to operate on
  *
- * Check if the device dev has its INTx line asserted, unmask it if not
- * and return true. False is returned and the mask remains active if
- * there was still an interrupt pending.
+ * Check if the device dev has its INTx line asserted, unmask it if not and
+ * return true. False is returned and the mask remains active if there was
+ * still an interrupt pending.
  */
 bool pci_check_and_unmask_intx(struct pci_dev *dev)
 {
@@ -4389,7 +4376,7 @@ bool pci_check_and_unmask_intx(struct pci_dev *dev)
 EXPORT_SYMBOL_GPL(pci_check_and_unmask_intx);
 
 /**
- * pci_wait_for_pending_transaction - waits for pending transaction
+ * pci_wait_for_pending_transaction - wait for pending transaction
  * @dev: the PCI device to operate on
  *
  * Return 0 if transaction is pending 1 otherwise.
@@ -4447,7 +4434,7 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
 
 /**
  * pcie_has_flr - check if a device supports function level resets
- * @dev:       device to check
+ * @dev: device to check
  *
  * Returns true if the device advertises support for PCIe function level
  * resets.
@@ -4466,7 +4453,7 @@ EXPORT_SYMBOL_GPL(pcie_has_flr);
 
 /**
  * pcie_flr - initiate a PCIe function level reset
- * @dev:       device to reset
+ * @dev: device to reset
  *
  * Initiate a function level reset on @dev.  The caller should ensure the
  * device supports FLR before calling this function, e.g. by using the
@@ -4810,6 +4797,7 @@ static void pci_dev_restore(struct pci_dev *dev)
  *
  * The device function is presumed to be unused and the caller is holding
  * the device mutex lock when this function is called.
+ *
  * Resetting the device will make the contents of PCI configuration space
  * random, so any caller of this must be prepared to reinitialise the
  * device including MSI, bus mastering, BARs, decoding IO and memory spaces,
@@ -5373,8 +5361,8 @@ EXPORT_SYMBOL_GPL(pci_reset_bus);
  * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count
  * @dev: PCI device to query
  *
- * Returns mmrbc: maximum designed memory read count in bytes
- *    or appropriate error value.
+ * Returns mmrbc: maximum designed memory read count in bytes or
+ * appropriate error value.
  */
 int pcix_get_max_mmrbc(struct pci_dev *dev)
 {
@@ -5396,8 +5384,8 @@ EXPORT_SYMBOL(pcix_get_max_mmrbc);
  * pcix_get_mmrbc - get PCI-X maximum memory read byte count
  * @dev: PCI device to query
  *
- * Returns mmrbc: maximum memory read count in bytes
- *    or appropriate error value.
+ * Returns mmrbc: maximum memory read count in bytes or appropriate error
+ * value.
  */
 int pcix_get_mmrbc(struct pci_dev *dev)
 {
@@ -5421,7 +5409,7 @@ EXPORT_SYMBOL(pcix_get_mmrbc);
  * @mmrbc: maximum memory read count in bytes
  *    valid values are 512, 1024, 2048, 4096
  *
- * If possible sets maximum memory read byte count, some bridges have erratas
+ * If possible sets maximum memory read byte count, some bridges have errata
  * that prevent this.
  */
 int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc)
@@ -5466,8 +5454,7 @@ EXPORT_SYMBOL(pcix_set_mmrbc);
  * pcie_get_readrq - get PCI Express read request size
  * @dev: PCI device to query
  *
- * Returns maximum memory read request in bytes
- *    or appropriate error value.
+ * Returns maximum memory read request in bytes or appropriate error value.
  */
 int pcie_get_readrq(struct pci_dev *dev)
 {
@@ -5495,10 +5482,9 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
                return -EINVAL;
 
        /*
-        * If using the "performance" PCIe config, we clamp the
-        * read rq size to the max packet size to prevent the
-        * host bridge generating requests larger than we can
-        * cope with
+        * If using the "performance" PCIe config, we clamp the read rq
+        * size to the max packet size to keep the host bridge from
+        * generating requests larger than we can cope with.
         */
        if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
                int mps = pcie_get_mps(dev);
@@ -6144,6 +6130,7 @@ static int of_pci_bus_find_domain_nr(struct device *parent)
 
        if (parent)
                domain = of_get_pci_domain_nr(parent->of_node);
+
        /*
         * Check DT domain and use_dt_domains values.
         *
@@ -6264,8 +6251,7 @@ static int __init pci_setup(char *str)
                        } else if (!strncmp(str, "disable_acs_redir=", 18)) {
                                disable_acs_redir_param = str + 18;
                        } else {
-                               printk(KERN_ERR "PCI: Unknown option `%s'\n",
-                                               str);
+                               pr_err("PCI: Unknown option `%s'\n", str);
                        }
                }
                str = k;
index d994839..9cb9938 100644 (file)
@@ -597,7 +597,7 @@ void pci_aer_clear_fatal_status(struct pci_dev *dev);
 void pci_aer_clear_device_status(struct pci_dev *dev);
 #else
 static inline void pci_no_aer(void) { }
-static inline int pci_aer_init(struct pci_dev *d) { return -ENODEV; }
+static inline void pci_aer_init(struct pci_dev *d) { }
 static inline void pci_aer_exit(struct pci_dev *d) { }
 static inline void pci_aer_clear_fatal_status(struct pci_dev *dev) { }
 static inline void pci_aer_clear_device_status(struct pci_dev *dev) { }
index f8fc211..b45bc47 100644 (file)
@@ -12,6 +12,9 @@
  *    Andrew Patterson <andrew.patterson@hp.com>
  */
 
+#define pr_fmt(fmt) "AER: " fmt
+#define dev_fmt pr_fmt
+
 #include <linux/cper.h>
 #include <linux/pci.h>
 #include <linux/pci-acpi.h>
@@ -779,10 +782,11 @@ static void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
        u8 bus = info->id >> 8;
        u8 devfn = info->id & 0xff;
 
-       pci_info(dev, "AER: %s%s error received: %04x:%02x:%02x.%d\n",
-               info->multi_error_valid ? "Multiple " : "",
-               aer_error_severity_string[info->severity],
-               pci_domain_nr(dev->bus), bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+       pci_info(dev, "%s%s error received: %04x:%02x:%02x.%d\n",
+                info->multi_error_valid ? "Multiple " : "",
+                aer_error_severity_string[info->severity],
+                pci_domain_nr(dev->bus), bus, PCI_SLOT(devfn),
+                PCI_FUNC(devfn));
 }
 
 #ifdef CONFIG_ACPI_APEI_PCIEAER
@@ -964,8 +968,7 @@ static bool find_source_device(struct pci_dev *parent,
        pci_walk_bus(parent->subordinate, find_device_iter, e_info);
 
        if (!e_info->error_dev_num) {
-               pci_printk(KERN_DEBUG, parent, "can't find device of ID%04x\n",
-                          e_info->id);
+               pci_info(parent, "can't find device of ID%04x\n", e_info->id);
                return false;
        }
        return true;
@@ -1377,25 +1380,24 @@ static int aer_probe(struct pcie_device *dev)
        int status;
        struct aer_rpc *rpc;
        struct device *device = &dev->device;
+       struct pci_dev *port = dev->port;
 
        rpc = devm_kzalloc(device, sizeof(struct aer_rpc), GFP_KERNEL);
-       if (!rpc) {
-               dev_printk(KERN_DEBUG, device, "alloc AER rpc failed\n");
+       if (!rpc)
                return -ENOMEM;
-       }
-       rpc->rpd = dev->port;
+
+       rpc->rpd = port;
        set_service_data(dev, rpc);
 
        status = devm_request_threaded_irq(device, dev->irq, aer_irq, aer_isr,
                                           IRQF_SHARED, "aerdrv", dev);
        if (status) {
-               dev_printk(KERN_DEBUG, device, "request AER IRQ %d failed\n",
-                          dev->irq);
+               pci_err(port, "request AER IRQ %d failed\n", dev->irq);
                return status;
        }
 
        aer_enable_rootport(rpc);
-       dev_info(device, "AER enabled with IRQ %d\n", dev->irq);
+       pci_info(port, "enabled with IRQ %d\n", dev->irq);
        return 0;
 }
 
@@ -1419,7 +1421,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
        pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
 
        rc = pci_bus_error_reset(dev);
-       pci_printk(KERN_DEBUG, dev, "Root Port link has been reset\n");
+       pci_info(dev, "Root Port link has been reset\n");
 
        /* Clear Root Error Status */
        pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &reg32);
index 95d4759..043b8b0 100644 (file)
@@ -12,6 +12,8 @@
  *     Huang Ying <ying.huang@intel.com>
  */
 
+#define dev_fmt(fmt) "aer_inject: " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/irq.h>
@@ -332,14 +334,14 @@ static int aer_inject(struct aer_error_inj *einj)
                return -ENODEV;
        rpdev = pcie_find_root_port(dev);
        if (!rpdev) {
-               pci_err(dev, "aer_inject: Root port not found\n");
+               pci_err(dev, "Root port not found\n");
                ret = -ENODEV;
                goto out_put;
        }
 
        pos_cap_err = dev->aer_cap;
        if (!pos_cap_err) {
-               pci_err(dev, "aer_inject: Device doesn't support AER\n");
+               pci_err(dev, "Device doesn't support AER\n");
                ret = -EPROTONOSUPPORT;
                goto out_put;
        }
@@ -350,7 +352,7 @@ static int aer_inject(struct aer_error_inj *einj)
 
        rp_pos_cap_err = rpdev->aer_cap;
        if (!rp_pos_cap_err) {
-               pci_err(rpdev, "aer_inject: Root port doesn't support AER\n");
+               pci_err(rpdev, "Root port doesn't support AER\n");
                ret = -EPROTONOSUPPORT;
                goto out_put;
        }
@@ -398,14 +400,14 @@ static int aer_inject(struct aer_error_inj *einj)
        if (!aer_mask_override && einj->cor_status &&
            !(einj->cor_status & ~cor_mask)) {
                ret = -EINVAL;
-               pci_warn(dev, "aer_inject: The correctable error(s) is masked by device\n");
+               pci_warn(dev, "The correctable error(s) is masked by device\n");
                spin_unlock_irqrestore(&inject_lock, flags);
                goto out_put;
        }
        if (!aer_mask_override && einj->uncor_status &&
            !(einj->uncor_status & ~uncor_mask)) {
                ret = -EINVAL;
-               pci_warn(dev, "aer_inject: The uncorrectable error(s) is masked by device\n");
+               pci_warn(dev, "The uncorrectable error(s) is masked by device\n");
                spin_unlock_irqrestore(&inject_lock, flags);
                goto out_put;
        }
@@ -460,19 +462,17 @@ static int aer_inject(struct aer_error_inj *einj)
        if (device) {
                edev = to_pcie_device(device);
                if (!get_service_data(edev)) {
-                       dev_warn(&edev->device,
-                                "aer_inject: AER service is not initialized\n");
+                       pci_warn(edev->port, "AER service is not initialized\n");
                        ret = -EPROTONOSUPPORT;
                        goto out_put;
                }
-               dev_info(&edev->device,
-                        "aer_inject: Injecting errors %08x/%08x into device %s\n",
+               pci_info(edev->port, "Injecting errors %08x/%08x into device %s\n",
                         einj->cor_status, einj->uncor_status, pci_name(dev));
                local_irq_disable();
                generic_handle_irq(edev->irq);
                local_irq_enable();
        } else {
-               pci_err(rpdev, "aer_inject: AER device not found\n");
+               pci_err(rpdev, "AER device not found\n");
                ret = -ENODEV;
        }
 out_put:
index 727e3c1..fd4cb75 100644 (file)
@@ -196,6 +196,36 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
        link->clkpm_capable = (blacklist) ? 0 : capable;
 }
 
+static bool pcie_retrain_link(struct pcie_link_state *link)
+{
+       struct pci_dev *parent = link->pdev;
+       unsigned long end_jiffies;
+       u16 reg16;
+
+       pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &reg16);
+       reg16 |= PCI_EXP_LNKCTL_RL;
+       pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
+       if (parent->clear_retrain_link) {
+               /*
+                * Due to an erratum in some devices the Retrain Link bit
+                * needs to be cleared again manually to allow the link
+                * training to succeed.
+                */
+               reg16 &= ~PCI_EXP_LNKCTL_RL;
+               pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
+       }
+
+       /* Wait for link training end. Break out after waiting for timeout */
+       end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT;
+       do {
+               pcie_capability_read_word(parent, PCI_EXP_LNKSTA, &reg16);
+               if (!(reg16 & PCI_EXP_LNKSTA_LT))
+                       break;
+               msleep(1);
+       } while (time_before(jiffies, end_jiffies));
+       return !(reg16 & PCI_EXP_LNKSTA_LT);
+}
+
 /*
  * pcie_aspm_configure_common_clock: check if the 2 ends of a link
  *   could use common clock. If they are, configure them to use the
@@ -205,7 +235,6 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
 {
        int same_clock = 1;
        u16 reg16, parent_reg, child_reg[8];
-       unsigned long start_jiffies;
        struct pci_dev *child, *parent = link->pdev;
        struct pci_bus *linkbus = parent->subordinate;
        /*
@@ -263,21 +292,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
                reg16 &= ~PCI_EXP_LNKCTL_CCC;
        pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
 
-       /* Retrain link */
-       reg16 |= PCI_EXP_LNKCTL_RL;
-       pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
-
-       /* Wait for link training end. Break out after waiting for timeout */
-       start_jiffies = jiffies;
-       for (;;) {
-               pcie_capability_read_word(parent, PCI_EXP_LNKSTA, &reg16);
-               if (!(reg16 & PCI_EXP_LNKSTA_LT))
-                       break;
-               if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT))
-                       break;
-               msleep(1);
-       }
-       if (!(reg16 & PCI_EXP_LNKSTA_LT))
+       if (pcie_retrain_link(link))
                return;
 
        /* Training failed. Restore common clock configurations */
index 4fa9e35..77e6857 100644 (file)
@@ -107,11 +107,25 @@ static void pcie_bandwidth_notification_remove(struct pcie_device *srv)
        free_irq(srv->irq, srv);
 }
 
+static int pcie_bandwidth_notification_suspend(struct pcie_device *srv)
+{
+       pcie_disable_link_bandwidth_notification(srv->port);
+       return 0;
+}
+
+static int pcie_bandwidth_notification_resume(struct pcie_device *srv)
+{
+       pcie_enable_link_bandwidth_notification(srv->port);
+       return 0;
+}
+
 static struct pcie_port_service_driver pcie_bandwidth_notification_driver = {
        .name           = "pcie_bw_notification",
        .port_type      = PCIE_ANY_PORT,
        .service        = PCIE_PORT_SERVICE_BWNOTIF,
        .probe          = pcie_bandwidth_notification_probe,
+       .suspend        = pcie_bandwidth_notification_suspend,
+       .resume         = pcie_bandwidth_notification_resume,
        .remove         = pcie_bandwidth_notification_remove,
 };
 
index 7b77754..a32ec34 100644 (file)
@@ -6,6 +6,8 @@
  * Copyright (C) 2016 Intel Corp.
  */
 
+#define dev_fmt(fmt) "DPC: " fmt
+
 #include <linux/aer.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -100,7 +102,6 @@ static int dpc_wait_rp_inactive(struct dpc_dev *dpc)
 {
        unsigned long timeout = jiffies + HZ;
        struct pci_dev *pdev = dpc->dev->port;
-       struct device *dev = &dpc->dev->device;
        u16 cap = dpc->cap_pos, status;
 
        pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status);
@@ -110,7 +111,7 @@ static int dpc_wait_rp_inactive(struct dpc_dev *dpc)
                pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status);
        }
        if (status & PCI_EXP_DPC_RP_BUSY) {
-               dev_warn(dev, "DPC root port still busy\n");
+               pci_warn(pdev, "root port still busy\n");
                return -EBUSY;
        }
        return 0;
@@ -148,7 +149,6 @@ static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev)
 
 static void dpc_process_rp_pio_error(struct dpc_dev *dpc)
 {
-       struct device *dev = &dpc->dev->device;
        struct pci_dev *pdev = dpc->dev->port;
        u16 cap = dpc->cap_pos, dpc_status, first_error;
        u32 status, mask, sev, syserr, exc, dw0, dw1, dw2, dw3, log, prefix;
@@ -156,13 +156,13 @@ static void dpc_process_rp_pio_error(struct dpc_dev *dpc)
 
        pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_STATUS, &status);
        pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_MASK, &mask);
-       dev_err(dev, "rp_pio_status: %#010x, rp_pio_mask: %#010x\n",
+       pci_err(pdev, "rp_pio_status: %#010x, rp_pio_mask: %#010x\n",
                status, mask);
 
        pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_SEVERITY, &sev);
        pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_SYSERROR, &syserr);
        pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_EXCEPTION, &exc);
-       dev_err(dev, "RP PIO severity=%#010x, syserror=%#010x, exception=%#010x\n",
+       pci_err(pdev, "RP PIO severity=%#010x, syserror=%#010x, exception=%#010x\n",
                sev, syserr, exc);
 
        /* Get First Error Pointer */
@@ -171,7 +171,7 @@ static void dpc_process_rp_pio_error(struct dpc_dev *dpc)
 
        for (i = 0; i < ARRAY_SIZE(rp_pio_error_string); i++) {
                if ((status & ~mask) & (1 << i))
-                       dev_err(dev, "[%2d] %s%s\n", i, rp_pio_error_string[i],
+                       pci_err(pdev, "[%2d] %s%s\n", i, rp_pio_error_string[i],
                                first_error == i ? " (First)" : "");
        }
 
@@ -185,18 +185,18 @@ static void dpc_process_rp_pio_error(struct dpc_dev *dpc)
                              &dw2);
        pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG + 12,
                              &dw3);
-       dev_err(dev, "TLP Header: %#010x %#010x %#010x %#010x\n",
+       pci_err(pdev, "TLP Header: %#010x %#010x %#010x %#010x\n",
                dw0, dw1, dw2, dw3);
 
        if (dpc->rp_log_size < 5)
                goto clear_status;
        pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_IMPSPEC_LOG, &log);
-       dev_err(dev, "RP PIO ImpSpec Log %#010x\n", log);
+       pci_err(pdev, "RP PIO ImpSpec Log %#010x\n", log);
 
        for (i = 0; i < dpc->rp_log_size - 5; i++) {
                pci_read_config_dword(pdev,
                        cap + PCI_EXP_DPC_RP_PIO_TLPPREFIX_LOG, &prefix);
-               dev_err(dev, "TLP Prefix Header: dw%d, %#010x\n", i, prefix);
+               pci_err(pdev, "TLP Prefix Header: dw%d, %#010x\n", i, prefix);
        }
  clear_status:
        pci_write_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_STATUS, status);
@@ -229,18 +229,17 @@ static irqreturn_t dpc_handler(int irq, void *context)
        struct aer_err_info info;
        struct dpc_dev *dpc = context;
        struct pci_dev *pdev = dpc->dev->port;
-       struct device *dev = &dpc->dev->device;
        u16 cap = dpc->cap_pos, status, source, reason, ext_reason;
 
        pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status);
        pci_read_config_word(pdev, cap + PCI_EXP_DPC_SOURCE_ID, &source);
 
-       dev_info(dev, "DPC containment event, status:%#06x source:%#06x\n",
+       pci_info(pdev, "containment event, status:%#06x source:%#06x\n",
                 status, source);
 
        reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN) >> 1;
        ext_reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT) >> 5;
-       dev_warn(dev, "DPC %s detected\n",
+       pci_warn(pdev, "%s detected\n",
                 (reason == 0) ? "unmasked uncorrectable error" :
                 (reason == 1) ? "ERR_NONFATAL" :
                 (reason == 2) ? "ERR_FATAL" :
@@ -307,7 +306,7 @@ static int dpc_probe(struct pcie_device *dev)
                                           dpc_handler, IRQF_SHARED,
                                           "pcie-dpc", dpc);
        if (status) {
-               dev_warn(device, "request IRQ%d failed: %d\n", dev->irq,
+               pci_warn(pdev, "request IRQ%d failed: %d\n", dev->irq,
                         status);
                return status;
        }
@@ -319,7 +318,7 @@ static int dpc_probe(struct pcie_device *dev)
        if (dpc->rp_extensions) {
                dpc->rp_log_size = (cap & PCI_EXP_DPC_RP_PIO_LOG_SIZE) >> 8;
                if (dpc->rp_log_size < 4 || dpc->rp_log_size > 9) {
-                       dev_err(device, "RP PIO log size %u is invalid\n",
+                       pci_err(pdev, "RP PIO log size %u is invalid\n",
                                dpc->rp_log_size);
                        dpc->rp_log_size = 0;
                }
@@ -328,11 +327,11 @@ static int dpc_probe(struct pcie_device *dev)
        ctl = (ctl & 0xfff4) | PCI_EXP_DPC_CTL_EN_FATAL | PCI_EXP_DPC_CTL_INT_EN;
        pci_write_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CTL, ctl);
 
-       dev_info(device, "DPC error containment capabilities: Int Msg #%d, RPExt%c PoisonedTLP%c SwTrigger%c RP PIO Log %d, DL_ActiveErr%c\n",
-               cap & PCI_EXP_DPC_IRQ, FLAG(cap, PCI_EXP_DPC_CAP_RP_EXT),
-               FLAG(cap, PCI_EXP_DPC_CAP_POISONED_TLP),
-               FLAG(cap, PCI_EXP_DPC_CAP_SW_TRIGGER), dpc->rp_log_size,
-               FLAG(cap, PCI_EXP_DPC_CAP_DL_ACTIVE));
+       pci_info(pdev, "error containment capabilities: Int Msg #%d, RPExt%c PoisonedTLP%c SwTrigger%c RP PIO Log %d, DL_ActiveErr%c\n",
+                cap & PCI_EXP_DPC_IRQ, FLAG(cap, PCI_EXP_DPC_CAP_RP_EXT),
+                FLAG(cap, PCI_EXP_DPC_CAP_POISONED_TLP),
+                FLAG(cap, PCI_EXP_DPC_CAP_SW_TRIGGER), dpc->rp_log_size,
+                FLAG(cap, PCI_EXP_DPC_CAP_DL_ACTIVE));
 
        pci_add_ext_cap_save_buffer(pdev, PCI_EXT_CAP_ID_DPC, sizeof(u16));
        return status;
index 54d593d..f38e6c1 100644 (file)
@@ -7,6 +7,8 @@
  * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
  */
 
+#define dev_fmt(fmt) "PME: " fmt
+
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -194,14 +196,14 @@ static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id)
                 * assuming that the PME was reported by a PCIe-PCI bridge that
                 * used devfn different from zero.
                 */
-               pci_dbg(port, "PME interrupt generated for non-existent device %02x:%02x.%d\n",
-                       busnr, PCI_SLOT(devfn), PCI_FUNC(devfn));
+               pci_info(port, "interrupt generated for non-existent device %02x:%02x.%d\n",
+                        busnr, PCI_SLOT(devfn), PCI_FUNC(devfn));
                found = pcie_pme_from_pci_bridge(bus, 0);
        }
 
  out:
        if (!found)
-               pci_dbg(port, "Spurious native PME interrupt!\n");
+               pci_info(port, "Spurious native interrupt!\n");
 }
 
 /**
@@ -341,7 +343,7 @@ static int pcie_pme_probe(struct pcie_device *srv)
                return ret;
        }
 
-       pci_info(port, "Signaling PME with IRQ %d\n", srv->irq);
+       pci_info(port, "Signaling with IRQ %d\n", srv->irq);
 
        pcie_pme_mark_devices(port);
        pcie_pme_interrupt_enable(port, true);
index 7e12d01..0e8e2c1 100644 (file)
@@ -317,7 +317,7 @@ fail:
        res->flags = 0;
 out:
        if (res->flags)
-               pci_printk(KERN_DEBUG, dev, "reg 0x%x: %pR\n", pos, res);
+               pci_info(dev, "reg 0x%x: %pR\n", pos, res);
 
        return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
 }
@@ -435,7 +435,7 @@ static void pci_read_bridge_io(struct pci_bus *child)
                region.start = base;
                region.end = limit + io_granularity - 1;
                pcibios_bus_to_resource(dev->bus, res, &region);
-               pci_printk(KERN_DEBUG, dev, "  bridge window %pR\n", res);
+               pci_info(dev, "  bridge window %pR\n", res);
        }
 }
 
@@ -457,7 +457,7 @@ static void pci_read_bridge_mmio(struct pci_bus *child)
                region.start = base;
                region.end = limit + 0xfffff;
                pcibios_bus_to_resource(dev->bus, res, &region);
-               pci_printk(KERN_DEBUG, dev, "  bridge window %pR\n", res);
+               pci_info(dev, "  bridge window %pR\n", res);
        }
 }
 
@@ -510,7 +510,7 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child)
                region.start = base;
                region.end = limit + 0xfffff;
                pcibios_bus_to_resource(dev->bus, res, &region);
-               pci_printk(KERN_DEBUG, dev, "  bridge window %pR\n", res);
+               pci_info(dev, "  bridge window %pR\n", res);
        }
 }
 
@@ -540,8 +540,7 @@ void pci_read_bridge_bases(struct pci_bus *child)
                        if (res && res->flags) {
                                pci_bus_add_resource(child, res,
                                                     PCI_SUBTRACTIVE_DECODE);
-                               pci_printk(KERN_DEBUG, dev,
-                                          "  bridge window %pR (subtractive decode)\n",
+                               pci_info(dev, "  bridge window %pR (subtractive decode)\n",
                                           res);
                        }
                }
@@ -586,16 +585,10 @@ static void pci_release_host_bridge_dev(struct device *dev)
        kfree(to_pci_host_bridge(dev));
 }
 
-struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
+static void pci_init_host_bridge(struct pci_host_bridge *bridge)
 {
-       struct pci_host_bridge *bridge;
-
-       bridge = kzalloc(sizeof(*bridge) + priv, GFP_KERNEL);
-       if (!bridge)
-               return NULL;
-
        INIT_LIST_HEAD(&bridge->windows);
-       bridge->dev.release = pci_release_host_bridge_dev;
+       INIT_LIST_HEAD(&bridge->dma_ranges);
 
        /*
         * We assume we can manage these PCIe features.  Some systems may
@@ -608,6 +601,18 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
        bridge->native_shpc_hotplug = 1;
        bridge->native_pme = 1;
        bridge->native_ltr = 1;
+}
+
+struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
+{
+       struct pci_host_bridge *bridge;
+
+       bridge = kzalloc(sizeof(*bridge) + priv, GFP_KERNEL);
+       if (!bridge)
+               return NULL;
+
+       pci_init_host_bridge(bridge);
+       bridge->dev.release = pci_release_host_bridge_dev;
 
        return bridge;
 }
@@ -622,7 +627,7 @@ struct pci_host_bridge *devm_pci_alloc_host_bridge(struct device *dev,
        if (!bridge)
                return NULL;
 
-       INIT_LIST_HEAD(&bridge->windows);
+       pci_init_host_bridge(bridge);
        bridge->dev.release = devm_pci_release_host_bridge_dev;
 
        return bridge;
@@ -632,6 +637,7 @@ EXPORT_SYMBOL(devm_pci_alloc_host_bridge);
 void pci_free_host_bridge(struct pci_host_bridge *bridge)
 {
        pci_free_resource_list(&bridge->windows);
+       pci_free_resource_list(&bridge->dma_ranges);
 
        kfree(bridge);
 }
@@ -1081,6 +1087,36 @@ static void pci_enable_crs(struct pci_dev *pdev)
 
 static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus,
                                              unsigned int available_buses);
+/**
+ * pci_ea_fixed_busnrs() - Read fixed Secondary and Subordinate bus
+ * numbers from EA capability.
+ * @dev: Bridge
+ * @sec: updated with secondary bus number from EA
+ * @sub: updated with subordinate bus number from EA
+ *
+ * If @dev is a bridge with EA capability, update @sec and @sub with
+ * fixed bus numbers from the capability and return true.  Otherwise,
+ * return false.
+ */
+static bool pci_ea_fixed_busnrs(struct pci_dev *dev, u8 *sec, u8 *sub)
+{
+       int ea, offset;
+       u32 dw;
+
+       if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE)
+               return false;
+
+       /* find PCI EA capability in list */
+       ea = pci_find_capability(dev, PCI_CAP_ID_EA);
+       if (!ea)
+               return false;
+
+       offset = ea + PCI_EA_FIRST_ENT;
+       pci_read_config_dword(dev, offset, &dw);
+       *sec =  dw & PCI_EA_SEC_BUS_MASK;
+       *sub = (dw & PCI_EA_SUB_BUS_MASK) >> PCI_EA_SUB_BUS_SHIFT;
+       return true;
+}
 
 /*
  * pci_scan_bridge_extend() - Scan buses behind a bridge
@@ -1115,6 +1151,9 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev,
        u16 bctl;
        u8 primary, secondary, subordinate;
        int broken = 0;
+       bool fixed_buses;
+       u8 fixed_sec, fixed_sub;
+       int next_busnr;
 
        /*
         * Make sure the bridge is powered on to be able to access config
@@ -1214,17 +1253,24 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev,
                /* Clear errors */
                pci_write_config_word(dev, PCI_STATUS, 0xffff);
 
+               /* Read bus numbers from EA Capability (if present) */
+               fixed_buses = pci_ea_fixed_busnrs(dev, &fixed_sec, &fixed_sub);
+               if (fixed_buses)
+                       next_busnr = fixed_sec;
+               else
+                       next_busnr = max + 1;
+
                /*
                 * Prevent assigning a bus number that already exists.
                 * This can happen when a bridge is hot-plugged, so in this
                 * case we only re-scan this bus.
                 */
-               child = pci_find_bus(pci_domain_nr(bus), max+1);
+               child = pci_find_bus(pci_domain_nr(bus), next_busnr);
                if (!child) {
-                       child = pci_add_new_bus(bus, dev, max+1);
+                       child = pci_add_new_bus(bus, dev, next_busnr);
                        if (!child)
                                goto out;
-                       pci_bus_insert_busn_res(child, max+1,
+                       pci_bus_insert_busn_res(child, next_busnr,
                                                bus->busn_res.end);
                }
                max++;
@@ -1285,7 +1331,13 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev,
                        max += i;
                }
 
-               /* Set subordinate bus number to its real value */
+               /*
+                * Set subordinate bus number to its real value.
+                * If fixed subordinate bus number exists from EA
+                * capability then use it.
+                */
+               if (fixed_buses)
+                       max = fixed_sub;
                pci_bus_update_busn_res_end(child, max);
                pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
        }
@@ -1690,7 +1742,7 @@ int pci_setup_device(struct pci_dev *dev)
        dev->revision = class & 0xff;
        dev->class = class >> 8;                    /* upper 3 bytes */
 
-       pci_printk(KERN_DEBUG, dev, "[%04x:%04x] type %02x class %#08x\n",
+       pci_info(dev, "[%04x:%04x] type %02x class %#08x\n",
                   dev->vendor, dev->device, dev->hdr_type, dev->class);
 
        if (pci_early_dump)
@@ -2026,6 +2078,119 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
         */
 }
 
+static u16 hpx3_device_type(struct pci_dev *dev)
+{
+       u16 pcie_type = pci_pcie_type(dev);
+       const int pcie_to_hpx3_type[] = {
+               [PCI_EXP_TYPE_ENDPOINT]    = HPX_TYPE_ENDPOINT,
+               [PCI_EXP_TYPE_LEG_END]     = HPX_TYPE_LEG_END,
+               [PCI_EXP_TYPE_RC_END]      = HPX_TYPE_RC_END,
+               [PCI_EXP_TYPE_RC_EC]       = HPX_TYPE_RC_EC,
+               [PCI_EXP_TYPE_ROOT_PORT]   = HPX_TYPE_ROOT_PORT,
+               [PCI_EXP_TYPE_UPSTREAM]    = HPX_TYPE_UPSTREAM,
+               [PCI_EXP_TYPE_DOWNSTREAM]  = HPX_TYPE_DOWNSTREAM,
+               [PCI_EXP_TYPE_PCI_BRIDGE]  = HPX_TYPE_PCI_BRIDGE,
+               [PCI_EXP_TYPE_PCIE_BRIDGE] = HPX_TYPE_PCIE_BRIDGE,
+       };
+
+       if (pcie_type >= ARRAY_SIZE(pcie_to_hpx3_type))
+               return 0;
+
+       return pcie_to_hpx3_type[pcie_type];
+}
+
+static u8 hpx3_function_type(struct pci_dev *dev)
+{
+       if (dev->is_virtfn)
+               return HPX_FN_SRIOV_VIRT;
+       else if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV) > 0)
+               return HPX_FN_SRIOV_PHYS;
+       else
+               return HPX_FN_NORMAL;
+}
+
+static bool hpx3_cap_ver_matches(u8 pcie_cap_id, u8 hpx3_cap_id)
+{
+       u8 cap_ver = hpx3_cap_id & 0xf;
+
+       if ((hpx3_cap_id & BIT(4)) && cap_ver >= pcie_cap_id)
+               return true;
+       else if (cap_ver == pcie_cap_id)
+               return true;
+
+       return false;
+}
+
+static void program_hpx_type3_register(struct pci_dev *dev,
+                                      const struct hpx_type3 *reg)
+{
+       u32 match_reg, write_reg, header, orig_value;
+       u16 pos;
+
+       if (!(hpx3_device_type(dev) & reg->device_type))
+               return;
+
+       if (!(hpx3_function_type(dev) & reg->function_type))
+               return;
+
+       switch (reg->config_space_location) {
+       case HPX_CFG_PCICFG:
+               pos = 0;
+               break;
+       case HPX_CFG_PCIE_CAP:
+               pos = pci_find_capability(dev, reg->pci_exp_cap_id);
+               if (pos == 0)
+                       return;
+
+               break;
+       case HPX_CFG_PCIE_CAP_EXT:
+               pos = pci_find_ext_capability(dev, reg->pci_exp_cap_id);
+               if (pos == 0)
+                       return;
+
+               pci_read_config_dword(dev, pos, &header);
+               if (!hpx3_cap_ver_matches(PCI_EXT_CAP_VER(header),
+                                         reg->pci_exp_cap_ver))
+                       return;
+
+               break;
+       case HPX_CFG_VEND_CAP:  /* Fall through */
+       case HPX_CFG_DVSEC:     /* Fall through */
+       default:
+               pci_warn(dev, "Encountered _HPX type 3 with unsupported config space location");
+               return;
+       }
+
+       pci_read_config_dword(dev, pos + reg->match_offset, &match_reg);
+
+       if ((match_reg & reg->match_mask_and) != reg->match_value)
+               return;
+
+       pci_read_config_dword(dev, pos + reg->reg_offset, &write_reg);
+       orig_value = write_reg;
+       write_reg &= reg->reg_mask_and;
+       write_reg |= reg->reg_mask_or;
+
+       if (orig_value == write_reg)
+               return;
+
+       pci_write_config_dword(dev, pos + reg->reg_offset, write_reg);
+
+       pci_dbg(dev, "Applied _HPX3 at [0x%x]: 0x%08x -> 0x%08x",
+               pos, orig_value, write_reg);
+}
+
+static void program_hpx_type3(struct pci_dev *dev, struct hpx_type3 *hpx3)
+{
+       if (!hpx3)
+               return;
+
+       if (!pci_is_pcie(dev))
+               return;
+
+       program_hpx_type3_register(dev, hpx3);
+}
+
 int pci_configure_extended_tags(struct pci_dev *dev, void *ign)
 {
        struct pci_host_bridge *host;
@@ -2206,8 +2371,12 @@ static void pci_configure_serr(struct pci_dev *dev)
 
 static void pci_configure_device(struct pci_dev *dev)
 {
-       struct hotplug_params hpp;
-       int ret;
+       static const struct hotplug_program_ops hp_ops = {
+               .program_type0 = program_hpp_type0,
+               .program_type1 = program_hpp_type1,
+               .program_type2 = program_hpp_type2,
+               .program_type3 = program_hpx_type3,
+       };
 
        pci_configure_mps(dev);
        pci_configure_extended_tags(dev, NULL);
@@ -2216,14 +2385,7 @@ static void pci_configure_device(struct pci_dev *dev)
        pci_configure_eetlp_prefix(dev);
        pci_configure_serr(dev);
 
-       memset(&hpp, 0, sizeof(hpp));
-       ret = pci_get_hp_params(dev, &hpp);
-       if (ret)
-               return;
-
-       program_hpp_type2(dev, hpp.t2);
-       program_hpp_type1(dev, hpp.t1);
-       program_hpp_type0(dev, hpp.t0);
+       pci_acpi_program_hp_params(dev, &hp_ops);
 }
 
 static void pci_release_capabilities(struct pci_dev *dev)
@@ -3086,7 +3248,7 @@ int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
        conflict = request_resource_conflict(parent_res, res);
 
        if (conflict)
-               dev_printk(KERN_DEBUG, &b->dev,
+               dev_info(&b->dev,
                           "busn_res: can not insert %pR under %s%pR (conflicts with %s %pR)\n",
                            res, pci_is_root_bus(b) ? "domain " : "",
                            parent_res, conflict->name, conflict);
@@ -3106,8 +3268,7 @@ int pci_bus_update_busn_res_end(struct pci_bus *b, int bus_max)
 
        size = bus_max - res->start + 1;
        ret = adjust_resource(res, res->start, size);
-       dev_printk(KERN_DEBUG, &b->dev,
-                       "busn_res: %pR end %s updated to %02x\n",
+       dev_info(&b->dev, "busn_res: %pR end %s updated to %02x\n",
                        &old_res, ret ? "can not be" : "is", bus_max);
 
        if (!ret && !res->parent)
@@ -3125,8 +3286,7 @@ void pci_bus_release_busn_res(struct pci_bus *b)
                return;
 
        ret = release_resource(res);
-       dev_printk(KERN_DEBUG, &b->dev,
-                       "busn_res: %pR %s released\n",
+       dev_info(&b->dev, "busn_res: %pR %s released\n",
                        res, ret ? "can not be" : "is");
 }
 
index 6fa1627..445b51d 100644 (file)
@@ -222,6 +222,7 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
                }
                /* If arch decided it can't, fall through... */
 #endif /* HAVE_PCI_MMAP */
+               /* fall through */
        default:
                ret = -EINVAL;
                break;
index eb0afc2..0f16acc 100644 (file)
@@ -159,8 +159,7 @@ static int __init pci_apply_final_quirks(void)
        u8 tmp;
 
        if (pci_cache_line_size)
-               printk(KERN_DEBUG "PCI: CLS %u bytes\n",
-                      pci_cache_line_size << 2);
+               pr_info("PCI: CLS %u bytes\n", pci_cache_line_size << 2);
 
        pci_apply_fixup_final_quirks = true;
        for_each_pci_dev(dev) {
@@ -177,16 +176,16 @@ static int __init pci_apply_final_quirks(void)
                        if (!tmp || cls == tmp)
                                continue;
 
-                       printk(KERN_DEBUG "PCI: CLS mismatch (%u != %u), using %u bytes\n",
-                              cls << 2, tmp << 2,
-                              pci_dfl_cache_line_size << 2);
+                       pci_info(dev, "CLS mismatch (%u != %u), using %u bytes\n",
+                                cls << 2, tmp << 2,
+                                pci_dfl_cache_line_size << 2);
                        pci_cache_line_size = pci_dfl_cache_line_size;
                }
        }
 
        if (!pci_cache_line_size) {
-               printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n",
-                      cls << 2, pci_dfl_cache_line_size << 2);
+               pr_info("PCI: CLS %u bytes, default %u\n", cls << 2,
+                       pci_dfl_cache_line_size << 2);
                pci_cache_line_size = cls ? cls : pci_dfl_cache_line_size;
        }
 
@@ -2245,6 +2244,23 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s);
 
+/*
+ * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain
+ * Link bit cleared after starting the link retrain process to allow this
+ * process to finish.
+ *
+ * Affected devices: PI7C9X110, PI7C9X111SL, PI7C9X130.  See also the
+ * Pericom Errata Sheet PI7C9X111SLB_errata_rev1.2_102711.pdf.
+ */
+static void quirk_enable_clear_retrain_link(struct pci_dev *dev)
+{
+       dev->clear_retrain_link = 1;
+       pci_info(dev, "Enable PCIe Retrain Link quirk\n");
+}
+DECLARE_PCI_FIXUP_HEADER(0x12d8, 0xe110, quirk_enable_clear_retrain_link);
+DECLARE_PCI_FIXUP_HEADER(0x12d8, 0xe111, quirk_enable_clear_retrain_link);
+DECLARE_PCI_FIXUP_HEADER(0x12d8, 0xe130, quirk_enable_clear_retrain_link);
+
 static void fixup_rev1_53c810(struct pci_dev *dev)
 {
        u32 class = dev->class;
@@ -2596,7 +2612,7 @@ static void nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
        pci_read_config_dword(dev, 0x74, &cfg);
 
        if (cfg & ((1 << 2) | (1 << 15))) {
-               printk(KERN_INFO "Rewriting IRQ routing register on MCP55\n");
+               pr_info("Rewriting IRQ routing register on MCP55\n");
                cfg &= ~((1 << 2) | (1 << 15));
                pci_write_config_dword(dev, 0x74, cfg);
        }
@@ -3408,6 +3424,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034, quirk_no_bus_reset);
 
 /*
  * Root port on some Cavium CN8xxx chips do not successfully complete a bus
@@ -4905,6 +4922,7 @@ static void quirk_no_ats(struct pci_dev *pdev)
 
 /* AMD Stoney platform GPU */
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x98e4, quirk_no_ats);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x6900, quirk_no_ats);
 #endif /* CONFIG_PCI_ATS */
 
 /* Freescale PCIe doesn't support MSI in RC mode */
@@ -5122,3 +5140,61 @@ SWITCHTEC_QUIRK(0x8573);  /* PFXI 48XG3 */
 SWITCHTEC_QUIRK(0x8574);  /* PFXI 64XG3 */
 SWITCHTEC_QUIRK(0x8575);  /* PFXI 80XG3 */
 SWITCHTEC_QUIRK(0x8576);  /* PFXI 96XG3 */
+
+/*
+ * On Lenovo Thinkpad P50 SKUs with a Nvidia Quadro M1000M, the BIOS does
+ * not always reset the secondary Nvidia GPU between reboots if the system
+ * is configured to use Hybrid Graphics mode.  This results in the GPU
+ * being left in whatever state it was in during the *previous* boot, which
+ * causes spurious interrupts from the GPU, which in turn causes us to
+ * disable the wrong IRQ and end up breaking the touchpad.  Unsurprisingly,
+ * this also completely breaks nouveau.
+ *
+ * Luckily, it seems a simple reset of the Nvidia GPU brings it back to a
+ * clean state and fixes all these issues.
+ *
+ * When the machine is configured in Dedicated display mode, the issue
+ * doesn't occur.  Fortunately the GPU advertises NoReset+ when in this
+ * mode, so we can detect that and avoid resetting it.
+ */
+static void quirk_reset_lenovo_thinkpad_p50_nvgpu(struct pci_dev *pdev)
+{
+       void __iomem *map;
+       int ret;
+
+       if (pdev->subsystem_vendor != PCI_VENDOR_ID_LENOVO ||
+           pdev->subsystem_device != 0x222e ||
+           !pdev->reset_fn)
+               return;
+
+       if (pci_enable_device_mem(pdev))
+               return;
+
+       /*
+        * Based on nvkm_device_ctor() in
+        * drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+        */
+       map = pci_iomap(pdev, 0, 0x23000);
+       if (!map) {
+               pci_err(pdev, "Can't map MMIO space\n");
+               goto out_disable;
+       }
+
+       /*
+        * Make sure the GPU looks like it's been POSTed before resetting
+        * it.
+        */
+       if (ioread32(map + 0x2240c) & 0x2) {
+               pci_info(pdev, FW_BUG "GPU left initialized by EFI, resetting\n");
+               ret = pci_reset_function(pdev);
+               if (ret < 0)
+                       pci_err(pdev, "Failed to reset GPU: %d\n", ret);
+       }
+
+       iounmap(map);
+out_disable:
+       pci_disable_device(pdev);
+}
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, 0x13b1,
+                             PCI_CLASS_DISPLAY_VGA, 8,
+                             quirk_reset_lenovo_thinkpad_p50_nvgpu);
index 2b5f720..5c79226 100644 (file)
@@ -33,7 +33,7 @@ int pci_for_each_dma_alias(struct pci_dev *pdev,
        struct pci_bus *bus;
        int ret;
 
-       ret = fn(pdev, PCI_DEVID(pdev->bus->number, pdev->devfn), data);
+       ret = fn(pdev, pci_dev_id(pdev), data);
        if (ret)
                return ret;
 
@@ -88,9 +88,7 @@ int pci_for_each_dma_alias(struct pci_dev *pdev,
                                        return ret;
                                continue;
                        case PCI_EXP_TYPE_PCIE_BRIDGE:
-                               ret = fn(tmp,
-                                        PCI_DEVID(tmp->bus->number,
-                                                  tmp->devfn), data);
+                               ret = fn(tmp, pci_dev_id(tmp), data);
                                if (ret)
                                        return ret;
                                continue;
@@ -101,9 +99,7 @@ int pci_for_each_dma_alias(struct pci_dev *pdev,
                                         PCI_DEVID(tmp->subordinate->number,
                                                   PCI_DEVFN(0, 0)), data);
                        else
-                               ret = fn(tmp,
-                                        PCI_DEVID(tmp->bus->number,
-                                                  tmp->devfn), data);
+                               ret = fn(tmp, pci_dev_id(tmp), data);
                        if (ret)
                                return ret;
                }
index ec44a0f..0cdd5ff 100644 (file)
@@ -49,17 +49,15 @@ static void free_list(struct list_head *head)
 }
 
 /**
- * add_to_list() - add a new resource tracker to the list
+ * add_to_list() - Add a new resource tracker to the list
  * @head:      Head of the list
- * @dev:       device corresponding to which the resource
- *             belongs
- * @res:       The resource to be tracked
- * @add_size:  additional size to be optionally added
- *              to the resource
+ * @dev:       Device to which the resource belongs
+ * @res:       Resource to be tracked
+ * @add_size:  Additional size to be optionally added to the resource
  */
-static int add_to_list(struct list_head *head,
-                struct pci_dev *dev, struct resource *res,
-                resource_size_t add_size, resource_size_t min_align)
+static int add_to_list(struct list_head *head, struct pci_dev *dev,
+                      struct resource *res, resource_size_t add_size,
+                      resource_size_t min_align)
 {
        struct pci_dev_resource *tmp;
 
@@ -80,8 +78,7 @@ static int add_to_list(struct list_head *head,
        return 0;
 }
 
-static void remove_from_list(struct list_head *head,
-                                struct resource *res)
+static void remove_from_list(struct list_head *head, struct resource *res)
 {
        struct pci_dev_resource *dev_res, *tmp;
 
@@ -158,7 +155,7 @@ static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
                tmp->res = r;
                tmp->dev = dev;
 
-               /* fallback is smallest one or list is empty*/
+               /* Fallback is smallest one or list is empty */
                n = head;
                list_for_each_entry(dev_res, head, list) {
                        resource_size_t align;
@@ -171,21 +168,20 @@ static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
                                break;
                        }
                }
-               /* Insert it just before n*/
+               /* Insert it just before n */
                list_add_tail(&tmp->list, n);
        }
 }
 
-static void __dev_sort_resources(struct pci_dev *dev,
-                                struct list_head *head)
+static void __dev_sort_resources(struct pci_dev *dev, struct list_head *head)
 {
        u16 class = dev->class >> 8;
 
-       /* Don't touch classless devices or host bridges or ioapics.  */
+       /* Don't touch classless devices or host bridges or IOAPICs */
        if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
                return;
 
-       /* Don't touch ioapic devices already enabled by firmware */
+       /* Don't touch IOAPIC devices already enabled by firmware */
        if (class == PCI_CLASS_SYSTEM_PIC) {
                u16 command;
                pci_read_config_word(dev, PCI_COMMAND, &command);
@@ -204,19 +200,18 @@ static inline void reset_resource(struct resource *res)
 }
 
 /**
- * reassign_resources_sorted() - satisfy any additional resource requests
+ * reassign_resources_sorted() - Satisfy any additional resource requests
  *
- * @realloc_head : head of the list tracking requests requiring additional
- *             resources
- * @head     : head of the list tracking requests with allocated
- *             resources
+ * @realloc_head:      Head of the list tracking requests requiring
+ *                     additional resources
+ * @head:              Head of the list tracking requests with allocated
+ *                     resources
  *
- * Walk through each element of the realloc_head and try to procure
- * additional resources for the element, provided the element
- * is in the head list.
+ * Walk through each element of the realloc_head and try to procure additional
+ * resources for the element, provided the element is in the head list.
  */
 static void reassign_resources_sorted(struct list_head *realloc_head,
-               struct list_head *head)
+                                     struct list_head *head)
 {
        struct resource *res;
        struct pci_dev_resource *add_res, *tmp;
@@ -228,18 +223,18 @@ static void reassign_resources_sorted(struct list_head *realloc_head,
                bool found_match = false;
 
                res = add_res->res;
-               /* skip resource that has been reset */
+               /* Skip resource that has been reset */
                if (!res->flags)
                        goto out;
 
-               /* skip this resource if not found in head list */
+               /* Skip this resource if not found in head list */
                list_for_each_entry(dev_res, head, list) {
                        if (dev_res->res == res) {
                                found_match = true;
                                break;
                        }
                }
-               if (!found_match)/* just skip */
+               if (!found_match) /* Just skip */
                        continue;
 
                idx = res - &add_res->dev->resource[0];
@@ -255,10 +250,9 @@ static void reassign_resources_sorted(struct list_head *realloc_head,
                                 (IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN);
                        if (pci_reassign_resource(add_res->dev, idx,
                                                  add_size, align))
-                               pci_printk(KERN_DEBUG, add_res->dev,
-                                          "failed to add %llx res[%d]=%pR\n",
-                                          (unsigned long long)add_size,
-                                          idx, res);
+                               pci_info(add_res->dev, "failed to add %llx res[%d]=%pR\n",
+                                        (unsigned long long) add_size, idx,
+                                        res);
                }
 out:
                list_del(&add_res->list);
@@ -267,14 +261,14 @@ out:
 }
 
 /**
- * assign_requested_resources_sorted() - satisfy resource requests
+ * assign_requested_resources_sorted() - Satisfy resource requests
  *
- * @head : head of the list tracking requests for resources
- * @fail_head : head of the list tracking requests that could
- *             not be allocated
+ * @head:      Head of the list tracking requests for resources
+ * @fail_head: Head of the list tracking requests that could not be
+ *             allocated
  *
- * Satisfy resource requests of each element in the list. Add
- * requests that could not satisfied to the failed_list.
+ * Satisfy resource requests of each element in the list.  Add requests that
+ * could not be satisfied to the failed_list.
  */
 static void assign_requested_resources_sorted(struct list_head *head,
                                 struct list_head *fail_head)
@@ -290,8 +284,9 @@ static void assign_requested_resources_sorted(struct list_head *head,
                    pci_assign_resource(dev_res->dev, idx)) {
                        if (fail_head) {
                                /*
-                                * if the failed res is for ROM BAR, and it will
-                                * be enabled later, don't add it to the list
+                                * If the failed resource is a ROM BAR and
+                                * it will be enabled later, don't add it
+                                * to the list.
                                 */
                                if (!((idx == PCI_ROM_RESOURCE) &&
                                      (!(res->flags & IORESOURCE_ROM_ENABLE))))
@@ -310,15 +305,14 @@ static unsigned long pci_fail_res_type_mask(struct list_head *fail_head)
        struct pci_dev_resource *fail_res;
        unsigned long mask = 0;
 
-       /* check failed type */
+       /* Check failed type */
        list_for_each_entry(fail_res, fail_head, list)
                mask |= fail_res->flags;
 
        /*
-        * one pref failed resource will set IORESOURCE_MEM,
-        * as we can allocate pref in non-pref range.
-        * Will release all assigned non-pref sibling resources
-        * according to that bit.
+        * One pref failed resource will set IORESOURCE_MEM, as we can
+        * allocate pref in non-pref range.  Will release all assigned
+        * non-pref sibling resources according to that bit.
         */
        return mask & (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH);
 }
@@ -328,11 +322,11 @@ static bool pci_need_to_release(unsigned long mask, struct resource *res)
        if (res->flags & IORESOURCE_IO)
                return !!(mask & IORESOURCE_IO);
 
-       /* check pref at first */
+       /* Check pref at first */
        if (res->flags & IORESOURCE_PREFETCH) {
                if (mask & IORESOURCE_PREFETCH)
                        return true;
-               /* count pref if its parent is non-pref */
+               /* Count pref if its parent is non-pref */
                else if ((mask & IORESOURCE_MEM) &&
                         !(res->parent->flags & IORESOURCE_PREFETCH))
                        return true;
@@ -343,33 +337,33 @@ static bool pci_need_to_release(unsigned long mask, struct resource *res)
        if (res->flags & IORESOURCE_MEM)
                return !!(mask & IORESOURCE_MEM);
 
-       return false;   /* should not get here */
+       return false;   /* Should not get here */
 }
 
 static void __assign_resources_sorted(struct list_head *head,
-                                struct list_head *realloc_head,
-                                struct list_head *fail_head)
+                                     struct list_head *realloc_head,
+                                     struct list_head *fail_head)
 {
        /*
-        * Should not assign requested resources at first.
-        *   they could be adjacent, so later reassign can not reallocate
-        *   them one by one in parent resource window.
-        * Try to assign requested + add_size at beginning
-        *  if could do that, could get out early.
-        *  if could not do that, we still try to assign requested at first,
-        *    then try to reassign add_size for some resources.
+        * Should not assign requested resources at first.  They could be
+        * adjacent, so later reassign can not reallocate them one by one in
+        * parent resource window.
+        *
+        * Try to assign requested + add_size at beginning.  If could do that,
+        * could get out early.  If could not do that, we still try to assign
+        * requested at first, then try to reassign add_size for some resources.
         *
         * Separate three resource type checking if we need to release
         * assigned resource after requested + add_size try.
-        *      1. if there is io port assign fail, will release assigned
-        *         io port.
-        *      2. if there is pref mmio assign fail, release assigned
-        *         pref mmio.
-        *         if assigned pref mmio's parent is non-pref mmio and there
-        *         is non-pref mmio assign fail, will release that assigned
-        *         pref mmio.
-        *      3. if there is non-pref mmio assign fail or pref mmio
-        *         assigned fail, will release assigned non-pref mmio.
+        *
+        *      1. If IO port assignment fails, will release assigned IO
+        *         port.
+        *      2. If pref MMIO assignment fails, release assigned pref
+        *         MMIO.  If assigned pref MMIO's parent is non-pref MMIO
+        *         and non-pref MMIO assignment fails, will release that
+        *         assigned pref MMIO.
+        *      3. If non-pref MMIO assignment fails or pref MMIO
+        *         assignment fails, will release assigned non-pref MMIO.
         */
        LIST_HEAD(save_head);
        LIST_HEAD(local_fail_head);
@@ -398,7 +392,7 @@ static void __assign_resources_sorted(struct list_head *head,
                /*
                 * There are two kinds of additional resources in the list:
                 * 1. bridge resource  -- IORESOURCE_STARTALIGN
-                * 2. SR-IOV resource   -- IORESOURCE_SIZEALIGN
+                * 2. SR-IOV resource  -- IORESOURCE_SIZEALIGN
                 * Here just fix the additional alignment for bridge
                 */
                if (!(dev_res->res->flags & IORESOURCE_STARTALIGN))
@@ -407,10 +401,10 @@ static void __assign_resources_sorted(struct list_head *head,
                add_align = get_res_add_align(realloc_head, dev_res->res);
 
                /*
-                * The "head" list is sorted by the alignment to make sure
-                * resources with bigger alignment will be assigned first.
-                * After we change the alignment of a dev_res in "head" list,
-                * we need to reorder the list by alignment to make it
+                * The "head" list is sorted by alignment so resources with
+                * bigger alignment will be assigned first.  After we
+                * change the alignment of a dev_res in "head" list, we
+                * need to reorder the list by alignment to make it
                 * consistent.
                 */
                if (add_align > dev_res->res->start) {
@@ -435,7 +429,7 @@ static void __assign_resources_sorted(struct list_head *head,
        /* Try updated head list with add_size added */
        assign_requested_resources_sorted(head, &local_fail_head);
 
-       /* all assigned with add_size ? */
+       /* All assigned with add_size? */
        if (list_empty(&local_fail_head)) {
                /* Remove head list from realloc_head list */
                list_for_each_entry(dev_res, head, list)
@@ -445,13 +439,13 @@ static void __assign_resources_sorted(struct list_head *head,
                return;
        }
 
-       /* check failed type */
+       /* Check failed type */
        fail_type = pci_fail_res_type_mask(&local_fail_head);
-       /* remove not need to be released assigned res from head list etc */
+       /* Remove not need to be released assigned res from head list etc */
        list_for_each_entry_safe(dev_res, tmp_res, head, list)
                if (dev_res->res->parent &&
                    !pci_need_to_release(fail_type, dev_res->res)) {
-                       /* remove it from realloc_head list */
+                       /* Remove it from realloc_head list */
                        remove_from_list(realloc_head, dev_res->res);
                        remove_from_list(&save_head, dev_res->res);
                        list_del(&dev_res->list);
@@ -477,16 +471,15 @@ requested_and_reassign:
        /* Satisfy the must-have resource requests */
        assign_requested_resources_sorted(head, fail_head);
 
-       /* Try to satisfy any additional optional resource
-               requests */
+       /* Try to satisfy any additional optional resource requests */
        if (realloc_head)
                reassign_resources_sorted(realloc_head, head);
        free_list(head);
 }
 
 static void pdev_assign_resources_sorted(struct pci_dev *dev,
-                                struct list_head *add_head,
-                                struct list_head *fail_head)
+                                        struct list_head *add_head,
+                                        struct list_head *fail_head)
 {
        LIST_HEAD(head);
 
@@ -563,17 +556,19 @@ void pci_setup_cardbus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pci_setup_cardbus);
 
-/* Initialize bridges with base/limit values we have collected.
-   PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998)
-   requires that if there is no I/O ports or memory behind the
-   bridge, corresponding range must be turned off by writing base
-   value greater than limit to the bridge's base/limit registers.
-
-   Note: care must be taken when updating I/O base/limit registers
-   of bridges which support 32-bit I/O. This update requires two
-   config space writes, so it's quite possible that an I/O window of
-   the bridge will have some undesirable address (e.g. 0) after the
-   first write. Ditto 64-bit prefetchable MMIO.  */
+/*
+ * Initialize bridges with base/limit values we have collected.  PCI-to-PCI
+ * Bridge Architecture Specification rev. 1.1 (1998) requires that if there
+ * are no I/O ports or memory behind the bridge, the corresponding range
+ * must be turned off by writing base value greater than limit to the
+ * bridge's base/limit registers.
+ *
+ * Note: care must be taken when updating I/O base/limit registers of
+ * bridges which support 32-bit I/O.  This update requires two config space
+ * writes, so it's quite possible that an I/O window of the bridge will
+ * have some undesirable address (e.g. 0) after the first write.  Ditto
+ * 64-bit prefetchable MMIO.
+ */
 static void pci_setup_bridge_io(struct pci_dev *bridge)
 {
        struct resource *res;
@@ -587,7 +582,7 @@ static void pci_setup_bridge_io(struct pci_dev *bridge)
        if (bridge->io_window_1k)
                io_mask = PCI_IO_1K_RANGE_MASK;
 
-       /* Set up the top and bottom of the PCI I/O segment for this bus. */
+       /* Set up the top and bottom of the PCI I/O segment for this bus */
        res = &bridge->resource[PCI_BRIDGE_RESOURCES + 0];
        pcibios_resource_to_bus(bridge->bus, &region, res);
        if (res->flags & IORESOURCE_IO) {
@@ -595,19 +590,19 @@ static void pci_setup_bridge_io(struct pci_dev *bridge)
                io_base_lo = (region.start >> 8) & io_mask;
                io_limit_lo = (region.end >> 8) & io_mask;
                l = ((u16) io_limit_lo << 8) | io_base_lo;
-               /* Set up upper 16 bits of I/O base/limit. */
+               /* Set up upper 16 bits of I/O base/limit */
                io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
                pci_info(bridge, "  bridge window %pR\n", res);
        } else {
-               /* Clear upper 16 bits of I/O base/limit. */
+               /* Clear upper 16 bits of I/O base/limit */
                io_upper16 = 0;
                l = 0x00f0;
        }
-       /* Temporarily disable the I/O range before updating PCI_IO_BASE. */
+       /* Temporarily disable the I/O range before updating PCI_IO_BASE */
        pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
-       /* Update lower 16 bits of I/O base/limit. */
+       /* Update lower 16 bits of I/O base/limit */
        pci_write_config_word(bridge, PCI_IO_BASE, l);
-       /* Update upper 16 bits of I/O base/limit. */
+       /* Update upper 16 bits of I/O base/limit */
        pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16);
 }
 
@@ -617,7 +612,7 @@ static void pci_setup_bridge_mmio(struct pci_dev *bridge)
        struct pci_bus_region region;
        u32 l;
 
-       /* Set up the top and bottom of the PCI Memory segment for this bus. */
+       /* Set up the top and bottom of the PCI Memory segment for this bus */
        res = &bridge->resource[PCI_BRIDGE_RESOURCES + 1];
        pcibios_resource_to_bus(bridge->bus, &region, res);
        if (res->flags & IORESOURCE_MEM) {
@@ -636,12 +631,14 @@ static void pci_setup_bridge_mmio_pref(struct pci_dev *bridge)
        struct pci_bus_region region;
        u32 l, bu, lu;
 
-       /* Clear out the upper 32 bits of PREF limit.
-          If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily
-          disables PREF range, which is ok. */
+       /*
+        * Clear out the upper 32 bits of PREF limit.  If
+        * PCI_PREF_BASE_UPPER32 was non-zero, this temporarily disables
+        * PREF range, which is ok.
+        */
        pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
 
-       /* Set up PREF base/limit. */
+       /* Set up PREF base/limit */
        bu = lu = 0;
        res = &bridge->resource[PCI_BRIDGE_RESOURCES + 2];
        pcibios_resource_to_bus(bridge->bus, &region, res);
@@ -658,7 +655,7 @@ static void pci_setup_bridge_mmio_pref(struct pci_dev *bridge)
        }
        pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
 
-       /* Set the upper 32 bits of PREF base & limit. */
+       /* Set the upper 32 bits of PREF base & limit */
        pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
        pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
 }
@@ -702,13 +699,13 @@ int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
                return 0;
 
        if (pci_claim_resource(bridge, i) == 0)
-               return 0;       /* claimed the window */
+               return 0;       /* Claimed the window */
 
        if ((bridge->class >> 8) != PCI_CLASS_BRIDGE_PCI)
                return 0;
 
        if (!pci_bus_clip_resource(bridge, i))
-               return -EINVAL; /* clipping didn't change anything */
+               return -EINVAL; /* Clipping didn't change anything */
 
        switch (i - PCI_BRIDGE_RESOURCES) {
        case 0:
@@ -725,14 +722,16 @@ int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
        }
 
        if (pci_claim_resource(bridge, i) == 0)
-               return 0;       /* claimed a smaller window */
+               return 0;       /* Claimed a smaller window */
 
        return -EINVAL;
 }
 
-/* Check whether the bridge supports optional I/O and
-   prefetchable memory ranges. If not, the respective
-   base/limit registers must be read-only and read as 0. */
+/*
+ * Check whether the bridge supports optional I/O and prefetchable memory
+ * ranges.  If not, the respective base/limit registers must be read-only
+ * and read as 0.
+ */
 static void pci_bridge_check_ranges(struct pci_bus *bus)
 {
        struct pci_dev *bridge = bus->self;
@@ -752,12 +751,14 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)
        }
 }
 
-/* Helper function for sizing routines: find first available
-   bus resource of a given type. Note: we intentionally skip
-   the bus resources which have already been assigned (that is,
-   have non-NULL parent resource). */
+/*
+ * Helper function for sizing routines: find first available bus resource
+ * of a given type.  Note: we intentionally skip the bus resources which
+ * have already been assigned (that is, have non-NULL parent resource).
+ */
 static struct resource *find_free_bus_resource(struct pci_bus *bus,
-                        unsigned long type_mask, unsigned long type)
+                                              unsigned long type_mask,
+                                              unsigned long type)
 {
        int i;
        struct resource *r;
@@ -772,19 +773,21 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus,
 }
 
 static resource_size_t calculate_iosize(resource_size_t size,
-               resource_size_t min_size,
-               resource_size_t size1,
-               resource_size_t add_size,
-               resource_size_t children_add_size,
-               resource_size_t old_size,
-               resource_size_t align)
+                                       resource_size_t min_size,
+                                       resource_size_t size1,
+                                       resource_size_t add_size,
+                                       resource_size_t children_add_size,
+                                       resource_size_t old_size,
+                                       resource_size_t align)
 {
        if (size < min_size)
                size = min_size;
        if (old_size == 1)
                old_size = 0;
-       /* To be fixed in 2.5: we should have sort of HAVE_ISA
-          flag in the struct pci_bus. */
+       /*
+        * To be fixed in 2.5: we should have sort of HAVE_ISA flag in the
+        * struct pci_bus.
+        */
 #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
        size = (size & 0xff) + ((size & ~0xffUL) << 2);
 #endif
@@ -797,11 +800,11 @@ static resource_size_t calculate_iosize(resource_size_t size,
 }
 
 static resource_size_t calculate_memsize(resource_size_t size,
-               resource_size_t min_size,
-               resource_size_t add_size,
-               resource_size_t children_add_size,
-               resource_size_t old_size,
-               resource_size_t align)
+                                        resource_size_t min_size,
+                                        resource_size_t add_size,
+                                        resource_size_t children_add_size,
+                                        resource_size_t old_size,
+                                        resource_size_t align)
 {
        if (size < min_size)
                size = min_size;
@@ -824,8 +827,7 @@ resource_size_t __weak pcibios_window_alignment(struct pci_bus *bus,
 #define PCI_P2P_DEFAULT_IO_ALIGN       0x1000          /* 4KiB */
 #define PCI_P2P_DEFAULT_IO_ALIGN_1K    0x400           /* 1KiB */
 
-static resource_size_t window_alignment(struct pci_bus *bus,
-                                       unsigned long type)
+static resource_size_t window_alignment(struct pci_bus *bus, unsigned long type)
 {
        resource_size_t align = 1, arch_align;
 
@@ -833,8 +835,8 @@ static resource_size_t window_alignment(struct pci_bus *bus,
                align = PCI_P2P_DEFAULT_MEM_ALIGN;
        else if (type & IORESOURCE_IO) {
                /*
-                * Per spec, I/O windows are 4K-aligned, but some
-                * bridges have an extension to support 1K alignment.
+                * Per spec, I/O windows are 4K-aligned, but some bridges have
+                * an extension to support 1K alignment.
                 */
                if (bus->self->io_window_1k)
                        align = PCI_P2P_DEFAULT_IO_ALIGN_1K;
@@ -847,20 +849,21 @@ static resource_size_t window_alignment(struct pci_bus *bus,
 }
 
 /**
- * pbus_size_io() - size the io window of a given bus
+ * pbus_size_io() - Size the I/O window of a given bus
  *
- * @bus : the bus
- * @min_size : the minimum io window that must to be allocated
- * @add_size : additional optional io window
- * @realloc_head : track the additional io window on this list
+ * @bus:               The bus
+ * @min_size:          The minimum I/O window that must be allocated
+ * @add_size:          Additional optional I/O window
+ * @realloc_head:      Track the additional I/O window on this list
  *
- * Sizing the IO windows of the PCI-PCI bridge is trivial,
- * since these windows have 1K or 4K granularity and the IO ranges
- * of non-bridge PCI devices are limited to 256 bytes.
- * We must be careful with the ISA aliasing though.
+ * Sizing the I/O windows of the PCI-PCI bridge is trivial, since these
+ * windows have 1K or 4K granularity and the I/O ranges of non-bridge PCI
+ * devices are limited to 256 bytes.  We must be careful with the ISA
+ * aliasing though.
  */
 static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
-               resource_size_t add_size, struct list_head *realloc_head)
+                        resource_size_t add_size,
+                        struct list_head *realloc_head)
 {
        struct pci_dev *dev;
        struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO,
@@ -918,9 +921,9 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
        if (size1 > size0 && realloc_head) {
                add_to_list(realloc_head, bus->self, b_res, size1-size0,
                            min_align);
-               pci_printk(KERN_DEBUG, bus->self, "bridge window %pR to %pR add_size %llx\n",
-                          b_res, &bus->busn_res,
-                          (unsigned long long)size1-size0);
+               pci_info(bus->self, "bridge window %pR to %pR add_size %llx\n",
+                        b_res, &bus->busn_res,
+                        (unsigned long long) size1 - size0);
        }
 }
 
@@ -947,33 +950,33 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns,
 }
 
 /**
- * pbus_size_mem() - size the memory window of a given bus
+ * pbus_size_mem() - Size the memory window of a given bus
  *
- * @bus : the bus
- * @mask: mask the resource flag, then compare it with type
- * @type: the type of free resource from bridge
- * @type2: second match type
- * @type3: third match type
- * @min_size : the minimum memory window that must to be allocated
- * @add_size : additional optional memory window
- * @realloc_head : track the additional memory window on this list
+ * @bus:               The bus
+ * @mask:              Mask the resource flag, then compare it with type
+ * @type:              The type of free resource from bridge
+ * @type2:             Second match type
+ * @type3:             Third match type
+ * @min_size:          The minimum memory window that must be allocated
+ * @add_size:          Additional optional memory window
+ * @realloc_head:      Track the additional memory window on this list
  *
- * Calculate the size of the bus and minimal alignment which
- * guarantees that all child resources fit in this size.
+ * Calculate the size of the bus and minimal alignment which guarantees
+ * that all child resources fit in this size.
  *
- * Returns -ENOSPC if there's no available bus resource of the desired type.
- * Otherwise, sets the bus resource start/end to indicate the required
- * size, adds things to realloc_head (if supplied), and returns 0.
+ * Return -ENOSPC if there's no available bus resource of the desired
+ * type.  Otherwise, set the bus resource start/end to indicate the
+ * required size, add things to realloc_head (if supplied), and return 0.
  */
 static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
                         unsigned long type, unsigned long type2,
-                        unsigned long type3,
-                        resource_size_t min_size, resource_size_t add_size,
+                        unsigned long type3, resource_size_t min_size,
+                        resource_size_t add_size,
                         struct list_head *realloc_head)
 {
        struct pci_dev *dev;
        resource_size_t min_align, align, size, size0, size1;
-       resource_size_t aligns[18];     /* Alignments from 1Mb to 128Gb */
+       resource_size_t aligns[18]; /* Alignments from 1MB to 128GB */
        int order, max_order;
        struct resource *b_res = find_free_bus_resource(bus,
                                        mask | IORESOURCE_PREFETCH, type);
@@ -1002,12 +1005,12 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
                                continue;
                        r_size = resource_size(r);
 #ifdef CONFIG_PCI_IOV
-                       /* put SRIOV requested res to the optional list */
+                       /* Put SRIOV requested res to the optional list */
                        if (realloc_head && i >= PCI_IOV_RESOURCES &&
                                        i <= PCI_IOV_RESOURCE_END) {
                                add_align = max(pci_resource_alignment(dev, r), add_align);
                                r->end = r->start - 1;
-                               add_to_list(realloc_head, dev, r, r_size, 0/* don't care */);
+                               add_to_list(realloc_head, dev, r, r_size, 0 /* Don't care */);
                                children_add_size += r_size;
                                continue;
                        }
@@ -1029,8 +1032,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
                                continue;
                        }
                        size += max(r_size, align);
-                       /* Exclude ranges with size > align from
-                          calculation of the alignment. */
+                       /*
+                        * Exclude ranges with size > align from calculation of
+                        * the alignment.
+                        */
                        if (r_size <= align)
                                aligns[order] += align;
                        if (order > max_order)
@@ -1063,7 +1068,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
        b_res->flags |= IORESOURCE_STARTALIGN;
        if (size1 > size0 && realloc_head) {
                add_to_list(realloc_head, bus->self, b_res, size1-size0, add_align);
-               pci_printk(KERN_DEBUG, bus->self, "bridge window %pR to %pR add_size %llx add_align %llx\n",
+               pci_info(bus->self, "bridge window %pR to %pR add_size %llx add_align %llx\n",
                           b_res, &bus->busn_res,
                           (unsigned long long) (size1 - size0),
                           (unsigned long long) add_align);
@@ -1081,7 +1086,7 @@ unsigned long pci_cardbus_resource_alignment(struct resource *res)
 }
 
 static void pci_bus_size_cardbus(struct pci_bus *bus,
-                       struct list_head *realloc_head)
+                                struct list_head *realloc_head)
 {
        struct pci_dev *bridge = bus->self;
        struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
@@ -1091,8 +1096,8 @@ static void pci_bus_size_cardbus(struct pci_bus *bus,
        if (b_res[0].parent)
                goto handle_b_res_1;
        /*
-        * Reserve some resources for CardBus.  We reserve
-        * a fixed amount of bus space for CardBus bridges.
+        * Reserve some resources for CardBus.  We reserve a fixed amount
+        * of bus space for CardBus bridges.
         */
        b_res[0].start = pci_cardbus_io_size;
        b_res[0].end = b_res[0].start + pci_cardbus_io_size - 1;
@@ -1116,7 +1121,7 @@ handle_b_res_1:
        }
 
 handle_b_res_2:
-       /* MEM1 must not be pref mmio */
+       /* MEM1 must not be pref MMIO */
        pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
        if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM1) {
                ctrl &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM1;
@@ -1124,10 +1129,7 @@ handle_b_res_2:
                pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
        }
 
-       /*
-        * Check whether prefetchable memory is supported
-        * by this bridge.
-        */
+       /* Check whether prefetchable memory is supported by this bridge. */
        pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
        if (!(ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0)) {
                ctrl |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
@@ -1138,9 +1140,8 @@ handle_b_res_2:
        if (b_res[2].parent)
                goto handle_b_res_3;
        /*
-        * If we have prefetchable memory support, allocate
-        * two regions.  Otherwise, allocate one region of
-        * twice the size.
+        * If we have prefetchable memory support, allocate two regions.
+        * Otherwise, allocate one region of twice the size.
         */
        if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
                b_res[2].start = pci_cardbus_mem_size;
@@ -1153,7 +1154,7 @@ handle_b_res_2:
                                 pci_cardbus_mem_size, pci_cardbus_mem_size);
                }
 
-               /* reduce that to half */
+               /* Reduce that to half */
                b_res_3_size = pci_cardbus_mem_size;
        }
 
@@ -1204,7 +1205,7 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
 
        switch (bus->self->hdr_type) {
        case PCI_HEADER_TYPE_CARDBUS:
-               /* don't size cardbuses yet. */
+               /* Don't size CardBuses yet */
                break;
 
        case PCI_HEADER_TYPE_BRIDGE:
@@ -1271,18 +1272,17 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
 
                /*
                 * Compute the size required to put everything else in the
-                * non-prefetchable window.  This includes:
+                * non-prefetchable window. This includes:
                 *
                 *   - all non-prefetchable resources
                 *   - 32-bit prefetchable resources if there's a 64-bit
                 *     prefetchable window or no prefetchable window at all
-                *   - 64-bit prefetchable resources if there's no
-                *     prefetchable window at all
+                *   - 64-bit prefetchable resources if there's no prefetchable
+                *     window at all
                 *
-                * Note that the strategy in __pci_assign_resource() must
-                * match that used here.  Specifically, we cannot put a
-                * 32-bit prefetchable resource in a 64-bit prefetchable
-                * window.
+                * Note that the strategy in __pci_assign_resource() must match
+                * that used here. Specifically, we cannot put a 32-bit
+                * prefetchable resource in a 64-bit prefetchable window.
                 */
                pbus_size_mem(bus, mask, IORESOURCE_MEM, type2, type3,
                                realloc_head ? 0 : additional_mem_size,
@@ -1315,8 +1315,8 @@ static void assign_fixed_resource_on_bus(struct pci_bus *b, struct resource *r)
 }
 
 /*
- * Try to assign any resources marked as IORESOURCE_PCI_FIXED, as they
- * are skipped by pbus_assign_resources_sorted().
+ * Try to assign any resources marked as IORESOURCE_PCI_FIXED, as they are
+ * skipped by pbus_assign_resources_sorted().
  */
 static void pdev_assign_fixed_resources(struct pci_dev *dev)
 {
@@ -1427,10 +1427,9 @@ static void pci_bus_allocate_resources(struct pci_bus *b)
        struct pci_bus *child;
 
        /*
-        * Carry out a depth-first search on the PCI bus
-        * tree to allocate bridge apertures. Read the
-        * programmed bridge bases and recursively claim
-        * the respective bridge resources.
+        * Carry out a depth-first search on the PCI bus tree to allocate
+        * bridge apertures.  Read the programmed bridge bases and
+        * recursively claim the respective bridge resources.
         */
        if (b->self) {
                pci_read_bridge_bases(b);
@@ -1484,7 +1483,7 @@ static void __pci_bridge_assign_resources(const struct pci_dev *bridge,
         IORESOURCE_MEM_64)
 
 static void pci_bridge_release_resources(struct pci_bus *bus,
-                                         unsigned long type)
+                                        unsigned long type)
 {
        struct pci_dev *dev = bus->self;
        struct resource *r;
@@ -1495,16 +1494,14 @@ static void pci_bridge_release_resources(struct pci_bus *bus,
        b_res = &dev->resource[PCI_BRIDGE_RESOURCES];
 
        /*
-        *     1. if there is io port assign fail, will release bridge
-        *        io port.
-        *     2. if there is non pref mmio assign fail, release bridge
-        *        nonpref mmio.
-        *     3. if there is 64bit pref mmio assign fail, and bridge pref
-        *        is 64bit, release bridge pref mmio.
-        *     4. if there is pref mmio assign fail, and bridge pref is
-        *        32bit mmio, release bridge pref mmio
-        *     5. if there is pref mmio assign fail, and bridge pref is not
-        *        assigned, release bridge nonpref mmio.
+        * 1. If IO port assignment fails, release bridge IO port.
+        * 2. If non pref MMIO assignment fails, release bridge nonpref MMIO.
+        * 3. If 64bit pref MMIO assignment fails, and bridge pref is 64bit,
+        *    release bridge pref MMIO.
+        * 4. If pref MMIO assignment fails, and bridge pref is 32bit,
+        *    release bridge pref MMIO.
+        * 5. If pref MMIO assignment fails, and bridge pref is not
+        *    assigned, release bridge nonpref MMIO.
         */
        if (type & IORESOURCE_IO)
                idx = 0;
@@ -1524,25 +1521,22 @@ static void pci_bridge_release_resources(struct pci_bus *bus,
        if (!r->parent)
                return;
 
-       /*
-        * if there are children under that, we should release them
-        *  all
-        */
+       /* If there are children, release them all */
        release_child_resources(r);
        if (!release_resource(r)) {
                type = old_flags = r->flags & PCI_RES_TYPE_MASK;
-               pci_printk(KERN_DEBUG, dev, "resource %d %pR released\n",
-                                       PCI_BRIDGE_RESOURCES + idx, r);
-               /* keep the old size */
+               pci_info(dev, "resource %d %pR released\n",
+                        PCI_BRIDGE_RESOURCES + idx, r);
+               /* Keep the old size */
                r->end = resource_size(r) - 1;
                r->start = 0;
                r->flags = 0;
 
-               /* avoiding touch the one without PREF */
+               /* Avoiding touch the one without PREF */
                if (type & IORESOURCE_PREFETCH)
                        type = IORESOURCE_PREFETCH;
                __pci_setup_bridge(bus, type);
-               /* for next child res under same bridge */
+               /* For next child res under same bridge */
                r->flags = old_flags;
        }
 }
@@ -1551,9 +1545,10 @@ enum release_type {
        leaf_only,
        whole_subtree,
 };
+
 /*
- * try to release pci bridge resources that is from leaf bridge,
- * so we can allocate big new one later
+ * Try to release PCI bridge resources from leaf bridge, so we can allocate
+ * a larger window later.
  */
 static void pci_bus_release_bridge_resources(struct pci_bus *bus,
                                             unsigned long type,
@@ -1596,7 +1591,7 @@ static void pci_bus_dump_res(struct pci_bus *bus)
                if (!res || !res->end || !res->flags)
                        continue;
 
-               dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res);
+               dev_info(&bus->dev, "resource %d %pR\n", i, res);
        }
 }
 
@@ -1678,7 +1673,7 @@ static int iov_resources_unassigned(struct pci_dev *dev, void *data)
                pcibios_resource_to_bus(dev->bus, &region, r);
                if (!region.start) {
                        *unassigned = true;
-                       return 1; /* return early from pci_walk_bus() */
+                       return 1; /* Return early from pci_walk_bus() */
                }
        }
 
@@ -1686,7 +1681,7 @@ static int iov_resources_unassigned(struct pci_dev *dev, void *data)
 }
 
 static enum enable_type pci_realloc_detect(struct pci_bus *bus,
-                        enum enable_type enable_local)
+                                          enum enable_type enable_local)
 {
        bool unassigned = false;
 
@@ -1701,21 +1696,21 @@ static enum enable_type pci_realloc_detect(struct pci_bus *bus,
 }
 #else
 static enum enable_type pci_realloc_detect(struct pci_bus *bus,
-                        enum enable_type enable_local)
+                                          enum enable_type enable_local)
 {
        return enable_local;
 }
 #endif
 
 /*
- * first try will not touch pci bridge res
- * second and later try will clear small leaf bridge res
- * will stop till to the max depth if can not find good one
+ * First try will not touch PCI bridge res.
+ * Second and later try will clear small leaf bridge res.
+ * Will stop till to the max depth if can not find good one.
  */
 void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
 {
-       LIST_HEAD(realloc_head); /* list of resources that
-                                       want additional resources */
+       LIST_HEAD(realloc_head);
+       /* List of resources that want additional resources */
        struct list_head *add_list = NULL;
        int tried_times = 0;
        enum release_type rel_type = leaf_only;
@@ -1724,26 +1719,26 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
        int pci_try_num = 1;
        enum enable_type enable_local;
 
-       /* don't realloc if asked to do so */
+       /* Don't realloc if asked to do so */
        enable_local = pci_realloc_detect(bus, pci_realloc_enable);
        if (pci_realloc_enabled(enable_local)) {
                int max_depth = pci_bus_get_depth(bus);
 
                pci_try_num = max_depth + 1;
-               dev_printk(KERN_DEBUG, &bus->dev,
-                          "max bus depth: %d pci_try_num: %d\n",
-                          max_depth, pci_try_num);
+               dev_info(&bus->dev, "max bus depth: %d pci_try_num: %d\n",
+                        max_depth, pci_try_num);
        }
 
 again:
        /*
-        * last try will use add_list, otherwise will try good to have as
-        * must have, so can realloc parent bridge resource
+        * Last try will use add_list, otherwise will try good to have as must
+        * have, so can realloc parent bridge resource
         */
        if (tried_times + 1 == pci_try_num)
                add_list = &realloc_head;
-       /* Depth first, calculate sizes and alignments of all
-          subordinate buses. */
+       /*
+        * Depth first, calculate sizes and alignments of all subordinate buses.
+        */
        __pci_bus_size_bridges(bus, add_list);
 
        /* Depth last, allocate resources and update the hardware. */
@@ -1752,7 +1747,7 @@ again:
                BUG_ON(!list_empty(add_list));
        tried_times++;
 
-       /* any device complain? */
+       /* Any device complain? */
        if (list_empty(&fail_head))
                goto dump;
 
@@ -1766,23 +1761,23 @@ again:
                goto dump;
        }
 
-       dev_printk(KERN_DEBUG, &bus->dev,
-                  "No. %d try to assign unassigned res\n", tried_times + 1);
+       dev_info(&bus->dev, "No. %d try to assign unassigned res\n",
+                tried_times + 1);
 
-       /* third times and later will not check if it is leaf */
+       /* Third times and later will not check if it is leaf */
        if ((tried_times + 1) > 2)
                rel_type = whole_subtree;
 
        /*
         * Try to release leaf bridge's resources that doesn't fit resource of
-        * child device under that bridge
+        * child device under that bridge.
         */
        list_for_each_entry(fail_res, &fail_head, list)
                pci_bus_release_bridge_resources(fail_res->dev->bus,
                                                 fail_res->flags & PCI_RES_TYPE_MASK,
                                                 rel_type);
 
-       /* restore size and flags */
+       /* Restore size and flags */
        list_for_each_entry(fail_res, &fail_head, list) {
                struct resource *res = fail_res->res;
 
@@ -1797,7 +1792,7 @@ again:
        goto again;
 
 dump:
-       /* dump the resource on buses */
+       /* Dump the resource on buses */
        pci_bus_dump_resources(bus);
 }
 
@@ -1808,14 +1803,15 @@ void __init pci_assign_unassigned_resources(void)
        list_for_each_entry(root_bus, &pci_root_buses, node) {
                pci_assign_unassigned_root_bus_resources(root_bus);
 
-               /* Make sure the root bridge has a companion ACPI device: */
+               /* Make sure the root bridge has a companion ACPI device */
                if (ACPI_HANDLE(root_bus->bridge))
                        acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge));
        }
 }
 
 static void extend_bridge_window(struct pci_dev *bridge, struct resource *res,
-                       struct list_head *add_list, resource_size_t available)
+                                struct list_head *add_list,
+                                resource_size_t available)
 {
        struct pci_dev_resource *dev_res;
 
@@ -1839,8 +1835,10 @@ static void extend_bridge_window(struct pci_dev *bridge, struct resource *res,
 }
 
 static void pci_bus_distribute_available_resources(struct pci_bus *bus,
-       struct list_head *add_list, resource_size_t available_io,
-       resource_size_t available_mmio, resource_size_t available_mmio_pref)
+                                           struct list_head *add_list,
+                                           resource_size_t available_io,
+                                           resource_size_t available_mmio,
+                                           resource_size_t available_mmio_pref)
 {
        resource_size_t remaining_io, remaining_mmio, remaining_mmio_pref;
        unsigned int normal_bridges = 0, hotplug_bridges = 0;
@@ -1864,7 +1862,7 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
 
        /*
         * Calculate the total amount of extra resource space we can
-        * pass to bridges below this one. This is basically the
+        * pass to bridges below this one.  This is basically the
         * extra space reduced by the minimal required space for the
         * non-hotplug bridges.
         */
@@ -1874,7 +1872,7 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
 
        /*
         * Calculate how many hotplug bridges and normal bridges there
-        * are on this bus. We will distribute the additional available
+        * are on this bus.  We will distribute the additional available
         * resources between hotplug bridges.
         */
        for_each_pci_bridge(dev, bus) {
@@ -1909,8 +1907,8 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
 
        /*
         * There is only one bridge on the bus so it gets all available
-        * resources which it can then distribute to the possible
-        * hotplug bridges below.
+        * resources which it can then distribute to the possible hotplug
+        * bridges below.
         */
        if (hotplug_bridges + normal_bridges == 1) {
                dev = list_first_entry(&bus->devices, struct pci_dev, bus_list);
@@ -1961,9 +1959,8 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
        }
 }
 
-static void
-pci_bridge_distribute_available_resources(struct pci_dev *bridge,
-                                         struct list_head *add_list)
+static void pci_bridge_distribute_available_resources(struct pci_dev *bridge,
+                                                    struct list_head *add_list)
 {
        resource_size_t available_io, available_mmio, available_mmio_pref;
        const struct resource *res;
@@ -1980,14 +1977,17 @@ pci_bridge_distribute_available_resources(struct pci_dev *bridge,
        available_mmio_pref = resource_size(res);
 
        pci_bus_distribute_available_resources(bridge->subordinate,
-               add_list, available_io, available_mmio, available_mmio_pref);
+                                              add_list, available_io,
+                                              available_mmio,
+                                              available_mmio_pref);
 }
 
 void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
 {
        struct pci_bus *parent = bridge->subordinate;
-       LIST_HEAD(add_list); /* list of resources that
-                                       want additional resources */
+       /* List of resources that want additional resources */
+       LIST_HEAD(add_list);
+
        int tried_times = 0;
        LIST_HEAD(fail_head);
        struct pci_dev_resource *fail_res;
@@ -1997,9 +1997,9 @@ again:
        __pci_bus_size_bridges(parent, &add_list);
 
        /*
-        * Distribute remaining resources (if any) equally between
-        * hotplug bridges below. This makes it possible to extend the
-        * hierarchy later without running out of resources.
+        * Distribute remaining resources (if any) equally between hotplug
+        * bridges below.  This makes it possible to extend the hierarchy
+        * later without running out of resources.
         */
        pci_bridge_distribute_available_resources(bridge, &add_list);
 
@@ -2011,7 +2011,7 @@ again:
                goto enable_all;
 
        if (tried_times >= 2) {
-               /* still fail, don't need to try more */
+               /* Still fail, don't need to try more */
                free_list(&fail_head);
                goto enable_all;
        }
@@ -2020,15 +2020,15 @@ again:
                         tried_times + 1);
 
        /*
-        * Try to release leaf bridge's resources that doesn't fit resource of
-        * child device under that bridge
+        * Try to release leaf bridge's resources that aren't big enough
+        * to contain child device resources.
         */
        list_for_each_entry(fail_res, &fail_head, list)
                pci_bus_release_bridge_resources(fail_res->dev->bus,
                                                 fail_res->flags & PCI_RES_TYPE_MASK,
                                                 whole_subtree);
 
-       /* restore size and flags */
+       /* Restore size and flags */
        list_for_each_entry(fail_res, &fail_head, list) {
                struct resource *res = fail_res->res;
 
@@ -2107,7 +2107,7 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
        }
 
        list_for_each_entry(dev_res, &saved, list) {
-               /* Skip the bridge we just assigned resources for. */
+               /* Skip the bridge we just assigned resources for */
                if (bridge == dev_res->dev)
                        continue;
 
@@ -2119,7 +2119,7 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
        return 0;
 
 cleanup:
-       /* restore size and flags */
+       /* Restore size and flags */
        list_for_each_entry(dev_res, &failed, list) {
                struct resource *res = dev_res->res;
 
@@ -2151,8 +2151,8 @@ cleanup:
 void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
 {
        struct pci_dev *dev;
-       LIST_HEAD(add_list); /* list of resources that
-                                       want additional resources */
+       /* List of resources that want additional resources */
+       LIST_HEAD(add_list);
 
        down_read(&pci_bus_sem);
        for_each_pci_bridge(dev, bus)
index c46d5e1..f4d92b1 100644 (file)
@@ -403,7 +403,7 @@ static int pci_slot_init(void)
        pci_slots_kset = kset_create_and_add("slots", NULL,
                                                &pci_bus_kset->kobj);
        if (!pci_slots_kset) {
-               printk(KERN_ERR "PCI: Slot initialization failure\n");
+               pr_err("PCI: Slot initialization failure\n");
                return -ENOMEM;
        }
        return 0;
index 0f7b801..bebbde4 100644 (file)
@@ -658,19 +658,25 @@ static int ioctl_flash_part_info(struct switchtec_dev *stdev,
 
 static int ioctl_event_summary(struct switchtec_dev *stdev,
        struct switchtec_user *stuser,
-       struct switchtec_ioctl_event_summary __user *usum)
+       struct switchtec_ioctl_event_summary __user *usum,
+       size_t size)
 {
-       struct switchtec_ioctl_event_summary s = {0};
+       struct switchtec_ioctl_event_summary *s;
        int i;
        u32 reg;
+       int ret = 0;
 
-       s.global = ioread32(&stdev->mmio_sw_event->global_summary);
-       s.part_bitmap = ioread32(&stdev->mmio_sw_event->part_event_bitmap);
-       s.local_part = ioread32(&stdev->mmio_part_cfg->part_event_summary);
+       s = kzalloc(sizeof(*s), GFP_KERNEL);
+       if (!s)
+               return -ENOMEM;
+
+       s->global = ioread32(&stdev->mmio_sw_event->global_summary);
+       s->part_bitmap = ioread32(&stdev->mmio_sw_event->part_event_bitmap);
+       s->local_part = ioread32(&stdev->mmio_part_cfg->part_event_summary);
 
        for (i = 0; i < stdev->partition_count; i++) {
                reg = ioread32(&stdev->mmio_part_cfg_all[i].part_event_summary);
-               s.part[i] = reg;
+               s->part[i] = reg;
        }
 
        for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++) {
@@ -679,15 +685,19 @@ static int ioctl_event_summary(struct switchtec_dev *stdev,
                        break;
 
                reg = ioread32(&stdev->mmio_pff_csr[i].pff_event_summary);
-               s.pff[i] = reg;
+               s->pff[i] = reg;
        }
 
-       if (copy_to_user(usum, &s, sizeof(s)))
-               return -EFAULT;
+       if (copy_to_user(usum, s, size)) {
+               ret = -EFAULT;
+               goto error_case;
+       }
 
        stuser->event_cnt = atomic_read(&stdev->event_cnt);
 
-       return 0;
+error_case:
+       kfree(s);
+       return ret;
 }
 
 static u32 __iomem *global_ev_reg(struct switchtec_dev *stdev,
@@ -977,8 +987,9 @@ static long switchtec_dev_ioctl(struct file *filp, unsigned int cmd,
        case SWITCHTEC_IOCTL_FLASH_PART_INFO:
                rc = ioctl_flash_part_info(stdev, argp);
                break;
-       case SWITCHTEC_IOCTL_EVENT_SUMMARY:
-               rc = ioctl_event_summary(stdev, stuser, argp);
+       case SWITCHTEC_IOCTL_EVENT_SUMMARY_LEGACY:
+               rc = ioctl_event_summary(stdev, stuser, argp,
+                                        sizeof(struct switchtec_ioctl_event_summary_legacy));
                break;
        case SWITCHTEC_IOCTL_EVENT_CTL:
                rc = ioctl_event_ctl(stdev, argp);
@@ -989,6 +1000,10 @@ static long switchtec_dev_ioctl(struct file *filp, unsigned int cmd,
        case SWITCHTEC_IOCTL_PORT_TO_PFF:
                rc = ioctl_port_to_pff(stdev, argp);
                break;
+       case SWITCHTEC_IOCTL_EVENT_SUMMARY:
+               rc = ioctl_event_summary(stdev, stuser, argp,
+                                        sizeof(struct switchtec_ioctl_event_summary));
+               break;
        default:
                rc = -ENOTTY;
                break;
@@ -1162,7 +1177,8 @@ static int mask_event(struct switchtec_dev *stdev, int eid, int idx)
        if (!(hdr & SWITCHTEC_EVENT_OCCURRED && hdr & SWITCHTEC_EVENT_EN_IRQ))
                return 0;
 
-       if (eid == SWITCHTEC_IOCTL_EVENT_LINK_STATE)
+       if (eid == SWITCHTEC_IOCTL_EVENT_LINK_STATE ||
+           eid == SWITCHTEC_IOCTL_EVENT_MRPC_COMP)
                return 0;
 
        dev_dbg(&stdev->dev, "%s: %d %d %x\n", __func__, eid, idx, hdr);
index eba6e33..d1b16cf 100644 (file)
@@ -291,8 +291,7 @@ static int pci_frontend_enable_msix(struct pci_dev *dev,
                                vector[i] = op.msix_entries[i].vector;
                        }
                } else {
-                       printk(KERN_DEBUG "enable msix get value %x\n",
-                               op.value);
+                       pr_info("enable msix get value %x\n", op.value);
                        err = op.value;
                }
        } else {
@@ -364,12 +363,12 @@ static void pci_frontend_disable_msi(struct pci_dev *dev)
        err = do_pci_op(pdev, &op);
        if (err == XEN_PCI_ERR_dev_not_found) {
                /* XXX No response from backend, what shall we do? */
-               printk(KERN_DEBUG "get no response from backend for disable MSI\n");
+               pr_info("get no response from backend for disable MSI\n");
                return;
        }
        if (err)
                /* how can pciback notify us fail? */
-               printk(KERN_DEBUG "get fake response frombackend\n");
+               pr_info("get fake response from backend\n");
 }
 
 static struct xen_pci_frontend_ops pci_frontend_ops = {
@@ -1104,7 +1103,7 @@ static void __ref pcifront_backend_changed(struct xenbus_device *xdev,
        case XenbusStateClosed:
                if (xdev->state == XenbusStateClosed)
                        break;
-               /* Missed the backend's CLOSING state -- fallthrough */
+               /* fall through - Missed the backend's CLOSING state. */
        case XenbusStateClosing:
                dev_warn(&xdev->dev, "backend going away!\n");
                pcifront_try_disconnect(pdev);
index c2a17a7..267fb87 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <mach/hardware.h>
 #include <asm/io.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <mach/mux.h>
 #include <mach/tc.h>
index 19d8af9..ea79854 100644 (file)
@@ -273,6 +273,20 @@ config PINCTRL_ST
        select PINCONF
        select GPIOLIB_IRQCHIP
 
+config PINCTRL_STMFX
+       tristate "STMicroelectronics STMFX GPIO expander pinctrl driver"
+       depends on I2C
+       depends on OF || COMPILE_TEST
+       select GENERIC_PINCONF
+       select GPIOLIB_IRQCHIP
+       select MFD_STMFX
+       help
+         Driver for STMicroelectronics Multi-Function eXpander (STMFX)
+         GPIO expander.
+         This provides a GPIO interface supporting inputs and outputs,
+         and configuring push-pull, open-drain, and can also be used as
+         interrupt-controller.
+
 config PINCTRL_U300
        bool "U300 pin controller driver"
        depends on ARCH_U300
index 62df406..ac537fd 100644 (file)
@@ -41,6 +41,7 @@ obj-$(CONFIG_PINCTRL_LANTIQ)  += pinctrl-lantiq.o
 obj-$(CONFIG_PINCTRL_LPC18XX)  += pinctrl-lpc18xx.o
 obj-$(CONFIG_PINCTRL_TB10X)    += pinctrl-tb10x.o
 obj-$(CONFIG_PINCTRL_ST)       += pinctrl-st.o
+obj-$(CONFIG_PINCTRL_STMFX)    += pinctrl-stmfx.o
 obj-$(CONFIG_PINCTRL_ZYNQ)     += pinctrl-zynq.o
 obj-$(CONFIG_PINCTRL_INGENIC)  += pinctrl-ingenic.o
 obj-$(CONFIG_PINCTRL_RK805)    += pinctrl-rk805.o
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
new file mode 100644 (file)
index 0000000..eba872c
--- /dev/null
@@ -0,0 +1,819 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for STMicroelectronics Multi-Function eXpander (STMFX) GPIO expander
+ *
+ * Copyright (C) 2019 STMicroelectronics
+ * Author(s): Amelie Delaunay <amelie.delaunay@st.com>.
+ */
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/stmfx.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "core.h"
+#include "pinctrl-utils.h"
+
+/* GPIOs expander */
+/* GPIO_STATE1 0x10, GPIO_STATE2 0x11, GPIO_STATE3 0x12 */
+#define STMFX_REG_GPIO_STATE           STMFX_REG_GPIO_STATE1 /* R */
+/* GPIO_DIR1 0x60, GPIO_DIR2 0x61, GPIO_DIR3 0x63 */
+#define STMFX_REG_GPIO_DIR             STMFX_REG_GPIO_DIR1 /* RW */
+/* GPIO_TYPE1 0x64, GPIO_TYPE2 0x65, GPIO_TYPE3 0x66 */
+#define STMFX_REG_GPIO_TYPE            STMFX_REG_GPIO_TYPE1 /* RW */
+/* GPIO_PUPD1 0x68, GPIO_PUPD2 0x69, GPIO_PUPD3 0x6A */
+#define STMFX_REG_GPIO_PUPD            STMFX_REG_GPIO_PUPD1 /* RW */
+/* GPO_SET1 0x6C, GPO_SET2 0x6D, GPO_SET3 0x6E */
+#define STMFX_REG_GPO_SET              STMFX_REG_GPO_SET1 /* RW */
+/* GPO_CLR1 0x70, GPO_CLR2 0x71, GPO_CLR3 0x72 */
+#define STMFX_REG_GPO_CLR              STMFX_REG_GPO_CLR1 /* RW */
+/* IRQ_GPI_SRC1 0x48, IRQ_GPI_SRC2 0x49, IRQ_GPI_SRC3 0x4A */
+#define STMFX_REG_IRQ_GPI_SRC          STMFX_REG_IRQ_GPI_SRC1 /* RW */
+/* IRQ_GPI_EVT1 0x4C, IRQ_GPI_EVT2 0x4D, IRQ_GPI_EVT3 0x4E */
+#define STMFX_REG_IRQ_GPI_EVT          STMFX_REG_IRQ_GPI_EVT1 /* RW */
+/* IRQ_GPI_TYPE1 0x50, IRQ_GPI_TYPE2 0x51, IRQ_GPI_TYPE3 0x52 */
+#define STMFX_REG_IRQ_GPI_TYPE         STMFX_REG_IRQ_GPI_TYPE1 /* RW */
+/* IRQ_GPI_PENDING1 0x0C, IRQ_GPI_PENDING2 0x0D, IRQ_GPI_PENDING3 0x0E*/
+#define STMFX_REG_IRQ_GPI_PENDING      STMFX_REG_IRQ_GPI_PENDING1 /* R */
+/* IRQ_GPI_ACK1 0x54, IRQ_GPI_ACK2 0x55, IRQ_GPI_ACK3 0x56 */
+#define STMFX_REG_IRQ_GPI_ACK          STMFX_REG_IRQ_GPI_ACK1 /* RW */
+
+#define NR_GPIO_REGS                   3
+#define NR_GPIOS_PER_REG               8
+#define get_reg(offset)                        ((offset) / NR_GPIOS_PER_REG)
+#define get_shift(offset)              ((offset) % NR_GPIOS_PER_REG)
+#define get_mask(offset)               (BIT(get_shift(offset)))
+
+/*
+ * STMFX pinctrl can have up to 24 pins if STMFX other functions are not used.
+ * Pins availability is managed thanks to gpio-ranges property.
+ */
+static const struct pinctrl_pin_desc stmfx_pins[] = {
+       PINCTRL_PIN(0, "gpio0"),
+       PINCTRL_PIN(1, "gpio1"),
+       PINCTRL_PIN(2, "gpio2"),
+       PINCTRL_PIN(3, "gpio3"),
+       PINCTRL_PIN(4, "gpio4"),
+       PINCTRL_PIN(5, "gpio5"),
+       PINCTRL_PIN(6, "gpio6"),
+       PINCTRL_PIN(7, "gpio7"),
+       PINCTRL_PIN(8, "gpio8"),
+       PINCTRL_PIN(9, "gpio9"),
+       PINCTRL_PIN(10, "gpio10"),
+       PINCTRL_PIN(11, "gpio11"),
+       PINCTRL_PIN(12, "gpio12"),
+       PINCTRL_PIN(13, "gpio13"),
+       PINCTRL_PIN(14, "gpio14"),
+       PINCTRL_PIN(15, "gpio15"),
+       PINCTRL_PIN(16, "agpio0"),
+       PINCTRL_PIN(17, "agpio1"),
+       PINCTRL_PIN(18, "agpio2"),
+       PINCTRL_PIN(19, "agpio3"),
+       PINCTRL_PIN(20, "agpio4"),
+       PINCTRL_PIN(21, "agpio5"),
+       PINCTRL_PIN(22, "agpio6"),
+       PINCTRL_PIN(23, "agpio7"),
+};
+
+struct stmfx_pinctrl {
+       struct device *dev;
+       struct stmfx *stmfx;
+       struct pinctrl_dev *pctl_dev;
+       struct pinctrl_desc pctl_desc;
+       struct gpio_chip gpio_chip;
+       struct irq_chip irq_chip;
+       struct mutex lock; /* IRQ bus lock */
+       unsigned long gpio_valid_mask;
+       /* Cache of IRQ_GPI_* registers for bus_lock */
+       u8 irq_gpi_src[NR_GPIO_REGS];
+       u8 irq_gpi_type[NR_GPIO_REGS];
+       u8 irq_gpi_evt[NR_GPIO_REGS];
+       u8 irq_toggle_edge[NR_GPIO_REGS];
+#ifdef CONFIG_PM
+       /* Backup of GPIO_* registers for suspend/resume */
+       u8 bkp_gpio_state[NR_GPIO_REGS];
+       u8 bkp_gpio_dir[NR_GPIO_REGS];
+       u8 bkp_gpio_type[NR_GPIO_REGS];
+       u8 bkp_gpio_pupd[NR_GPIO_REGS];
+#endif
+};
+
+static int stmfx_gpio_get(struct gpio_chip *gc, unsigned int offset)
+{
+       struct stmfx_pinctrl *pctl = gpiochip_get_data(gc);
+       u32 reg = STMFX_REG_GPIO_STATE + get_reg(offset);
+       u32 mask = get_mask(offset);
+       u32 value;
+       int ret;
+
+       ret = regmap_read(pctl->stmfx->map, reg, &value);
+
+       return ret ? ret : !!(value & mask);
+}
+
+static void stmfx_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
+{
+       struct stmfx_pinctrl *pctl = gpiochip_get_data(gc);
+       u32 reg = value ? STMFX_REG_GPO_SET : STMFX_REG_GPO_CLR;
+       u32 mask = get_mask(offset);
+
+       regmap_write_bits(pctl->stmfx->map, reg + get_reg(offset),
+                         mask, mask);
+}
+
+static int stmfx_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+       struct stmfx_pinctrl *pctl = gpiochip_get_data(gc);
+       u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset);
+       u32 mask = get_mask(offset);
+       u32 val;
+       int ret;
+
+       ret = regmap_read(pctl->stmfx->map, reg, &val);
+       /*
+        * On stmfx, gpio pins direction is (0)input, (1)output.
+        * .get_direction returns 0=out, 1=in
+        */
+
+       return ret ? ret : !(val & mask);
+}
+
+static int stmfx_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
+{
+       struct stmfx_pinctrl *pctl = gpiochip_get_data(gc);
+       u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset);
+       u32 mask = get_mask(offset);
+
+       return regmap_write_bits(pctl->stmfx->map, reg, mask, 0);
+}
+
+static int stmfx_gpio_direction_output(struct gpio_chip *gc,
+                                      unsigned int offset, int value)
+{
+       struct stmfx_pinctrl *pctl = gpiochip_get_data(gc);
+       u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset);
+       u32 mask = get_mask(offset);
+
+       stmfx_gpio_set(gc, offset, value);
+
+       return regmap_write_bits(pctl->stmfx->map, reg, mask, mask);
+}
+
+static int stmfx_pinconf_get_pupd(struct stmfx_pinctrl *pctl,
+                                 unsigned int offset)
+{
+       u32 reg = STMFX_REG_GPIO_PUPD + get_reg(offset);
+       u32 pupd, mask = get_mask(offset);
+       int ret;
+
+       ret = regmap_read(pctl->stmfx->map, reg, &pupd);
+       if (ret)
+               return ret;
+
+       return !!(pupd & mask);
+}
+
+static int stmfx_pinconf_set_pupd(struct stmfx_pinctrl *pctl,
+                                 unsigned int offset, u32 pupd)
+{
+       u32 reg = STMFX_REG_GPIO_PUPD + get_reg(offset);
+       u32 mask = get_mask(offset);
+
+       return regmap_write_bits(pctl->stmfx->map, reg, mask, pupd ? mask : 0);
+}
+
+static int stmfx_pinconf_get_type(struct stmfx_pinctrl *pctl,
+                                 unsigned int offset)
+{
+       u32 reg = STMFX_REG_GPIO_TYPE + get_reg(offset);
+       u32 type, mask = get_mask(offset);
+       int ret;
+
+       ret = regmap_read(pctl->stmfx->map, reg, &type);
+       if (ret)
+               return ret;
+
+       return !!(type & mask);
+}
+
+static int stmfx_pinconf_set_type(struct stmfx_pinctrl *pctl,
+                                 unsigned int offset, u32 type)
+{
+       u32 reg = STMFX_REG_GPIO_TYPE + get_reg(offset);
+       u32 mask = get_mask(offset);
+
+       return regmap_write_bits(pctl->stmfx->map, reg, mask, type ? mask : 0);
+}
+
+static int stmfx_pinconf_get(struct pinctrl_dev *pctldev,
+                            unsigned int pin, unsigned long *config)
+{
+       struct stmfx_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       u32 param = pinconf_to_config_param(*config);
+       struct pinctrl_gpio_range *range;
+       u32 arg = 0;
+       int ret, dir, type, pupd;
+
+       range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin);
+       if (!range)
+               return -EINVAL;
+
+       dir = stmfx_gpio_get_direction(&pctl->gpio_chip, pin);
+       if (dir < 0)
+               return dir;
+       type = stmfx_pinconf_get_type(pctl, pin);
+       if (type < 0)
+               return type;
+       pupd = stmfx_pinconf_get_pupd(pctl, pin);
+       if (pupd < 0)
+               return pupd;
+
+       switch (param) {
+       case PIN_CONFIG_BIAS_DISABLE:
+               if ((!dir && (!type || !pupd)) || (dir && !type))
+                       arg = 1;
+               break;
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               if (dir && type && !pupd)
+                       arg = 1;
+               break;
+       case PIN_CONFIG_BIAS_PULL_UP:
+               if (type && pupd)
+                       arg = 1;
+               break;
+       case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+               if ((!dir && type) || (dir && !type))
+                       arg = 1;
+               break;
+       case PIN_CONFIG_DRIVE_PUSH_PULL:
+               if ((!dir && !type) || (dir && type))
+                       arg = 1;
+               break;
+       case PIN_CONFIG_OUTPUT:
+               if (dir)
+                       return -EINVAL;
+
+               ret = stmfx_gpio_get(&pctl->gpio_chip, pin);
+               if (ret < 0)
+                       return ret;
+
+               arg = ret;
+               break;
+       default:
+               return -ENOTSUPP;
+       }
+
+       *config = pinconf_to_config_packed(param, arg);
+
+       return 0;
+}
+
+static int stmfx_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+                            unsigned long *configs, unsigned int num_configs)
+{
+       struct stmfx_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct pinctrl_gpio_range *range;
+       enum pin_config_param param;
+       u32 arg;
+       int dir, i, ret;
+
+       range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin);
+       if (!range) {
+               dev_err(pctldev->dev, "pin %d is not available\n", pin);
+               return -EINVAL;
+       }
+
+       dir = stmfx_gpio_get_direction(&pctl->gpio_chip, pin);
+       if (dir < 0)
+               return dir;
+
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
+               arg = pinconf_to_config_argument(configs[i]);
+
+               switch (param) {
+               case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+               case PIN_CONFIG_BIAS_DISABLE:
+               case PIN_CONFIG_BIAS_PULL_DOWN:
+                       ret = stmfx_pinconf_set_pupd(pctl, pin, 0);
+                       if (ret)
+                               return ret;
+                       break;
+               case PIN_CONFIG_BIAS_PULL_UP:
+                       ret = stmfx_pinconf_set_pupd(pctl, pin, 1);
+                       if (ret)
+                               return ret;
+                       break;
+               case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+                       if (!dir)
+                               ret = stmfx_pinconf_set_type(pctl, pin, 1);
+                       else
+                               ret = stmfx_pinconf_set_type(pctl, pin, 0);
+                       if (ret)
+                               return ret;
+                       break;
+               case PIN_CONFIG_DRIVE_PUSH_PULL:
+                       if (!dir)
+                               ret = stmfx_pinconf_set_type(pctl, pin, 0);
+                       else
+                               ret = stmfx_pinconf_set_type(pctl, pin, 1);
+                       if (ret)
+                               return ret;
+                       break;
+               case PIN_CONFIG_OUTPUT:
+                       ret = stmfx_gpio_direction_output(&pctl->gpio_chip,
+                                                         pin, arg);
+                       if (ret)
+                               return ret;
+                       break;
+               default:
+                       return -ENOTSUPP;
+               }
+       }
+
+       return 0;
+}
+
+static void stmfx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+                                  struct seq_file *s, unsigned int offset)
+{
+       struct stmfx_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct pinctrl_gpio_range *range;
+       int dir, type, pupd, val;
+
+       range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, offset);
+       if (!range)
+               return;
+
+       dir = stmfx_gpio_get_direction(&pctl->gpio_chip, offset);
+       if (dir < 0)
+               return;
+       type = stmfx_pinconf_get_type(pctl, offset);
+       if (type < 0)
+               return;
+       pupd = stmfx_pinconf_get_pupd(pctl, offset);
+       if (pupd < 0)
+               return;
+       val = stmfx_gpio_get(&pctl->gpio_chip, offset);
+       if (val < 0)
+               return;
+
+       if (!dir) {
+               seq_printf(s, "output %s ", val ? "high" : "low");
+               if (type)
+                       seq_printf(s, "open drain %s internal pull-up ",
+                                  pupd ? "with" : "without");
+               else
+                       seq_puts(s, "push pull no pull ");
+       } else {
+               seq_printf(s, "input %s ", val ? "high" : "low");
+               if (type)
+                       seq_printf(s, "with internal pull-%s ",
+                                  pupd ? "up" : "down");
+               else
+                       seq_printf(s, "%s ", pupd ? "floating" : "analog");
+       }
+}
+
+static const struct pinconf_ops stmfx_pinconf_ops = {
+       .pin_config_get         = stmfx_pinconf_get,
+       .pin_config_set         = stmfx_pinconf_set,
+       .pin_config_dbg_show    = stmfx_pinconf_dbg_show,
+};
+
+static int stmfx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       return 0;
+}
+
+static const char *stmfx_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+                                               unsigned int selector)
+{
+       return NULL;
+}
+
+static int stmfx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+                                       unsigned int selector,
+                                       const unsigned int **pins,
+                                       unsigned int *num_pins)
+{
+       return -ENOTSUPP;
+}
+
+static const struct pinctrl_ops stmfx_pinctrl_ops = {
+       .get_groups_count = stmfx_pinctrl_get_groups_count,
+       .get_group_name = stmfx_pinctrl_get_group_name,
+       .get_group_pins = stmfx_pinctrl_get_group_pins,
+       .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+       .dt_free_map = pinctrl_utils_free_map,
+};
+
+static void stmfx_pinctrl_irq_mask(struct irq_data *data)
+{
+       struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data);
+       struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip);
+       u32 reg = get_reg(data->hwirq);
+       u32 mask = get_mask(data->hwirq);
+
+       pctl->irq_gpi_src[reg] &= ~mask;
+}
+
+static void stmfx_pinctrl_irq_unmask(struct irq_data *data)
+{
+       struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data);
+       struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip);
+       u32 reg = get_reg(data->hwirq);
+       u32 mask = get_mask(data->hwirq);
+
+       pctl->irq_gpi_src[reg] |= mask;
+}
+
+static int stmfx_pinctrl_irq_set_type(struct irq_data *data, unsigned int type)
+{
+       struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data);
+       struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip);
+       u32 reg = get_reg(data->hwirq);
+       u32 mask = get_mask(data->hwirq);
+
+       if (type == IRQ_TYPE_NONE)
+               return -EINVAL;
+
+       if (type & IRQ_TYPE_EDGE_BOTH) {
+               pctl->irq_gpi_evt[reg] |= mask;
+               irq_set_handler_locked(data, handle_edge_irq);
+       } else {
+               pctl->irq_gpi_evt[reg] &= ~mask;
+               irq_set_handler_locked(data, handle_level_irq);
+       }
+
+       if ((type & IRQ_TYPE_EDGE_RISING) || (type & IRQ_TYPE_LEVEL_HIGH))
+               pctl->irq_gpi_type[reg] |= mask;
+       else
+               pctl->irq_gpi_type[reg] &= ~mask;
+
+       /*
+        * In case of (type & IRQ_TYPE_EDGE_BOTH), we need to know current
+        * GPIO value to set the right edge trigger. But in atomic context
+        * here we can't access registers over I2C. That's why (type &
+        * IRQ_TYPE_EDGE_BOTH) will be managed in .irq_sync_unlock.
+        */
+
+       if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+               pctl->irq_toggle_edge[reg] |= mask;
+       else
+               pctl->irq_toggle_edge[reg] &= mask;
+
+       return 0;
+}
+
+static void stmfx_pinctrl_irq_bus_lock(struct irq_data *data)
+{
+       struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data);
+       struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip);
+
+       mutex_lock(&pctl->lock);
+}
+
+static void stmfx_pinctrl_irq_bus_sync_unlock(struct irq_data *data)
+{
+       struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(data);
+       struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip);
+       u32 reg = get_reg(data->hwirq);
+       u32 mask = get_mask(data->hwirq);
+
+       /*
+        * In case of IRQ_TYPE_EDGE_BOTH), read the current GPIO value
+        * (this couldn't be done in .irq_set_type because of atomic context)
+        * to set the right irq trigger type.
+        */
+       if (pctl->irq_toggle_edge[reg] & mask) {
+               if (stmfx_gpio_get(gpio_chip, data->hwirq))
+                       pctl->irq_gpi_type[reg] &= ~mask;
+               else
+                       pctl->irq_gpi_type[reg] |= mask;
+       }
+
+       regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_EVT,
+                         pctl->irq_gpi_evt, NR_GPIO_REGS);
+       regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_TYPE,
+                         pctl->irq_gpi_type, NR_GPIO_REGS);
+       regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC,
+                         pctl->irq_gpi_src, NR_GPIO_REGS);
+
+       mutex_unlock(&pctl->lock);
+}
+
+static void stmfx_pinctrl_irq_toggle_trigger(struct stmfx_pinctrl *pctl,
+                                            unsigned int offset)
+{
+       u32 reg = get_reg(offset);
+       u32 mask = get_mask(offset);
+       int val;
+
+       if (!(pctl->irq_toggle_edge[reg] & mask))
+               return;
+
+       val = stmfx_gpio_get(&pctl->gpio_chip, offset);
+       if (val < 0)
+               return;
+
+       if (val) {
+               pctl->irq_gpi_type[reg] &= mask;
+               regmap_write_bits(pctl->stmfx->map,
+                                 STMFX_REG_IRQ_GPI_TYPE + reg,
+                                 mask, 0);
+
+       } else {
+               pctl->irq_gpi_type[reg] |= mask;
+               regmap_write_bits(pctl->stmfx->map,
+                                 STMFX_REG_IRQ_GPI_TYPE + reg,
+                                 mask, mask);
+       }
+}
+
+static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id)
+{
+       struct stmfx_pinctrl *pctl = (struct stmfx_pinctrl *)dev_id;
+       struct gpio_chip *gc = &pctl->gpio_chip;
+       u8 pending[NR_GPIO_REGS];
+       u8 src[NR_GPIO_REGS] = {0, 0, 0};
+       unsigned long n, status;
+       int ret;
+
+       ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_IRQ_GPI_PENDING,
+                              &pending, NR_GPIO_REGS);
+       if (ret)
+               return IRQ_NONE;
+
+       regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC,
+                         src, NR_GPIO_REGS);
+
+       status = *(unsigned long *)pending;
+       for_each_set_bit(n, &status, gc->ngpio) {
+               handle_nested_irq(irq_find_mapping(gc->irq.domain, n));
+               stmfx_pinctrl_irq_toggle_trigger(pctl, n);
+       }
+
+       regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC,
+                         pctl->irq_gpi_src, NR_GPIO_REGS);
+
+       return IRQ_HANDLED;
+}
+
+static int stmfx_pinctrl_gpio_function_enable(struct stmfx_pinctrl *pctl)
+{
+       struct pinctrl_gpio_range *gpio_range;
+       struct pinctrl_dev *pctl_dev = pctl->pctl_dev;
+       u32 func = STMFX_FUNC_GPIO;
+
+       pctl->gpio_valid_mask = GENMASK(15, 0);
+
+       gpio_range = pinctrl_find_gpio_range_from_pin(pctl_dev, 16);
+       if (gpio_range) {
+               func |= STMFX_FUNC_ALTGPIO_LOW;
+               pctl->gpio_valid_mask |= GENMASK(19, 16);
+       }
+
+       gpio_range = pinctrl_find_gpio_range_from_pin(pctl_dev, 20);
+       if (gpio_range) {
+               func |= STMFX_FUNC_ALTGPIO_HIGH;
+               pctl->gpio_valid_mask |= GENMASK(23, 20);
+       }
+
+       return stmfx_function_enable(pctl->stmfx, func);
+}
+
+static int stmfx_pinctrl_probe(struct platform_device *pdev)
+{
+       struct stmfx *stmfx = dev_get_drvdata(pdev->dev.parent);
+       struct device_node *np = pdev->dev.of_node;
+       struct stmfx_pinctrl *pctl;
+       u32 n;
+       int irq, ret;
+
+       pctl = devm_kzalloc(stmfx->dev, sizeof(*pctl), GFP_KERNEL);
+       if (!pctl)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, pctl);
+
+       pctl->dev = &pdev->dev;
+       pctl->stmfx = stmfx;
+
+       if (!of_find_property(np, "gpio-ranges", NULL)) {
+               dev_err(pctl->dev, "missing required gpio-ranges property\n");
+               return -EINVAL;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq <= 0) {
+               dev_err(pctl->dev, "failed to get irq\n");
+               return -ENXIO;
+       }
+
+       mutex_init(&pctl->lock);
+
+       /* Register pin controller */
+       pctl->pctl_desc.name = "stmfx-pinctrl";
+       pctl->pctl_desc.pctlops = &stmfx_pinctrl_ops;
+       pctl->pctl_desc.confops = &stmfx_pinconf_ops;
+       pctl->pctl_desc.pins = stmfx_pins;
+       pctl->pctl_desc.npins = ARRAY_SIZE(stmfx_pins);
+       pctl->pctl_desc.owner = THIS_MODULE;
+
+       ret = devm_pinctrl_register_and_init(pctl->dev, &pctl->pctl_desc,
+                                            pctl, &pctl->pctl_dev);
+       if (ret) {
+               dev_err(pctl->dev, "pinctrl registration failed\n");
+               return ret;
+       }
+
+       ret = pinctrl_enable(pctl->pctl_dev);
+       if (ret) {
+               dev_err(pctl->dev, "pinctrl enable failed\n");
+               return ret;
+       }
+
+       /* Register gpio controller */
+       pctl->gpio_chip.label = "stmfx-gpio";
+       pctl->gpio_chip.parent = pctl->dev;
+       pctl->gpio_chip.get_direction = stmfx_gpio_get_direction;
+       pctl->gpio_chip.direction_input = stmfx_gpio_direction_input;
+       pctl->gpio_chip.direction_output = stmfx_gpio_direction_output;
+       pctl->gpio_chip.get = stmfx_gpio_get;
+       pctl->gpio_chip.set = stmfx_gpio_set;
+       pctl->gpio_chip.set_config = gpiochip_generic_config;
+       pctl->gpio_chip.base = -1;
+       pctl->gpio_chip.ngpio = pctl->pctl_desc.npins;
+       pctl->gpio_chip.can_sleep = true;
+       pctl->gpio_chip.of_node = np;
+       pctl->gpio_chip.need_valid_mask = true;
+
+       ret = devm_gpiochip_add_data(pctl->dev, &pctl->gpio_chip, pctl);
+       if (ret) {
+               dev_err(pctl->dev, "gpio_chip registration failed\n");
+               return ret;
+       }
+
+       ret = stmfx_pinctrl_gpio_function_enable(pctl);
+       if (ret)
+               return ret;
+
+       pctl->irq_chip.name = dev_name(pctl->dev);
+       pctl->irq_chip.irq_mask = stmfx_pinctrl_irq_mask;
+       pctl->irq_chip.irq_unmask = stmfx_pinctrl_irq_unmask;
+       pctl->irq_chip.irq_set_type = stmfx_pinctrl_irq_set_type;
+       pctl->irq_chip.irq_bus_lock = stmfx_pinctrl_irq_bus_lock;
+       pctl->irq_chip.irq_bus_sync_unlock = stmfx_pinctrl_irq_bus_sync_unlock;
+       for_each_clear_bit(n, &pctl->gpio_valid_mask, pctl->gpio_chip.ngpio)
+               clear_bit(n, pctl->gpio_chip.valid_mask);
+
+       ret = gpiochip_irqchip_add_nested(&pctl->gpio_chip, &pctl->irq_chip,
+                                         0, handle_bad_irq, IRQ_TYPE_NONE);
+       if (ret) {
+               dev_err(pctl->dev, "cannot add irqchip to gpiochip\n");
+               return ret;
+       }
+
+       ret = devm_request_threaded_irq(pctl->dev, irq, NULL,
+                                       stmfx_pinctrl_irq_thread_fn,
+                                       IRQF_ONESHOT,
+                                       pctl->irq_chip.name, pctl);
+       if (ret) {
+               dev_err(pctl->dev, "cannot request irq%d\n", irq);
+               return ret;
+       }
+
+       gpiochip_set_nested_irqchip(&pctl->gpio_chip, &pctl->irq_chip, irq);
+
+       dev_info(pctl->dev,
+                "%ld GPIOs available\n", hweight_long(pctl->gpio_valid_mask));
+
+       return 0;
+}
+
+static int stmfx_pinctrl_remove(struct platform_device *pdev)
+{
+       struct stmfx *stmfx = dev_get_platdata(&pdev->dev);
+
+       return stmfx_function_disable(stmfx,
+                                     STMFX_FUNC_GPIO |
+                                     STMFX_FUNC_ALTGPIO_LOW |
+                                     STMFX_FUNC_ALTGPIO_HIGH);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int stmfx_pinctrl_backup_regs(struct stmfx_pinctrl *pctl)
+{
+       int ret;
+
+       ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_GPIO_STATE,
+                              &pctl->bkp_gpio_state, NR_GPIO_REGS);
+       if (ret)
+               return ret;
+       ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_GPIO_DIR,
+                              &pctl->bkp_gpio_dir, NR_GPIO_REGS);
+       if (ret)
+               return ret;
+       ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_GPIO_TYPE,
+                              &pctl->bkp_gpio_type, NR_GPIO_REGS);
+       if (ret)
+               return ret;
+       ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_GPIO_PUPD,
+                              &pctl->bkp_gpio_pupd, NR_GPIO_REGS);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int stmfx_pinctrl_restore_regs(struct stmfx_pinctrl *pctl)
+{
+       int ret;
+
+       ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_GPIO_DIR,
+                               pctl->bkp_gpio_dir, NR_GPIO_REGS);
+       if (ret)
+               return ret;
+       ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_GPIO_TYPE,
+                               pctl->bkp_gpio_type, NR_GPIO_REGS);
+       if (ret)
+               return ret;
+       ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_GPIO_PUPD,
+                               pctl->bkp_gpio_pupd, NR_GPIO_REGS);
+       if (ret)
+               return ret;
+       ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_GPO_SET,
+                               pctl->bkp_gpio_state, NR_GPIO_REGS);
+       if (ret)
+               return ret;
+       ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_EVT,
+                               pctl->irq_gpi_evt, NR_GPIO_REGS);
+       if (ret)
+               return ret;
+       ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_TYPE,
+                               pctl->irq_gpi_type, NR_GPIO_REGS);
+       if (ret)
+               return ret;
+       ret = regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC,
+                               pctl->irq_gpi_src, NR_GPIO_REGS);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int stmfx_pinctrl_suspend(struct device *dev)
+{
+       struct stmfx_pinctrl *pctl = dev_get_drvdata(dev);
+       int ret;
+
+       ret = stmfx_pinctrl_backup_regs(pctl);
+       if (ret) {
+               dev_err(pctl->dev, "registers backup failure\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int stmfx_pinctrl_resume(struct device *dev)
+{
+       struct stmfx_pinctrl *pctl = dev_get_drvdata(dev);
+       int ret;
+
+       ret = stmfx_pinctrl_restore_regs(pctl);
+       if (ret) {
+               dev_err(pctl->dev, "registers restoration failure\n");
+               return ret;
+       }
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(stmfx_pinctrl_dev_pm_ops,
+                        stmfx_pinctrl_suspend, stmfx_pinctrl_resume);
+
+static const struct of_device_id stmfx_pinctrl_of_match[] = {
+       { .compatible = "st,stmfx-0300-pinctrl", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, stmfx_pinctrl_of_match);
+
+static struct platform_driver stmfx_pinctrl_driver = {
+       .driver = {
+               .name = "stmfx-pinctrl",
+               .of_match_table = stmfx_pinctrl_of_match,
+               .pm = &stmfx_pinctrl_dev_pm_ops,
+       },
+       .probe = stmfx_pinctrl_probe,
+       .remove = stmfx_pinctrl_remove,
+};
+module_platform_driver(stmfx_pinctrl_driver);
+
+MODULE_DESCRIPTION("STMFX pinctrl/GPIO driver");
+MODULE_AUTHOR("Amelie Delaunay <amelie.delaunay@st.com>");
+MODULE_LICENSE("GPL v2");
index 24326ee..7abbb61 100644 (file)
@@ -125,7 +125,7 @@ static bool chromeos_laptop_match_adapter_devid(struct device *dev, u32 devid)
                return false;
 
        pdev = to_pci_dev(dev);
-       return devid == PCI_DEVID(pdev->bus->number, pdev->devfn);
+       return devid == pci_dev_id(pdev);
 }
 
 static void chromeos_laptop_check_adapter(struct i2c_adapter *adapter)
index 1714758..3d23251 100644 (file)
@@ -429,6 +429,12 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev)
        else
                ec_dev->mkbp_event_supported = 1;
 
+       /* Probe if host sleep v1 is supported for S0ix failure detection. */
+       ret = cros_ec_get_host_command_version_mask(ec_dev,
+                                                   EC_CMD_HOST_SLEEP_EVENT,
+                                                   &ver_mask);
+       ec_dev->host_sleep_v1 = (ret >= 0 && (ver_mask & EC_VER_MASK(1)));
+
        /*
         * Get host event wake mask, assume all events are wake events
         * if unavailable.
index 321bc67..cef0133 100644 (file)
@@ -274,7 +274,8 @@ static int pin_user_pages(unsigned long first_page,
                *iter_last_page_size = last_page_size;
        }
 
-       ret = get_user_pages_fast(first_page, requested_pages, !is_write,
+       ret = get_user_pages_fast(first_page, requested_pages,
+                                 !is_write ? FOLL_WRITE : 0,
                                  pages);
        if (ret <= 0)
                return -EFAULT;
index 2b686c5..e341cc5 100644 (file)
 
 #define SHDW_WK_PIN(reg, cfg)  ((reg) & AT91_SHDW_WKUPIS((cfg)->wkup_pin_input))
 #define SHDW_RTCWK(reg, cfg)   (((reg) >> ((cfg)->sr_rtcwk_shift)) & 0x1)
+#define SHDW_RTTWK(reg, cfg)   (((reg) >> ((cfg)->sr_rttwk_shift)) & 0x1)
 #define SHDW_RTCWKEN(cfg)      (1 << ((cfg)->mr_rtcwk_shift))
+#define SHDW_RTTWKEN(cfg)      (1 << ((cfg)->mr_rttwk_shift))
 
 #define DBC_PERIOD_US(x)       DIV_ROUND_UP_ULL((1000000 * (x)), \
                                                        SLOW_CLOCK_FREQ)
 
+#define SHDW_CFG_NOT_USED      (32)
+
 struct shdwc_config {
        u8 wkup_pin_input;
        u8 mr_rtcwk_shift;
+       u8 mr_rttwk_shift;
        u8 sr_rtcwk_shift;
+       u8 sr_rttwk_shift;
 };
 
 struct shdwc {
@@ -104,6 +110,8 @@ static void __init at91_wakeup_status(struct platform_device *pdev)
                reason = "WKUP pin";
        else if (SHDW_RTCWK(reg, shdw->cfg))
                reason = "RTC";
+       else if (SHDW_RTTWK(reg, shdw->cfg))
+               reason = "RTT";
 
        pr_info("AT91: Wake-Up source: %s\n", reason);
 }
@@ -221,6 +229,9 @@ static void at91_shdwc_dt_configure(struct platform_device *pdev)
        if (of_property_read_bool(np, "atmel,wakeup-rtc-timer"))
                mode |= SHDW_RTCWKEN(shdw->cfg);
 
+       if (of_property_read_bool(np, "atmel,wakeup-rtt-timer"))
+               mode |= SHDW_RTTWKEN(shdw->cfg);
+
        dev_dbg(&pdev->dev, "%s: mode = %#x\n", __func__, mode);
        writel(mode, shdw->shdwc_base + AT91_SHDW_MR);
 
@@ -231,13 +242,27 @@ static void at91_shdwc_dt_configure(struct platform_device *pdev)
 static const struct shdwc_config sama5d2_shdwc_config = {
        .wkup_pin_input = 0,
        .mr_rtcwk_shift = 17,
+       .mr_rttwk_shift = SHDW_CFG_NOT_USED,
        .sr_rtcwk_shift = 5,
+       .sr_rttwk_shift = SHDW_CFG_NOT_USED,
+};
+
+static const struct shdwc_config sam9x60_shdwc_config = {
+       .wkup_pin_input = 0,
+       .mr_rtcwk_shift = 17,
+       .mr_rttwk_shift = 16,
+       .sr_rtcwk_shift = 5,
+       .sr_rttwk_shift = 4,
 };
 
 static const struct of_device_id at91_shdwc_of_match[] = {
        {
                .compatible = "atmel,sama5d2-shdwc",
                .data = &sama5d2_shdwc_config,
+       },
+       {
+               .compatible = "microchip,sam9x60-shdwc",
+               .data = &sam9x60_shdwc_config,
        }, {
                /*sentinel*/
        }
index 7d0d269..5a6bb63 100644 (file)
@@ -27,6 +27,7 @@
 struct syscon_reboot_context {
        struct regmap *map;
        u32 offset;
+       u32 value;
        u32 mask;
        struct notifier_block restart_handler;
 };
@@ -39,7 +40,7 @@ static int syscon_restart_handle(struct notifier_block *this,
                                        restart_handler);
 
        /* Issue the reboot */
-       regmap_write(ctx->map, ctx->offset, ctx->mask);
+       regmap_update_bits(ctx->map, ctx->offset, ctx->mask, ctx->value);
 
        mdelay(1000);
 
@@ -51,6 +52,7 @@ static int syscon_reboot_probe(struct platform_device *pdev)
 {
        struct syscon_reboot_context *ctx;
        struct device *dev = &pdev->dev;
+       int mask_err, value_err;
        int err;
 
        ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
@@ -64,8 +66,21 @@ static int syscon_reboot_probe(struct platform_device *pdev)
        if (of_property_read_u32(pdev->dev.of_node, "offset", &ctx->offset))
                return -EINVAL;
 
-       if (of_property_read_u32(pdev->dev.of_node, "mask", &ctx->mask))
+       value_err = of_property_read_u32(pdev->dev.of_node, "value", &ctx->value);
+       mask_err = of_property_read_u32(pdev->dev.of_node, "mask", &ctx->mask);
+       if (value_err && mask_err) {
+               dev_err(dev, "unable to read 'value' and 'mask'");
                return -EINVAL;
+       }
+
+       if (value_err) {
+               /* support old binding */
+               ctx->value = ctx->mask;
+               ctx->mask = 0xFFFFFFFF;
+       } else if (mask_err) {
+               /* support value without mask*/
+               ctx->mask = 0xFFFFFFFF;
+       }
 
        ctx->restart_handler.notifier_call = syscon_restart_handle;
        ctx->restart_handler.priority = 192;
index e901b98..26dacda 100644 (file)
@@ -169,6 +169,17 @@ config BATTERY_COLLIE
          Say Y to enable support for the battery on the Sharp Zaurus
          SL-5500 (collie) models.
 
+config BATTERY_INGENIC
+       tristate "Ingenic JZ47xx SoCs battery driver"
+       depends on MIPS || COMPILE_TEST
+       depends on INGENIC_ADC
+       help
+         Choose this option if you want to monitor battery status on
+         Ingenic JZ47xx SoC based devices.
+
+         This driver can also be built as a module. If so, the module will be
+         called ingenic-battery.
+
 config BATTERY_IPAQ_MICRO
        tristate "iPAQ Atmel Micro ASIC battery driver"
        depends on MFD_IPAQ_MICRO
@@ -475,12 +486,12 @@ config CHARGER_MANAGER
           runtime and in suspend-to-RAM by waking up the system periodically
           with help of suspend_again support.
 
-config CHARGER_LTC3651
-       tristate "LTC3651 charger"
+config CHARGER_LT3651
+       tristate "Analog Devices LT3651 charger"
        depends on GPIOLIB
        help
-         Say Y to include support for the LTC3651 battery charger which reports
-         its status via GPIO lines.
+         Say Y to include support for the Analog Devices (Linear Technology)
+         LT3651 battery charger which reports its status via GPIO lines.
 
 config CHARGER_MAX14577
        tristate "Maxim MAX14577/77836 battery charger driver"
@@ -499,6 +510,13 @@ config CHARGER_DETECTOR_MAX14656
          Revision 1.2 and can be found e.g. in Kindle 4/5th generation
          readers and certain LG devices.
 
+config CHARGER_MAX77650
+       tristate "Maxim MAX77650 battery charger driver"
+       depends on MFD_MAX77650
+       help
+         Say Y to enable support for the battery charger control of MAX77650
+         PMICs.
+
 config CHARGER_MAX77693
        tristate "Maxim MAX77693 battery charger driver"
        depends on MFD_MAX77693
@@ -660,4 +678,14 @@ config FUEL_GAUGE_SC27XX
         Say Y here to enable support for fuel gauge with SC27XX
         PMIC chips.
 
+config CHARGER_UCS1002
+       tristate "Microchip UCS1002 USB Port Power Controller"
+       depends on I2C
+       depends on OF
+       depends on REGULATOR
+       select REGMAP_I2C
+       help
+         Say Y to enable support for Microchip UCS1002 Programmable
+         USB Port Power Controller with Charger Emulation.
+
 endif # POWER_SUPPLY
index b731c2a..f208273 100644 (file)
@@ -34,6 +34,7 @@ obj-$(CONFIG_BATTERY_PMU)     += pmu_battery.o
 obj-$(CONFIG_BATTERY_OLPC)     += olpc_battery.o
 obj-$(CONFIG_BATTERY_TOSA)     += tosa_battery.o
 obj-$(CONFIG_BATTERY_COLLIE)   += collie_battery.o
+obj-$(CONFIG_BATTERY_INGENIC)  += ingenic-battery.o
 obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
 obj-$(CONFIG_BATTERY_WM97XX)   += wm97xx_battery.o
 obj-$(CONFIG_BATTERY_SBS)      += sbs-battery.o
@@ -67,9 +68,10 @@ obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o
 obj-$(CONFIG_CHARGER_LP8788)   += lp8788-charger.o
 obj-$(CONFIG_CHARGER_GPIO)     += gpio-charger.o
 obj-$(CONFIG_CHARGER_MANAGER)  += charger-manager.o
-obj-$(CONFIG_CHARGER_LTC3651)  += ltc3651-charger.o
+obj-$(CONFIG_CHARGER_LT3651)   += lt3651-charger.o
 obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o
 obj-$(CONFIG_CHARGER_DETECTOR_MAX14656)        += max14656_charger_detector.o
+obj-$(CONFIG_CHARGER_MAX77650) += max77650-charger.o
 obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o
 obj-$(CONFIG_CHARGER_MAX8997)  += max8997_charger.o
 obj-$(CONFIG_CHARGER_MAX8998)  += max8998_charger.o
@@ -87,3 +89,4 @@ obj-$(CONFIG_AXP288_CHARGER)  += axp288_charger.o
 obj-$(CONFIG_CHARGER_CROS_USBPD)       += cros_usbpd-charger.o
 obj-$(CONFIG_CHARGER_SC2731)   += sc2731_charger.o
 obj-$(CONFIG_FUEL_GAUGE_SC27XX)        += sc27xx_fuel_gauge.o
+obj-$(CONFIG_CHARGER_UCS1002)  += ucs1002_power.o
index 7b2b699..f6a6697 100644 (file)
@@ -508,6 +508,7 @@ int ab8500_bm_of_probe(struct device *dev,
        btech = of_get_property(battery_node, "stericsson,battery-type", NULL);
        if (!btech) {
                dev_warn(dev, "missing property battery-name/type\n");
+               of_node_put(battery_node);
                return -EINVAL;
        }
 
index f52fe77..d2b1255 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/iio/consumer.h>
+#include <linux/workqueue.h>
 
 #define DRVNAME "axp20x-usb-power-supply"
 
 #define AXP20X_VBUS_VHOLD_MASK         GENMASK(5, 3)
 #define AXP20X_VBUS_VHOLD_OFFSET       3
 #define AXP20X_VBUS_CLIMIT_MASK                3
-#define AXP20X_VBUC_CLIMIT_900mA       0
-#define AXP20X_VBUC_CLIMIT_500mA       1
-#define AXP20X_VBUC_CLIMIT_100mA       2
-#define AXP20X_VBUC_CLIMIT_NONE                3
+#define AXP20X_VBUS_CLIMIT_900mA       0
+#define AXP20X_VBUS_CLIMIT_500mA       1
+#define AXP20X_VBUS_CLIMIT_100mA       2
+#define AXP20X_VBUS_CLIMIT_NONE                3
+
+#define AXP813_VBUS_CLIMIT_900mA       0
+#define AXP813_VBUS_CLIMIT_1500mA      1
+#define AXP813_VBUS_CLIMIT_2000mA      2
+#define AXP813_VBUS_CLIMIT_2500mA      3
 
 #define AXP20X_ADC_EN1_VBUS_CURR       BIT(2)
 #define AXP20X_ADC_EN1_VBUS_VOLT       BIT(3)
 
 #define AXP20X_VBUS_MON_VBUS_VALID     BIT(3)
 
+/*
+ * Note do not raise the debounce time, we must report Vusb high within
+ * 100ms otherwise we get Vbus errors in musb.
+ */
+#define DEBOUNCE_TIME                  msecs_to_jiffies(50)
+
 struct axp20x_usb_power {
        struct device_node *np;
        struct regmap *regmap;
@@ -53,6 +65,8 @@ struct axp20x_usb_power {
        enum axp20x_variants axp20x_id;
        struct iio_channel *vbus_v;
        struct iio_channel *vbus_i;
+       struct delayed_work vbus_detect;
+       unsigned int old_status;
 };
 
 static irqreturn_t axp20x_usb_power_irq(int irq, void *devid)
@@ -64,6 +78,89 @@ static irqreturn_t axp20x_usb_power_irq(int irq, void *devid)
        return IRQ_HANDLED;
 }
 
+static void axp20x_usb_power_poll_vbus(struct work_struct *work)
+{
+       struct axp20x_usb_power *power =
+               container_of(work, struct axp20x_usb_power, vbus_detect.work);
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &val);
+       if (ret)
+               goto out;
+
+       val &= (AXP20X_PWR_STATUS_VBUS_PRESENT | AXP20X_PWR_STATUS_VBUS_USED);
+       if (val != power->old_status)
+               power_supply_changed(power->supply);
+
+       power->old_status = val;
+
+out:
+       mod_delayed_work(system_wq, &power->vbus_detect, DEBOUNCE_TIME);
+}
+
+static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power)
+{
+       if (power->axp20x_id >= AXP221_ID)
+               return true;
+
+       return false;
+}
+
+static int axp20x_get_current_max(struct axp20x_usb_power *power, int *val)
+{
+       unsigned int v;
+       int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
+
+       if (ret)
+               return ret;
+
+       switch (v & AXP20X_VBUS_CLIMIT_MASK) {
+       case AXP20X_VBUS_CLIMIT_100mA:
+               if (power->axp20x_id == AXP221_ID)
+                       *val = -1; /* No 100mA limit */
+               else
+                       *val = 100000;
+               break;
+       case AXP20X_VBUS_CLIMIT_500mA:
+               *val = 500000;
+               break;
+       case AXP20X_VBUS_CLIMIT_900mA:
+               *val = 900000;
+               break;
+       case AXP20X_VBUS_CLIMIT_NONE:
+               *val = -1;
+               break;
+       }
+
+       return 0;
+}
+
+static int axp813_get_current_max(struct axp20x_usb_power *power, int *val)
+{
+       unsigned int v;
+       int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
+
+       if (ret)
+               return ret;
+
+       switch (v & AXP20X_VBUS_CLIMIT_MASK) {
+       case AXP813_VBUS_CLIMIT_900mA:
+               *val = 900000;
+               break;
+       case AXP813_VBUS_CLIMIT_1500mA:
+               *val = 1500000;
+               break;
+       case AXP813_VBUS_CLIMIT_2000mA:
+               *val = 2000000;
+               break;
+       case AXP813_VBUS_CLIMIT_2500mA:
+               *val = 2500000;
+               break;
+       }
+       return 0;
+}
+
 static int axp20x_usb_power_get_property(struct power_supply *psy,
        enum power_supply_property psp, union power_supply_propval *val)
 {
@@ -102,28 +199,9 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
                val->intval = ret * 1700; /* 1 step = 1.7 mV */
                return 0;
        case POWER_SUPPLY_PROP_CURRENT_MAX:
-               ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
-               if (ret)
-                       return ret;
-
-               switch (v & AXP20X_VBUS_CLIMIT_MASK) {
-               case AXP20X_VBUC_CLIMIT_100mA:
-                       if (power->axp20x_id == AXP221_ID)
-                               val->intval = -1; /* No 100mA limit */
-                       else
-                               val->intval = 100000;
-                       break;
-               case AXP20X_VBUC_CLIMIT_500mA:
-                       val->intval = 500000;
-                       break;
-               case AXP20X_VBUC_CLIMIT_900mA:
-                       val->intval = 900000;
-                       break;
-               case AXP20X_VBUC_CLIMIT_NONE:
-                       val->intval = -1;
-                       break;
-               }
-               return 0;
+               if (power->axp20x_id == AXP813_ID)
+                       return axp813_get_current_max(power, &val->intval);
+               return axp20x_get_current_max(power, &val->intval);
        case POWER_SUPPLY_PROP_CURRENT_NOW:
                if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
                        ret = iio_read_channel_processed(power->vbus_i,
@@ -214,6 +292,31 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
        return -EINVAL;
 }
 
+static int axp813_usb_power_set_current_max(struct axp20x_usb_power *power,
+                                           int intval)
+{
+       int val;
+
+       switch (intval) {
+       case 900000:
+               return regmap_update_bits(power->regmap,
+                                         AXP20X_VBUS_IPSOUT_MGMT,
+                                         AXP20X_VBUS_CLIMIT_MASK,
+                                         AXP813_VBUS_CLIMIT_900mA);
+       case 1500000:
+       case 2000000:
+       case 2500000:
+               val = (intval - 1000000) / 500000;
+               return regmap_update_bits(power->regmap,
+                                         AXP20X_VBUS_IPSOUT_MGMT,
+                                         AXP20X_VBUS_CLIMIT_MASK, val);
+       default:
+               return -EINVAL;
+       }
+
+       return -EINVAL;
+}
+
 static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power,
                                            int intval)
 {
@@ -248,6 +351,9 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
                return axp20x_usb_power_set_voltage_min(power, val->intval);
 
        case POWER_SUPPLY_PROP_CURRENT_MAX:
+               if (power->axp20x_id == AXP813_ID)
+                       return axp813_usb_power_set_current_max(power,
+                                                               val->intval);
                return axp20x_usb_power_set_current_max(power, val->intval);
 
        default:
@@ -357,6 +463,7 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
        if (!power)
                return -ENOMEM;
 
+       platform_set_drvdata(pdev, power);
        power->axp20x_id = (enum axp20x_variants)of_device_get_match_data(
                                                                &pdev->dev);
 
@@ -382,7 +489,8 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
                usb_power_desc = &axp20x_usb_power_desc;
                irq_names = axp20x_irq_names;
        } else if (power->axp20x_id == AXP221_ID ||
-                  power->axp20x_id == AXP223_ID) {
+                  power->axp20x_id == AXP223_ID ||
+                  power->axp20x_id == AXP813_ID) {
                usb_power_desc = &axp22x_usb_power_desc;
                irq_names = axp22x_irq_names;
        } else {
@@ -415,6 +523,19 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
                                 irq_names[i], ret);
        }
 
+       INIT_DELAYED_WORK(&power->vbus_detect, axp20x_usb_power_poll_vbus);
+       if (axp20x_usb_vbus_needs_polling(power))
+               queue_delayed_work(system_wq, &power->vbus_detect, 0);
+
+       return 0;
+}
+
+static int axp20x_usb_power_remove(struct platform_device *pdev)
+{
+       struct axp20x_usb_power *power = platform_get_drvdata(pdev);
+
+       cancel_delayed_work_sync(&power->vbus_detect);
+
        return 0;
 }
 
@@ -428,12 +549,16 @@ static const struct of_device_id axp20x_usb_power_match[] = {
        }, {
                .compatible = "x-powers,axp223-usb-power-supply",
                .data = (void *)AXP223_ID,
+       }, {
+               .compatible = "x-powers,axp813-usb-power-supply",
+               .data = (void *)AXP813_ID,
        }, { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, axp20x_usb_power_match);
 
 static struct platform_driver axp20x_usb_power_driver = {
        .probe = axp20x_usb_power_probe,
+       .remove = axp20x_usb_power_remove,
        .driver = {
                .name = DRVNAME,
                .of_match_table = axp20x_usb_power_match,
index f8c6da9..00b9618 100644 (file)
@@ -833,6 +833,10 @@ static int axp288_charger_probe(struct platform_device *pdev)
        /* Register charger interrupts */
        for (i = 0; i < CHRG_INTR_END; i++) {
                pirq = platform_get_irq(info->pdev, i);
+               if (pirq < 0) {
+                       dev_err(&pdev->dev, "Failed to get IRQ: %d\n", pirq);
+                       return pirq;
+               }
                info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq);
                if (info->irq[i] < 0) {
                        dev_warn(&info->pdev->dev,
index 9ff2461..368281b 100644 (file)
@@ -685,6 +685,26 @@ intr_failed:
  * detection reports one despite it not being there.
  */
 static const struct dmi_system_id axp288_fuel_gauge_blacklist[] = {
+       {
+               /* ACEPC T8 Cherry Trail Z8350 mini PC */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."),
+                       DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "T8"),
+                       /* also match on somewhat unique bios-version */
+                       DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1.000"),
+               },
+       },
+       {
+               /* ACEPC T11 Cherry Trail Z8350 mini PC */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."),
+                       DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "T11"),
+                       /* also match on somewhat unique bios-version */
+                       DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1.000"),
+               },
+       },
        {
                /* Intel Cherry Trail Compute Stick, Windows version */
                .matches = {
index 29b3a40..195c18c 100644 (file)
@@ -1612,7 +1612,8 @@ void bq27xxx_battery_update(struct bq27xxx_device_info *di)
                        di->charge_design_full = bq27xxx_battery_read_dcap(di);
        }
 
-       if (di->cache.capacity != cache.capacity)
+       if ((di->cache.capacity != cache.capacity) ||
+           (di->cache.flags != cache.flags))
                power_supply_changed(di->bat);
 
        if (memcmp(&di->cache, &cache, sizeof(cache)) != 0)
index 2e8db5e..a6900aa 100644 (file)
@@ -1987,6 +1987,9 @@ static struct platform_driver charger_manager_driver = {
 static int __init charger_manager_init(void)
 {
        cm_wq = create_freezable_workqueue("charger_manager");
+       if (unlikely(!cm_wq))
+               return -ENOMEM;
+
        INIT_DELAYED_WORK(&cm_monitor_work, cm_monitor_poller);
 
        return platform_driver_register(&charger_manager_driver);
index 6887870..61d6447 100644 (file)
@@ -82,9 +82,9 @@ struct cpcap_battery_config {
 };
 
 struct cpcap_coulomb_counter_data {
-       s32 sample;             /* 24-bits */
+       s32 sample;             /* 24 or 32 bits */
        s32 accumulator;
-       s16 offset;             /* 10-bits */
+       s16 offset;             /* bits */
 };
 
 enum cpcap_battery_state {
@@ -213,7 +213,7 @@ static int cpcap_battery_get_current(struct cpcap_battery_ddata *ddata)
  * TI or ST coulomb counter in the PMIC.
  */
 static int cpcap_battery_cc_raw_div(struct cpcap_battery_ddata *ddata,
-                                   u32 sample, s32 accumulator,
+                                   s32 sample, s32 accumulator,
                                    s16 offset, u32 divider)
 {
        s64 acc;
@@ -224,9 +224,6 @@ static int cpcap_battery_cc_raw_div(struct cpcap_battery_ddata *ddata,
        if (!divider)
                return 0;
 
-       sample &= 0xffffff;             /* 24-bits, unsigned */
-       offset &= 0x7ff;                /* 10-bits, signed */
-
        switch (ddata->vendor) {
        case CPCAP_VENDOR_ST:
                cc_lsb = 95374;         /* μAms per LSB */
@@ -259,7 +256,7 @@ static int cpcap_battery_cc_raw_div(struct cpcap_battery_ddata *ddata,
 
 /* 3600000μAms = 1μAh */
 static int cpcap_battery_cc_to_uah(struct cpcap_battery_ddata *ddata,
-                                  u32 sample, s32 accumulator,
+                                  s32 sample, s32 accumulator,
                                   s16 offset)
 {
        return cpcap_battery_cc_raw_div(ddata, sample,
@@ -268,7 +265,7 @@ static int cpcap_battery_cc_to_uah(struct cpcap_battery_ddata *ddata,
 }
 
 static int cpcap_battery_cc_to_ua(struct cpcap_battery_ddata *ddata,
-                                 u32 sample, s32 accumulator,
+                                 s32 sample, s32 accumulator,
                                  s16 offset)
 {
        return cpcap_battery_cc_raw_div(ddata, sample,
@@ -312,17 +309,19 @@ cpcap_battery_read_accumulated(struct cpcap_battery_ddata *ddata,
        /* Sample value CPCAP_REG_CCS1 & 2 */
        ccd->sample = (buf[1] & 0x0fff) << 16;
        ccd->sample |= buf[0];
+       if (ddata->vendor == CPCAP_VENDOR_TI)
+               ccd->sample = sign_extend32(24, ccd->sample);
 
        /* Accumulator value CPCAP_REG_CCA1 & 2 */
        ccd->accumulator = ((s16)buf[3]) << 16;
        ccd->accumulator |= buf[2];
 
-       /* Offset value CPCAP_REG_CCO */
-       ccd->offset = buf[5];
-
-       /* Adjust offset based on mode value CPCAP_REG_CCM? */
-       if (buf[4] >= 0x200)
-               ccd->offset |= 0xfc00;
+       /*
+        * Coulomb counter calibration offset is CPCAP_REG_CCM,
+        * REG_CCO seems unused
+        */
+       ccd->offset = buf[4];
+       ccd->offset = sign_extend32(ccd->offset, 9);
 
        return cpcap_battery_cc_to_uah(ddata,
                                       ccd->sample,
@@ -477,11 +476,11 @@ static int cpcap_battery_get_property(struct power_supply *psy,
                val->intval = ddata->config.info.voltage_min_design;
                break;
        case POWER_SUPPLY_PROP_CURRENT_AVG:
-               if (cached) {
+               sample = latest->cc.sample - previous->cc.sample;
+               if (!sample) {
                        val->intval = cpcap_battery_cc_get_avg_current(ddata);
                        break;
                }
-               sample = latest->cc.sample - previous->cc.sample;
                accumulator = latest->cc.accumulator - previous->cc.accumulator;
                val->intval = cpcap_battery_cc_to_ua(ddata, sample,
                                                     accumulator,
@@ -498,13 +497,13 @@ static int cpcap_battery_get_property(struct power_supply *psy,
                val->intval = div64_s64(tmp, 100);
                break;
        case POWER_SUPPLY_PROP_POWER_AVG:
-               if (cached) {
+               sample = latest->cc.sample - previous->cc.sample;
+               if (!sample) {
                        tmp = cpcap_battery_cc_get_avg_current(ddata);
                        tmp *= (latest->voltage / 10000);
                        val->intval = div64_s64(tmp, 100);
                        break;
                }
-               sample = latest->cc.sample - previous->cc.sample;
                accumulator = latest->cc.accumulator - previous->cc.accumulator;
                tmp = cpcap_battery_cc_to_ua(ddata, sample, accumulator,
                                             latest->cc.offset);
@@ -562,11 +561,11 @@ static irqreturn_t cpcap_battery_irq_thread(int irq, void *data)
 
        switch (d->action) {
        case CPCAP_BATTERY_IRQ_ACTION_BATTERY_LOW:
-               if (latest->counter_uah >= 0)
+               if (latest->current_ua >= 0)
                        dev_warn(ddata->dev, "Battery low at 3.3V!\n");
                break;
        case CPCAP_BATTERY_IRQ_ACTION_POWEROFF:
-               if (latest->counter_uah >= 0) {
+               if (latest->current_ua >= 0) {
                        dev_emerg(ddata->dev,
                                  "Battery empty at 3.1V, powering off\n");
                        orderly_poweroff(true);
@@ -670,8 +669,9 @@ static int cpcap_battery_init_iio(struct cpcap_battery_ddata *ddata)
        return 0;
 
 out_err:
-       dev_err(ddata->dev, "could not initialize VBUS or ID IIO: %i\n",
-               error);
+       if (error != -EPROBE_DEFER)
+               dev_err(ddata->dev, "could not initialize VBUS or ID IIO: %i\n",
+                       error);
 
        return error;
 }
index c3ed7b4..b4781b5 100644 (file)
@@ -574,8 +574,9 @@ static int cpcap_charger_init_iio(struct cpcap_charger_ddata *ddata)
        return 0;
 
 out_err:
-       dev_err(ddata->dev, "could not initialize VBUS or ID IIO: %i\n",
-               error);
+       if (error != -EPROBE_DEFER)
+               dev_err(ddata->dev, "could not initialize VBUS or ID IIO: %i\n",
+                       error);
 
        return error;
 }
index 7e4f11d..f99e8f1 100644 (file)
 
 struct gpio_charger {
        unsigned int irq;
+       unsigned int charge_status_irq;
        bool wakeup_enabled;
 
        struct power_supply *charger;
        struct power_supply_desc charger_desc;
        struct gpio_desc *gpiod;
+       struct gpio_desc *charge_status;
 };
 
 static irqreturn_t gpio_charger_irq(int irq, void *devid)
@@ -59,6 +61,12 @@ static int gpio_charger_get_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_ONLINE:
                val->intval = gpiod_get_value_cansleep(gpio_charger->gpiod);
                break;
+       case POWER_SUPPLY_PROP_STATUS:
+               if (gpiod_get_value_cansleep(gpio_charger->charge_status))
+                       val->intval = POWER_SUPPLY_STATUS_CHARGING;
+               else
+                       val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               break;
        default:
                return -EINVAL;
        }
@@ -93,8 +101,29 @@ static enum power_supply_type gpio_charger_get_type(struct device *dev)
        return POWER_SUPPLY_TYPE_UNKNOWN;
 }
 
+static int gpio_charger_get_irq(struct device *dev, void *dev_id,
+                               struct gpio_desc *gpio)
+{
+       int ret, irq = gpiod_to_irq(gpio);
+
+       if (irq > 0) {
+               ret = devm_request_any_context_irq(dev, irq, gpio_charger_irq,
+                                                  IRQF_TRIGGER_RISING |
+                                                  IRQF_TRIGGER_FALLING,
+                                                  dev_name(dev),
+                                                  dev_id);
+               if (ret < 0) {
+                       dev_warn(dev, "Failed to request irq: %d\n", ret);
+                       irq = 0;
+               }
+       }
+
+       return irq;
+}
+
 static enum power_supply_property gpio_charger_properties[] = {
        POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_STATUS /* Must always be last in the array. */
 };
 
 static int gpio_charger_probe(struct platform_device *pdev)
@@ -104,8 +133,10 @@ static int gpio_charger_probe(struct platform_device *pdev)
        struct power_supply_config psy_cfg = {};
        struct gpio_charger *gpio_charger;
        struct power_supply_desc *charger_desc;
+       struct gpio_desc *charge_status;
+       int charge_status_irq;
        unsigned long flags;
-       int irq, ret;
+       int ret;
 
        if (!pdata && !dev->of_node) {
                dev_err(dev, "No platform data\n");
@@ -151,9 +182,17 @@ static int gpio_charger_probe(struct platform_device *pdev)
                return PTR_ERR(gpio_charger->gpiod);
        }
 
+       charge_status = devm_gpiod_get_optional(dev, "charge-status", GPIOD_IN);
+       gpio_charger->charge_status = charge_status;
+       if (IS_ERR(gpio_charger->charge_status))
+               return PTR_ERR(gpio_charger->charge_status);
+
        charger_desc = &gpio_charger->charger_desc;
        charger_desc->properties = gpio_charger_properties;
        charger_desc->num_properties = ARRAY_SIZE(gpio_charger_properties);
+       /* Remove POWER_SUPPLY_PROP_STATUS from the supported properties. */
+       if (!gpio_charger->charge_status)
+               charger_desc->num_properties -= 1;
        charger_desc->get_property = gpio_charger_get_property;
 
        psy_cfg.of_node = dev->of_node;
@@ -180,16 +219,12 @@ static int gpio_charger_probe(struct platform_device *pdev)
                return ret;
        }
 
-       irq = gpiod_to_irq(gpio_charger->gpiod);
-       if (irq > 0) {
-               ret = devm_request_any_context_irq(dev, irq, gpio_charger_irq,
-                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                               dev_name(dev), gpio_charger->charger);
-               if (ret < 0)
-                       dev_warn(dev, "Failed to request irq: %d\n", ret);
-               else
-                       gpio_charger->irq = irq;
-       }
+       gpio_charger->irq = gpio_charger_get_irq(dev, gpio_charger->charger,
+                                                gpio_charger->gpiod);
+
+       charge_status_irq = gpio_charger_get_irq(dev, gpio_charger->charger,
+                                                gpio_charger->charge_status);
+       gpio_charger->charge_status_irq = charge_status_irq;
 
        platform_set_drvdata(pdev, gpio_charger);
 
diff --git a/drivers/power/supply/ingenic-battery.c b/drivers/power/supply/ingenic-battery.c
new file mode 100644 (file)
index 0000000..35816d4
--- /dev/null
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Battery driver for the Ingenic JZ47xx SoCs
+ * Copyright (c) 2019 Artur Rojek <contact@artur-rojek.eu>
+ *
+ * based on drivers/power/supply/jz4740-battery.c
+ */
+
+#include <linux/iio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/property.h>
+
+struct ingenic_battery {
+       struct device *dev;
+       struct iio_channel *channel;
+       struct power_supply_desc desc;
+       struct power_supply *battery;
+       struct power_supply_battery_info info;
+};
+
+static int ingenic_battery_get_property(struct power_supply *psy,
+                                       enum power_supply_property psp,
+                                       union power_supply_propval *val)
+{
+       struct ingenic_battery *bat = power_supply_get_drvdata(psy);
+       struct power_supply_battery_info *info = &bat->info;
+       int ret;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_HEALTH:
+               ret = iio_read_channel_processed(bat->channel, &val->intval);
+               val->intval *= 1000;
+               if (val->intval < info->voltage_min_design_uv)
+                       val->intval = POWER_SUPPLY_HEALTH_DEAD;
+               else if (val->intval > info->voltage_max_design_uv)
+                       val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+               else
+                       val->intval = POWER_SUPPLY_HEALTH_GOOD;
+               return ret;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               ret = iio_read_channel_processed(bat->channel, &val->intval);
+               val->intval *= 1000;
+               return ret;
+       case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+               val->intval = info->voltage_min_design_uv;
+               return 0;
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+               val->intval = info->voltage_max_design_uv;
+               return 0;
+       default:
+               return -EINVAL;
+       };
+}
+
+/* Set the most appropriate IIO channel voltage reference scale
+ * based on the battery's max voltage.
+ */
+static int ingenic_battery_set_scale(struct ingenic_battery *bat)
+{
+       const int *scale_raw;
+       int scale_len, scale_type, best_idx = -1, best_mV, max_raw, i, ret;
+       u64 max_mV;
+
+       ret = iio_read_max_channel_raw(bat->channel, &max_raw);
+       if (ret) {
+               dev_err(bat->dev, "Unable to read max raw channel value\n");
+               return ret;
+       }
+
+       ret = iio_read_avail_channel_attribute(bat->channel, &scale_raw,
+                                              &scale_type, &scale_len,
+                                              IIO_CHAN_INFO_SCALE);
+       if (ret < 0) {
+               dev_err(bat->dev, "Unable to read channel avail scale\n");
+               return ret;
+       }
+       if (ret != IIO_AVAIL_LIST || scale_type != IIO_VAL_FRACTIONAL_LOG2)
+               return -EINVAL;
+
+       max_mV = bat->info.voltage_max_design_uv / 1000;
+
+       for (i = 0; i < scale_len; i += 2) {
+               u64 scale_mV = (max_raw * scale_raw[i]) >> scale_raw[i + 1];
+
+               if (scale_mV < max_mV)
+                       continue;
+
+               if (best_idx >= 0 && scale_mV > best_mV)
+                       continue;
+
+               best_mV = scale_mV;
+               best_idx = i;
+       }
+
+       if (best_idx < 0) {
+               dev_err(bat->dev, "Unable to find matching voltage scale\n");
+               return -EINVAL;
+       }
+
+       return iio_write_channel_attribute(bat->channel,
+                                          scale_raw[best_idx],
+                                          scale_raw[best_idx + 1],
+                                          IIO_CHAN_INFO_SCALE);
+}
+
+static enum power_supply_property ingenic_battery_properties[] = {
+       POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+       POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+};
+
+static int ingenic_battery_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct ingenic_battery *bat;
+       struct power_supply_config psy_cfg = {};
+       struct power_supply_desc *desc;
+       int ret;
+
+       bat = devm_kzalloc(dev, sizeof(*bat), GFP_KERNEL);
+       if (!bat)
+               return -ENOMEM;
+
+       bat->dev = dev;
+       bat->channel = devm_iio_channel_get(dev, "battery");
+       if (IS_ERR(bat->channel))
+               return PTR_ERR(bat->channel);
+
+       desc = &bat->desc;
+       desc->name = "jz-battery";
+       desc->type = POWER_SUPPLY_TYPE_BATTERY;
+       desc->properties = ingenic_battery_properties;
+       desc->num_properties = ARRAY_SIZE(ingenic_battery_properties);
+       desc->get_property = ingenic_battery_get_property;
+       psy_cfg.drv_data = bat;
+       psy_cfg.of_node = dev->of_node;
+
+       bat->battery = devm_power_supply_register(dev, desc, &psy_cfg);
+       if (IS_ERR(bat->battery)) {
+               dev_err(dev, "Unable to register battery\n");
+               return PTR_ERR(bat->battery);
+       }
+
+       ret = power_supply_get_battery_info(bat->battery, &bat->info);
+       if (ret) {
+               dev_err(dev, "Unable to get battery info: %d\n", ret);
+               return ret;
+       }
+       if (bat->info.voltage_min_design_uv < 0) {
+               dev_err(dev, "Unable to get voltage min design\n");
+               return bat->info.voltage_min_design_uv;
+       }
+       if (bat->info.voltage_max_design_uv < 0) {
+               dev_err(dev, "Unable to get voltage max design\n");
+               return bat->info.voltage_max_design_uv;
+       }
+
+       return ingenic_battery_set_scale(bat);
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ingenic_battery_of_match[] = {
+       { .compatible = "ingenic,jz4740-battery", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, ingenic_battery_of_match);
+#endif
+
+static struct platform_driver ingenic_battery_driver = {
+       .driver = {
+               .name = "ingenic-battery",
+               .of_match_table = of_match_ptr(ingenic_battery_of_match),
+       },
+       .probe = ingenic_battery_probe,
+};
+module_platform_driver(ingenic_battery_driver);
+
+MODULE_DESCRIPTION("Battery driver for Ingenic JZ47xx SoCs");
+MODULE_AUTHOR("Artur Rojek <contact@artur-rojek.eu>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/supply/lt3651-charger.c b/drivers/power/supply/lt3651-charger.c
new file mode 100644 (file)
index 0000000..8de500f
--- /dev/null
@@ -0,0 +1,207 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  Driver for Analog Devices (Linear Technology) LT3651 charger IC.
+ *  Copyright (C) 2017, Topic Embedded Products
+ */
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+struct lt3651_charger {
+       struct power_supply *charger;
+       struct power_supply_desc charger_desc;
+       struct gpio_desc *acpr_gpio;
+       struct gpio_desc *fault_gpio;
+       struct gpio_desc *chrg_gpio;
+};
+
+static irqreturn_t lt3651_charger_irq(int irq, void *devid)
+{
+       struct power_supply *charger = devid;
+
+       power_supply_changed(charger);
+
+       return IRQ_HANDLED;
+}
+
+static inline struct lt3651_charger *psy_to_lt3651_charger(
+       struct power_supply *psy)
+{
+       return power_supply_get_drvdata(psy);
+}
+
+static int lt3651_charger_get_property(struct power_supply *psy,
+               enum power_supply_property psp, union power_supply_propval *val)
+{
+       struct lt3651_charger *lt3651_charger = psy_to_lt3651_charger(psy);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               if (!lt3651_charger->chrg_gpio) {
+                       val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+                       break;
+               }
+               if (gpiod_get_value(lt3651_charger->chrg_gpio))
+                       val->intval = POWER_SUPPLY_STATUS_CHARGING;
+               else
+                       val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               break;
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = gpiod_get_value(lt3651_charger->acpr_gpio);
+               break;
+       case POWER_SUPPLY_PROP_HEALTH:
+               if (!lt3651_charger->fault_gpio) {
+                       val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
+                       break;
+               }
+               if (!gpiod_get_value(lt3651_charger->fault_gpio)) {
+                       val->intval = POWER_SUPPLY_HEALTH_GOOD;
+                       break;
+               }
+               /*
+                * If the fault pin is active, the chrg pin explains the type
+                * of failure.
+                */
+               if (!lt3651_charger->chrg_gpio) {
+                       val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+                       break;
+               }
+               val->intval = gpiod_get_value(lt3651_charger->chrg_gpio) ?
+                               POWER_SUPPLY_HEALTH_OVERHEAT :
+                               POWER_SUPPLY_HEALTH_DEAD;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static enum power_supply_property lt3651_charger_properties[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_HEALTH,
+};
+
+static int lt3651_charger_probe(struct platform_device *pdev)
+{
+       struct power_supply_config psy_cfg = {};
+       struct lt3651_charger *lt3651_charger;
+       struct power_supply_desc *charger_desc;
+       int ret;
+
+       lt3651_charger = devm_kzalloc(&pdev->dev, sizeof(*lt3651_charger),
+                                       GFP_KERNEL);
+       if (!lt3651_charger)
+               return -ENOMEM;
+
+       lt3651_charger->acpr_gpio = devm_gpiod_get(&pdev->dev,
+                                       "lltc,acpr", GPIOD_IN);
+       if (IS_ERR(lt3651_charger->acpr_gpio)) {
+               ret = PTR_ERR(lt3651_charger->acpr_gpio);
+               dev_err(&pdev->dev, "Failed to acquire acpr GPIO: %d\n", ret);
+               return ret;
+       }
+       lt3651_charger->fault_gpio = devm_gpiod_get_optional(&pdev->dev,
+                                       "lltc,fault", GPIOD_IN);
+       if (IS_ERR(lt3651_charger->fault_gpio)) {
+               ret = PTR_ERR(lt3651_charger->fault_gpio);
+               dev_err(&pdev->dev, "Failed to acquire fault GPIO: %d\n", ret);
+               return ret;
+       }
+       lt3651_charger->chrg_gpio = devm_gpiod_get_optional(&pdev->dev,
+                                       "lltc,chrg", GPIOD_IN);
+       if (IS_ERR(lt3651_charger->chrg_gpio)) {
+               ret = PTR_ERR(lt3651_charger->chrg_gpio);
+               dev_err(&pdev->dev, "Failed to acquire chrg GPIO: %d\n", ret);
+               return ret;
+       }
+
+       charger_desc = &lt3651_charger->charger_desc;
+       charger_desc->name = pdev->dev.of_node->name;
+       charger_desc->type = POWER_SUPPLY_TYPE_MAINS;
+       charger_desc->properties = lt3651_charger_properties;
+       charger_desc->num_properties = ARRAY_SIZE(lt3651_charger_properties);
+       charger_desc->get_property = lt3651_charger_get_property;
+       psy_cfg.of_node = pdev->dev.of_node;
+       psy_cfg.drv_data = lt3651_charger;
+
+       lt3651_charger->charger = devm_power_supply_register(&pdev->dev,
+                                                     charger_desc, &psy_cfg);
+       if (IS_ERR(lt3651_charger->charger)) {
+               ret = PTR_ERR(lt3651_charger->charger);
+               dev_err(&pdev->dev, "Failed to register power supply: %d\n",
+                       ret);
+               return ret;
+       }
+
+       /*
+        * Acquire IRQs for the GPIO pins if possible. If the system does not
+        * support IRQs on these pins, userspace will have to poll the sysfs
+        * files manually.
+        */
+       if (lt3651_charger->acpr_gpio) {
+               ret = gpiod_to_irq(lt3651_charger->acpr_gpio);
+               if (ret >= 0)
+                       ret = devm_request_any_context_irq(&pdev->dev, ret,
+                               lt3651_charger_irq,
+                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                               dev_name(&pdev->dev), lt3651_charger->charger);
+               if (ret < 0)
+                       dev_warn(&pdev->dev, "Failed to request acpr irq\n");
+       }
+       if (lt3651_charger->fault_gpio) {
+               ret = gpiod_to_irq(lt3651_charger->fault_gpio);
+               if (ret >= 0)
+                       ret = devm_request_any_context_irq(&pdev->dev, ret,
+                               lt3651_charger_irq,
+                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                               dev_name(&pdev->dev), lt3651_charger->charger);
+               if (ret < 0)
+                       dev_warn(&pdev->dev, "Failed to request fault irq\n");
+       }
+       if (lt3651_charger->chrg_gpio) {
+               ret = gpiod_to_irq(lt3651_charger->chrg_gpio);
+               if (ret >= 0)
+                       ret = devm_request_any_context_irq(&pdev->dev, ret,
+                               lt3651_charger_irq,
+                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                               dev_name(&pdev->dev), lt3651_charger->charger);
+               if (ret < 0)
+                       dev_warn(&pdev->dev, "Failed to request chrg irq\n");
+       }
+
+       platform_set_drvdata(pdev, lt3651_charger);
+
+       return 0;
+}
+
+static const struct of_device_id lt3651_charger_match[] = {
+       { .compatible = "lltc,ltc3651-charger" }, /* DEPRECATED */
+       { .compatible = "lltc,lt3651-charger" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, lt3651_charger_match);
+
+static struct platform_driver lt3651_charger_driver = {
+       .probe = lt3651_charger_probe,
+       .driver = {
+               .name = "lt3651-charger",
+               .of_match_table = lt3651_charger_match,
+       },
+};
+
+module_platform_driver(lt3651_charger_driver);
+
+MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
+MODULE_DESCRIPTION("Driver for LT3651 charger");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lt3651-charger");
diff --git a/drivers/power/supply/ltc3651-charger.c b/drivers/power/supply/ltc3651-charger.c
deleted file mode 100644 (file)
index eea63ff..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- *  Copyright (C) 2017, Topic Embedded Products
- *  Driver for LTC3651 charger IC.
- *
- *  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/device.h>
-#include <linux/gpio/consumer.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/power_supply.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-
-struct ltc3651_charger {
-       struct power_supply *charger;
-       struct power_supply_desc charger_desc;
-       struct gpio_desc *acpr_gpio;
-       struct gpio_desc *fault_gpio;
-       struct gpio_desc *chrg_gpio;
-};
-
-static irqreturn_t ltc3651_charger_irq(int irq, void *devid)
-{
-       struct power_supply *charger = devid;
-
-       power_supply_changed(charger);
-
-       return IRQ_HANDLED;
-}
-
-static inline struct ltc3651_charger *psy_to_ltc3651_charger(
-       struct power_supply *psy)
-{
-       return power_supply_get_drvdata(psy);
-}
-
-static int ltc3651_charger_get_property(struct power_supply *psy,
-               enum power_supply_property psp, union power_supply_propval *val)
-{
-       struct ltc3651_charger *ltc3651_charger = psy_to_ltc3651_charger(psy);
-
-       switch (psp) {
-       case POWER_SUPPLY_PROP_STATUS:
-               if (!ltc3651_charger->chrg_gpio) {
-                       val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
-                       break;
-               }
-               if (gpiod_get_value(ltc3651_charger->chrg_gpio))
-                       val->intval = POWER_SUPPLY_STATUS_CHARGING;
-               else
-                       val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
-               break;
-       case POWER_SUPPLY_PROP_ONLINE:
-               val->intval = gpiod_get_value(ltc3651_charger->acpr_gpio);
-               break;
-       case POWER_SUPPLY_PROP_HEALTH:
-               if (!ltc3651_charger->fault_gpio) {
-                       val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
-                       break;
-               }
-               if (!gpiod_get_value(ltc3651_charger->fault_gpio)) {
-                       val->intval = POWER_SUPPLY_HEALTH_GOOD;
-                       break;
-               }
-               /*
-                * If the fault pin is active, the chrg pin explains the type
-                * of failure.
-                */
-               if (!ltc3651_charger->chrg_gpio) {
-                       val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
-                       break;
-               }
-               val->intval = gpiod_get_value(ltc3651_charger->chrg_gpio) ?
-                               POWER_SUPPLY_HEALTH_OVERHEAT :
-                               POWER_SUPPLY_HEALTH_DEAD;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static enum power_supply_property ltc3651_charger_properties[] = {
-       POWER_SUPPLY_PROP_STATUS,
-       POWER_SUPPLY_PROP_ONLINE,
-       POWER_SUPPLY_PROP_HEALTH,
-};
-
-static int ltc3651_charger_probe(struct platform_device *pdev)
-{
-       struct power_supply_config psy_cfg = {};
-       struct ltc3651_charger *ltc3651_charger;
-       struct power_supply_desc *charger_desc;
-       int ret;
-
-       ltc3651_charger = devm_kzalloc(&pdev->dev, sizeof(*ltc3651_charger),
-                                       GFP_KERNEL);
-       if (!ltc3651_charger)
-               return -ENOMEM;
-
-       ltc3651_charger->acpr_gpio = devm_gpiod_get(&pdev->dev,
-                                       "lltc,acpr", GPIOD_IN);
-       if (IS_ERR(ltc3651_charger->acpr_gpio)) {
-               ret = PTR_ERR(ltc3651_charger->acpr_gpio);
-               dev_err(&pdev->dev, "Failed to acquire acpr GPIO: %d\n", ret);
-               return ret;
-       }
-       ltc3651_charger->fault_gpio = devm_gpiod_get_optional(&pdev->dev,
-                                       "lltc,fault", GPIOD_IN);
-       if (IS_ERR(ltc3651_charger->fault_gpio)) {
-               ret = PTR_ERR(ltc3651_charger->fault_gpio);
-               dev_err(&pdev->dev, "Failed to acquire fault GPIO: %d\n", ret);
-               return ret;
-       }
-       ltc3651_charger->chrg_gpio = devm_gpiod_get_optional(&pdev->dev,
-                                       "lltc,chrg", GPIOD_IN);
-       if (IS_ERR(ltc3651_charger->chrg_gpio)) {
-               ret = PTR_ERR(ltc3651_charger->chrg_gpio);
-               dev_err(&pdev->dev, "Failed to acquire chrg GPIO: %d\n", ret);
-               return ret;
-       }
-
-       charger_desc = &ltc3651_charger->charger_desc;
-       charger_desc->name = pdev->dev.of_node->name;
-       charger_desc->type = POWER_SUPPLY_TYPE_MAINS;
-       charger_desc->properties = ltc3651_charger_properties;
-       charger_desc->num_properties = ARRAY_SIZE(ltc3651_charger_properties);
-       charger_desc->get_property = ltc3651_charger_get_property;
-       psy_cfg.of_node = pdev->dev.of_node;
-       psy_cfg.drv_data = ltc3651_charger;
-
-       ltc3651_charger->charger = devm_power_supply_register(&pdev->dev,
-                                                     charger_desc, &psy_cfg);
-       if (IS_ERR(ltc3651_charger->charger)) {
-               ret = PTR_ERR(ltc3651_charger->charger);
-               dev_err(&pdev->dev, "Failed to register power supply: %d\n",
-                       ret);
-               return ret;
-       }
-
-       /*
-        * Acquire IRQs for the GPIO pins if possible. If the system does not
-        * support IRQs on these pins, userspace will have to poll the sysfs
-        * files manually.
-        */
-       if (ltc3651_charger->acpr_gpio) {
-               ret = gpiod_to_irq(ltc3651_charger->acpr_gpio);
-               if (ret >= 0)
-                       ret = devm_request_any_context_irq(&pdev->dev, ret,
-                               ltc3651_charger_irq,
-                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                               dev_name(&pdev->dev), ltc3651_charger->charger);
-               if (ret < 0)
-                       dev_warn(&pdev->dev, "Failed to request acpr irq\n");
-       }
-       if (ltc3651_charger->fault_gpio) {
-               ret = gpiod_to_irq(ltc3651_charger->fault_gpio);
-               if (ret >= 0)
-                       ret = devm_request_any_context_irq(&pdev->dev, ret,
-                               ltc3651_charger_irq,
-                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                               dev_name(&pdev->dev), ltc3651_charger->charger);
-               if (ret < 0)
-                       dev_warn(&pdev->dev, "Failed to request fault irq\n");
-       }
-       if (ltc3651_charger->chrg_gpio) {
-               ret = gpiod_to_irq(ltc3651_charger->chrg_gpio);
-               if (ret >= 0)
-                       ret = devm_request_any_context_irq(&pdev->dev, ret,
-                               ltc3651_charger_irq,
-                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                               dev_name(&pdev->dev), ltc3651_charger->charger);
-               if (ret < 0)
-                       dev_warn(&pdev->dev, "Failed to request chrg irq\n");
-       }
-
-       platform_set_drvdata(pdev, ltc3651_charger);
-
-       return 0;
-}
-
-static const struct of_device_id ltc3651_charger_match[] = {
-       { .compatible = "lltc,ltc3651-charger" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, ltc3651_charger_match);
-
-static struct platform_driver ltc3651_charger_driver = {
-       .probe = ltc3651_charger_probe,
-       .driver = {
-               .name = "ltc3651-charger",
-               .of_match_table = ltc3651_charger_match,
-       },
-};
-
-module_platform_driver(ltc3651_charger_driver);
-
-MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
-MODULE_DESCRIPTION("Driver for LTC3651 charger");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:ltc3651-charger");
index b91b1d2..9e64728 100644 (file)
@@ -240,6 +240,14 @@ static enum power_supply_property max14656_battery_props[] = {
        POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
+static void stop_irq_work(void *data)
+{
+       struct max14656_chip *chip = data;
+
+       cancel_delayed_work_sync(&chip->irq_work);
+}
+
+
 static int max14656_probe(struct i2c_client *client,
                          const struct i2c_device_id *id)
 {
@@ -278,7 +286,19 @@ static int max14656_probe(struct i2c_client *client,
        if (ret)
                return -ENODEV;
 
+       chip->detect_psy = devm_power_supply_register(dev,
+                      &chip->psy_desc, &psy_cfg);
+       if (IS_ERR(chip->detect_psy)) {
+               dev_err(dev, "power_supply_register failed\n");
+               return -EINVAL;
+       }
+
        INIT_DELAYED_WORK(&chip->irq_work, max14656_irq_worker);
+       ret = devm_add_action(dev, stop_irq_work, chip);
+       if (ret) {
+               dev_err(dev, "devm_add_action %d failed\n", ret);
+               return ret;
+       }
 
        ret = devm_request_irq(dev, chip->irq, max14656_irq,
                               IRQF_TRIGGER_FALLING,
@@ -289,13 +309,6 @@ static int max14656_probe(struct i2c_client *client,
        }
        enable_irq_wake(chip->irq);
 
-       chip->detect_psy = devm_power_supply_register(dev,
-                      &chip->psy_desc, &psy_cfg);
-       if (IS_ERR(chip->detect_psy)) {
-               dev_err(dev, "power_supply_register failed\n");
-               return -EINVAL;
-       }
-
        schedule_delayed_work(&chip->irq_work, msecs_to_jiffies(2000));
 
        return 0;
diff --git a/drivers/power/supply/max77650-charger.c b/drivers/power/supply/max77650-charger.c
new file mode 100644 (file)
index 0000000..e34714c
--- /dev/null
@@ -0,0 +1,368 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// Battery charger driver for MAXIM 77650/77651 charger/power-supply.
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/max77650.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+
+#define MAX77650_CHARGER_ENABLED               BIT(0)
+#define MAX77650_CHARGER_DISABLED              0x00
+#define MAX77650_CHARGER_CHG_EN_MASK           BIT(0)
+
+#define MAX77650_CHG_DETAILS_MASK              GENMASK(7, 4)
+#define MAX77650_CHG_DETAILS_BITS(_reg) \
+               (((_reg) & MAX77650_CHG_DETAILS_MASK) >> 4)
+
+/* Charger is OFF. */
+#define MAX77650_CHG_OFF                       0x00
+/* Charger is in prequalification mode. */
+#define MAX77650_CHG_PREQ                      0x01
+/* Charger is in fast-charge constant current mode. */
+#define MAX77650_CHG_ON_CURR                   0x02
+/* Charger is in JEITA modified fast-charge constant-current mode. */
+#define MAX77650_CHG_ON_CURR_JEITA             0x03
+/* Charger is in fast-charge constant-voltage mode. */
+#define MAX77650_CHG_ON_VOLT                   0x04
+/* Charger is in JEITA modified fast-charge constant-voltage mode. */
+#define MAX77650_CHG_ON_VOLT_JEITA             0x05
+/* Charger is in top-off mode. */
+#define MAX77650_CHG_ON_TOPOFF                 0x06
+/* Charger is in JEITA modified top-off mode. */
+#define MAX77650_CHG_ON_TOPOFF_JEITA           0x07
+/* Charger is done. */
+#define MAX77650_CHG_DONE                      0x08
+/* Charger is JEITA modified done. */
+#define MAX77650_CHG_DONE_JEITA                        0x09
+/* Charger is suspended due to a prequalification timer fault. */
+#define MAX77650_CHG_SUSP_PREQ_TIM_FAULT       0x0a
+/* Charger is suspended due to a fast-charge timer fault. */
+#define MAX77650_CHG_SUSP_FAST_CHG_TIM_FAULT   0x0b
+/* Charger is suspended due to a battery temperature fault. */
+#define MAX77650_CHG_SUSP_BATT_TEMP_FAULT      0x0c
+
+#define MAX77650_CHGIN_DETAILS_MASK            GENMASK(3, 2)
+#define MAX77650_CHGIN_DETAILS_BITS(_reg) \
+               (((_reg) & MAX77650_CHGIN_DETAILS_MASK) >> 2)
+
+#define MAX77650_CHGIN_UNDERVOLTAGE_LOCKOUT    0x00
+#define MAX77650_CHGIN_OVERVOLTAGE_LOCKOUT     0x01
+#define MAX77650_CHGIN_OKAY                    0x11
+
+#define MAX77650_CHARGER_CHG_MASK      BIT(1)
+#define MAX77650_CHARGER_CHG_CHARGING(_reg) \
+               (((_reg) & MAX77650_CHARGER_CHG_MASK) > 1)
+
+#define MAX77650_CHARGER_VCHGIN_MIN_MASK       0xc0
+#define MAX77650_CHARGER_VCHGIN_MIN_SHIFT(_val)        ((_val) << 5)
+
+#define MAX77650_CHARGER_ICHGIN_LIM_MASK       0x1c
+#define MAX77650_CHARGER_ICHGIN_LIM_SHIFT(_val)        ((_val) << 2)
+
+struct max77650_charger_data {
+       struct regmap *map;
+       struct device *dev;
+};
+
+static enum power_supply_property max77650_charger_properties[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_CHARGE_TYPE
+};
+
+static const unsigned int max77650_charger_vchgin_min_table[] = {
+       4000000, 4100000, 4200000, 4300000, 4400000, 4500000, 4600000, 4700000
+};
+
+static const unsigned int max77650_charger_ichgin_lim_table[] = {
+       95000, 190000, 285000, 380000, 475000
+};
+
+static int max77650_charger_set_vchgin_min(struct max77650_charger_data *chg,
+                                          unsigned int val)
+{
+       int i, rv;
+
+       for (i = 0; i < ARRAY_SIZE(max77650_charger_vchgin_min_table); i++) {
+               if (val == max77650_charger_vchgin_min_table[i]) {
+                       rv = regmap_update_bits(chg->map,
+                                       MAX77650_REG_CNFG_CHG_B,
+                                       MAX77650_CHARGER_VCHGIN_MIN_MASK,
+                                       MAX77650_CHARGER_VCHGIN_MIN_SHIFT(i));
+                       if (rv)
+                               return rv;
+
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int max77650_charger_set_ichgin_lim(struct max77650_charger_data *chg,
+                                          unsigned int val)
+{
+       int i, rv;
+
+       for (i = 0; i < ARRAY_SIZE(max77650_charger_ichgin_lim_table); i++) {
+               if (val == max77650_charger_ichgin_lim_table[i]) {
+                       rv = regmap_update_bits(chg->map,
+                                       MAX77650_REG_CNFG_CHG_B,
+                                       MAX77650_CHARGER_ICHGIN_LIM_MASK,
+                                       MAX77650_CHARGER_ICHGIN_LIM_SHIFT(i));
+                       if (rv)
+                               return rv;
+
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int max77650_charger_enable(struct max77650_charger_data *chg)
+{
+       int rv;
+
+       rv = regmap_update_bits(chg->map,
+                               MAX77650_REG_CNFG_CHG_B,
+                               MAX77650_CHARGER_CHG_EN_MASK,
+                               MAX77650_CHARGER_ENABLED);
+       if (rv)
+               dev_err(chg->dev, "unable to enable the charger: %d\n", rv);
+
+       return rv;
+}
+
+static int max77650_charger_disable(struct max77650_charger_data *chg)
+{
+       int rv;
+
+       rv = regmap_update_bits(chg->map,
+                               MAX77650_REG_CNFG_CHG_B,
+                               MAX77650_CHARGER_CHG_EN_MASK,
+                               MAX77650_CHARGER_DISABLED);
+       if (rv)
+               dev_err(chg->dev, "unable to disable the charger: %d\n", rv);
+
+       return rv;
+}
+
+static irqreturn_t max77650_charger_check_status(int irq, void *data)
+{
+       struct max77650_charger_data *chg = data;
+       int rv, reg;
+
+       rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, &reg);
+       if (rv) {
+               dev_err(chg->dev,
+                       "unable to read the charger status: %d\n", rv);
+               return IRQ_HANDLED;
+       }
+
+       switch (MAX77650_CHGIN_DETAILS_BITS(reg)) {
+       case MAX77650_CHGIN_UNDERVOLTAGE_LOCKOUT:
+               dev_err(chg->dev, "undervoltage lockout detected, disabling charger\n");
+               max77650_charger_disable(chg);
+               break;
+       case MAX77650_CHGIN_OVERVOLTAGE_LOCKOUT:
+               dev_err(chg->dev, "overvoltage lockout detected, disabling charger\n");
+               max77650_charger_disable(chg);
+               break;
+       case MAX77650_CHGIN_OKAY:
+               max77650_charger_enable(chg);
+               break;
+       default:
+               /* May be 0x10 - debouncing */
+               break;
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int max77650_charger_get_property(struct power_supply *psy,
+                                        enum power_supply_property psp,
+                                        union power_supply_propval *val)
+{
+       struct max77650_charger_data *chg = power_supply_get_drvdata(psy);
+       int rv, reg;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, &reg);
+               if (rv)
+                       return rv;
+
+               if (MAX77650_CHARGER_CHG_CHARGING(reg)) {
+                       val->intval = POWER_SUPPLY_STATUS_CHARGING;
+                       break;
+               }
+
+               switch (MAX77650_CHG_DETAILS_BITS(reg)) {
+               case MAX77650_CHG_OFF:
+               case MAX77650_CHG_SUSP_PREQ_TIM_FAULT:
+               case MAX77650_CHG_SUSP_FAST_CHG_TIM_FAULT:
+               case MAX77650_CHG_SUSP_BATT_TEMP_FAULT:
+                       val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+                       break;
+               case MAX77650_CHG_PREQ:
+               case MAX77650_CHG_ON_CURR:
+               case MAX77650_CHG_ON_CURR_JEITA:
+               case MAX77650_CHG_ON_VOLT:
+               case MAX77650_CHG_ON_VOLT_JEITA:
+               case MAX77650_CHG_ON_TOPOFF:
+               case MAX77650_CHG_ON_TOPOFF_JEITA:
+                       val->intval = POWER_SUPPLY_STATUS_CHARGING;
+                       break;
+               case MAX77650_CHG_DONE:
+                       val->intval = POWER_SUPPLY_STATUS_FULL;
+                       break;
+               default:
+                       val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+               }
+               break;
+       case POWER_SUPPLY_PROP_ONLINE:
+               rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, &reg);
+               if (rv)
+                       return rv;
+
+               val->intval = MAX77650_CHARGER_CHG_CHARGING(reg);
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_TYPE:
+               rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, &reg);
+               if (rv)
+                       return rv;
+
+               if (!MAX77650_CHARGER_CHG_CHARGING(reg)) {
+                       val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+                       break;
+               }
+
+               switch (MAX77650_CHG_DETAILS_BITS(reg)) {
+               case MAX77650_CHG_PREQ:
+               case MAX77650_CHG_ON_CURR:
+               case MAX77650_CHG_ON_CURR_JEITA:
+               case MAX77650_CHG_ON_VOLT:
+               case MAX77650_CHG_ON_VOLT_JEITA:
+                       val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+                       break;
+               case MAX77650_CHG_ON_TOPOFF:
+               case MAX77650_CHG_ON_TOPOFF_JEITA:
+                       val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+                       break;
+               default:
+                       val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct power_supply_desc max77650_battery_desc = {
+       .name           = "max77650",
+       .type           = POWER_SUPPLY_TYPE_USB,
+       .get_property   = max77650_charger_get_property,
+       .properties     = max77650_charger_properties,
+       .num_properties = ARRAY_SIZE(max77650_charger_properties),
+};
+
+static int max77650_charger_probe(struct platform_device *pdev)
+{
+       struct power_supply_config pscfg = {};
+       struct max77650_charger_data *chg;
+       struct power_supply *battery;
+       struct device *dev, *parent;
+       int rv, chg_irq, chgin_irq;
+       unsigned int prop;
+
+       dev = &pdev->dev;
+       parent = dev->parent;
+
+       chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL);
+       if (!chg)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, chg);
+
+       chg->map = dev_get_regmap(parent, NULL);
+       if (!chg->map)
+               return -ENODEV;
+
+       chg->dev = dev;
+
+       pscfg.of_node = dev->of_node;
+       pscfg.drv_data = chg;
+
+       chg_irq = platform_get_irq_byname(pdev, "CHG");
+       if (chg_irq < 0)
+               return chg_irq;
+
+       chgin_irq = platform_get_irq_byname(pdev, "CHGIN");
+       if (chgin_irq < 0)
+               return chgin_irq;
+
+       rv = devm_request_any_context_irq(dev, chg_irq,
+                                         max77650_charger_check_status,
+                                         IRQF_ONESHOT, "chg", chg);
+       if (rv < 0)
+               return rv;
+
+       rv = devm_request_any_context_irq(dev, chgin_irq,
+                                         max77650_charger_check_status,
+                                         IRQF_ONESHOT, "chgin", chg);
+       if (rv < 0)
+               return rv;
+
+       battery = devm_power_supply_register(dev,
+                                            &max77650_battery_desc, &pscfg);
+       if (IS_ERR(battery))
+               return PTR_ERR(battery);
+
+       rv = of_property_read_u32(dev->of_node,
+                                 "input-voltage-min-microvolt", &prop);
+       if (rv == 0) {
+               rv = max77650_charger_set_vchgin_min(chg, prop);
+               if (rv)
+                       return rv;
+       }
+
+       rv = of_property_read_u32(dev->of_node,
+                                 "input-current-limit-microamp", &prop);
+       if (rv == 0) {
+               rv = max77650_charger_set_ichgin_lim(chg, prop);
+               if (rv)
+                       return rv;
+       }
+
+       return max77650_charger_enable(chg);
+}
+
+static int max77650_charger_remove(struct platform_device *pdev)
+{
+       struct max77650_charger_data *chg = platform_get_drvdata(pdev);
+
+       return max77650_charger_disable(chg);
+}
+
+static struct platform_driver max77650_charger_driver = {
+       .driver = {
+               .name = "max77650-charger",
+       },
+       .probe = max77650_charger_probe,
+       .remove = max77650_charger_remove,
+};
+module_platform_driver(max77650_charger_driver);
+
+MODULE_DESCRIPTION("MAXIM 77650/77651 charger driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL v2");
index 5a97e42..7720e4c 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/err.h>
 #include <linux/device.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
 #include <linux/jiffies.h>
 
 #define BAT_ADDR_MFR_TYPE      0x5F
 
+struct olpc_battery_data {
+       struct power_supply *olpc_ac;
+       struct power_supply *olpc_bat;
+       char bat_serial[17];
+       bool new_proto;
+       bool little_endian;
+};
+
 /*********************************************************************
  *             Power
  *********************************************************************/
@@ -90,13 +99,10 @@ static const struct power_supply_desc olpc_ac_desc = {
        .get_property = olpc_ac_get_prop,
 };
 
-static struct power_supply *olpc_ac;
-
-static char bat_serial[17]; /* Ick */
-
-static int olpc_bat_get_status(union power_supply_propval *val, uint8_t ec_byte)
+static int olpc_bat_get_status(struct olpc_battery_data *data,
+               union power_supply_propval *val, uint8_t ec_byte)
 {
-       if (olpc_platform_info.ecver > 0x44) {
+       if (data->new_proto) {
                if (ec_byte & (BAT_STAT_CHARGING | BAT_STAT_TRICKLE))
                        val->intval = POWER_SUPPLY_STATUS_CHARGING;
                else if (ec_byte & BAT_STAT_DISCHARGING)
@@ -318,6 +324,14 @@ static int olpc_bat_get_voltage_max_design(union power_supply_propval *val)
        return ret;
 }
 
+static u16 ecword_to_cpu(struct olpc_battery_data *data, u16 ec_word)
+{
+       if (data->little_endian)
+               return le16_to_cpu((__force __le16)ec_word);
+       else
+               return be16_to_cpu((__force __be16)ec_word);
+}
+
 /*********************************************************************
  *             Battery properties
  *********************************************************************/
@@ -325,8 +339,9 @@ static int olpc_bat_get_property(struct power_supply *psy,
                                 enum power_supply_property psp,
                                 union power_supply_propval *val)
 {
+       struct olpc_battery_data *data = power_supply_get_drvdata(psy);
        int ret = 0;
-       __be16 ec_word;
+       u16 ec_word;
        uint8_t ec_byte;
        __be64 ser_buf;
 
@@ -346,7 +361,7 @@ static int olpc_bat_get_property(struct power_supply *psy,
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
-               ret = olpc_bat_get_status(val, ec_byte);
+               ret = olpc_bat_get_status(data, val, ec_byte);
                if (ret)
                        return ret;
                break;
@@ -389,7 +404,7 @@ static int olpc_bat_get_property(struct power_supply *psy,
                if (ret)
                        return ret;
 
-               val->intval = (s16)be16_to_cpu(ec_word) * 9760L / 32;
+               val->intval = ecword_to_cpu(data, ec_word) * 9760L / 32;
                break;
        case POWER_SUPPLY_PROP_CURRENT_AVG:
        case POWER_SUPPLY_PROP_CURRENT_NOW:
@@ -397,7 +412,7 @@ static int olpc_bat_get_property(struct power_supply *psy,
                if (ret)
                        return ret;
 
-               val->intval = (s16)be16_to_cpu(ec_word) * 15625L / 120;
+               val->intval = ecword_to_cpu(data, ec_word) * 15625L / 120;
                break;
        case POWER_SUPPLY_PROP_CAPACITY:
                ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1);
@@ -428,29 +443,29 @@ static int olpc_bat_get_property(struct power_supply *psy,
                if (ret)
                        return ret;
 
-               val->intval = (s16)be16_to_cpu(ec_word) * 10 / 256;
+               val->intval = ecword_to_cpu(data, ec_word) * 10 / 256;
                break;
        case POWER_SUPPLY_PROP_TEMP_AMBIENT:
                ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
                if (ret)
                        return ret;
 
-               val->intval = (int)be16_to_cpu(ec_word) * 10 / 256;
+               val->intval = (int)ecword_to_cpu(data, ec_word) * 10 / 256;
                break;
        case POWER_SUPPLY_PROP_CHARGE_COUNTER:
                ret = olpc_ec_cmd(EC_BAT_ACR, NULL, 0, (void *)&ec_word, 2);
                if (ret)
                        return ret;
 
-               val->intval = (s16)be16_to_cpu(ec_word) * 6250 / 15;
+               val->intval = ecword_to_cpu(data, ec_word) * 6250 / 15;
                break;
        case POWER_SUPPLY_PROP_SERIAL_NUMBER:
                ret = olpc_ec_cmd(EC_BAT_SERIAL, NULL, 0, (void *)&ser_buf, 8);
                if (ret)
                        return ret;
 
-               sprintf(bat_serial, "%016llx", (long long)be64_to_cpu(ser_buf));
-               val->strval = bat_serial;
+               sprintf(data->bat_serial, "%016llx", (long long)be64_to_cpu(ser_buf));
+               val->strval = data->bat_serial;
                break;
        case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
                ret = olpc_bat_get_voltage_max_design(val);
@@ -536,7 +551,7 @@ static ssize_t olpc_bat_eeprom_read(struct file *filp, struct kobject *kobj,
        return count;
 }
 
-static const struct bin_attribute olpc_bat_eeprom = {
+static struct bin_attribute olpc_bat_eeprom = {
        .attr = {
                .name = "eeprom",
                .mode = S_IRUGO,
@@ -560,7 +575,7 @@ static ssize_t olpc_bat_error_read(struct device *dev,
        return sprintf(buf, "%d\n", ec_byte);
 }
 
-static const struct device_attribute olpc_bat_error = {
+static struct device_attribute olpc_bat_error = {
        .attr = {
                .name = "error",
                .mode = S_IRUGO,
@@ -568,6 +583,27 @@ static const struct device_attribute olpc_bat_error = {
        .show = olpc_bat_error_read,
 };
 
+static struct attribute *olpc_bat_sysfs_attrs[] = {
+       &olpc_bat_error.attr,
+       NULL
+};
+
+static struct bin_attribute *olpc_bat_sysfs_bin_attrs[] = {
+       &olpc_bat_eeprom,
+       NULL
+};
+
+static const struct attribute_group olpc_bat_sysfs_group = {
+       .attrs = olpc_bat_sysfs_attrs,
+       .bin_attrs = olpc_bat_sysfs_bin_attrs,
+
+};
+
+static const struct attribute_group *olpc_bat_sysfs_groups[] = {
+       &olpc_bat_sysfs_group,
+       NULL
+};
+
 /*********************************************************************
  *             Initialisation
  *********************************************************************/
@@ -578,17 +614,17 @@ static struct power_supply_desc olpc_bat_desc = {
        .use_for_apm = 1,
 };
 
-static struct power_supply *olpc_bat;
-
 static int olpc_battery_suspend(struct platform_device *pdev,
                                pm_message_t state)
 {
-       if (device_may_wakeup(&olpc_ac->dev))
+       struct olpc_battery_data *data = platform_get_drvdata(pdev);
+
+       if (device_may_wakeup(&data->olpc_ac->dev))
                olpc_ec_wakeup_set(EC_SCI_SRC_ACPWR);
        else
                olpc_ec_wakeup_clear(EC_SCI_SRC_ACPWR);
 
-       if (device_may_wakeup(&olpc_bat->dev))
+       if (device_may_wakeup(&data->olpc_bat->dev))
                olpc_ec_wakeup_set(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC
                                   | EC_SCI_SRC_BATERR);
        else
@@ -600,16 +636,37 @@ static int olpc_battery_suspend(struct platform_device *pdev,
 
 static int olpc_battery_probe(struct platform_device *pdev)
 {
-       int ret;
+       struct power_supply_config bat_psy_cfg = {};
+       struct power_supply_config ac_psy_cfg = {};
+       struct olpc_battery_data *data;
        uint8_t status;
+       uint8_t ecver;
+       int ret;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       platform_set_drvdata(pdev, data);
 
-       /*
-        * We've seen a number of EC protocol changes; this driver requires
-        * the latest EC protocol, supported by 0x44 and above.
-        */
-       if (olpc_platform_info.ecver < 0x44) {
+       /* See if the EC is already there and get the EC revision */
+       ret = olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, &ecver, 1);
+       if (ret)
+               return ret;
+
+       if (of_find_compatible_node(NULL, NULL, "olpc,xo1.75-ec")) {
+               /* XO 1.75 */
+               data->new_proto = true;
+               data->little_endian = true;
+       } else if (ecver > 0x44) {
+               /* XO 1 or 1.5 with a new EC firmware. */
+               data->new_proto = true;
+       } else if (ecver < 0x44) {
+               /*
+                * We've seen a number of EC protocol changes; this driver
+                * requires the latest EC protocol, supported by 0x44 and above.
+                */
                printk(KERN_NOTICE "OLPC EC version 0x%02x too old for "
-                       "battery driver.\n", olpc_platform_info.ecver);
+                       "battery driver.\n", ecver);
                return -ENXIO;
        }
 
@@ -619,59 +676,44 @@ static int olpc_battery_probe(struct platform_device *pdev)
 
        /* Ignore the status. It doesn't actually matter */
 
-       olpc_ac = power_supply_register(&pdev->dev, &olpc_ac_desc, NULL);
-       if (IS_ERR(olpc_ac))
-               return PTR_ERR(olpc_ac);
+       ac_psy_cfg.of_node = pdev->dev.of_node;
+       ac_psy_cfg.drv_data = data;
+
+       data->olpc_ac = devm_power_supply_register(&pdev->dev, &olpc_ac_desc,
+                                                               &ac_psy_cfg);
+       if (IS_ERR(data->olpc_ac))
+               return PTR_ERR(data->olpc_ac);
 
-       if (olpc_board_at_least(olpc_board_pre(0xd0))) { /* XO-1.5 */
+       if (of_device_is_compatible(pdev->dev.of_node, "olpc,xo1.5-battery")) {
+               /* XO-1.5 */
                olpc_bat_desc.properties = olpc_xo15_bat_props;
                olpc_bat_desc.num_properties = ARRAY_SIZE(olpc_xo15_bat_props);
-       } else { /* XO-1 */
+       } else {
+               /* XO-1 */
                olpc_bat_desc.properties = olpc_xo1_bat_props;
                olpc_bat_desc.num_properties = ARRAY_SIZE(olpc_xo1_bat_props);
        }
 
-       olpc_bat = power_supply_register(&pdev->dev, &olpc_bat_desc, NULL);
-       if (IS_ERR(olpc_bat)) {
-               ret = PTR_ERR(olpc_bat);
-               goto battery_failed;
-       }
-
-       ret = device_create_bin_file(&olpc_bat->dev, &olpc_bat_eeprom);
-       if (ret)
-               goto eeprom_failed;
+       bat_psy_cfg.of_node = pdev->dev.of_node;
+       bat_psy_cfg.drv_data = data;
+       bat_psy_cfg.attr_grp = olpc_bat_sysfs_groups;
 
-       ret = device_create_file(&olpc_bat->dev, &olpc_bat_error);
-       if (ret)
-               goto error_failed;
+       data->olpc_bat = devm_power_supply_register(&pdev->dev, &olpc_bat_desc,
+                                                               &bat_psy_cfg);
+       if (IS_ERR(data->olpc_bat))
+               return PTR_ERR(data->olpc_bat);
 
        if (olpc_ec_wakeup_available()) {
-               device_set_wakeup_capable(&olpc_ac->dev, true);
-               device_set_wakeup_capable(&olpc_bat->dev, true);
+               device_set_wakeup_capable(&data->olpc_ac->dev, true);
+               device_set_wakeup_capable(&data->olpc_bat->dev, true);
        }
 
        return 0;
-
-error_failed:
-       device_remove_bin_file(&olpc_bat->dev, &olpc_bat_eeprom);
-eeprom_failed:
-       power_supply_unregister(olpc_bat);
-battery_failed:
-       power_supply_unregister(olpc_ac);
-       return ret;
-}
-
-static int olpc_battery_remove(struct platform_device *pdev)
-{
-       device_remove_file(&olpc_bat->dev, &olpc_bat_error);
-       device_remove_bin_file(&olpc_bat->dev, &olpc_bat_eeprom);
-       power_supply_unregister(olpc_bat);
-       power_supply_unregister(olpc_ac);
-       return 0;
 }
 
 static const struct of_device_id olpc_battery_ids[] = {
        { .compatible = "olpc,xo1-battery" },
+       { .compatible = "olpc,xo1.5-battery" },
        {}
 };
 MODULE_DEVICE_TABLE(of, olpc_battery_ids);
@@ -682,7 +724,6 @@ static struct platform_driver olpc_battery_driver = {
                .of_match_table = olpc_battery_ids,
        },
        .probe = olpc_battery_probe,
-       .remove = olpc_battery_remove,
        .suspend = olpc_battery_suspend,
 };
 
index c917a8b..f7033ec 100644 (file)
@@ -598,10 +598,12 @@ int power_supply_get_battery_info(struct power_supply *psy,
 
        err = of_property_read_string(battery_np, "compatible", &value);
        if (err)
-               return err;
+               goto out_put_node;
 
-       if (strcmp("simple-battery", value))
-               return -ENODEV;
+       if (strcmp("simple-battery", value)) {
+               err = -ENODEV;
+               goto out_put_node;
+       }
 
        /* The property and field names below must correspond to elements
         * in enum power_supply_property. For reasoning, see
@@ -620,19 +622,21 @@ int power_supply_get_battery_info(struct power_supply *psy,
                             &info->precharge_current_ua);
        of_property_read_u32(battery_np, "charge-term-current-microamp",
                             &info->charge_term_current_ua);
-       of_property_read_u32(battery_np, "constant_charge_current_max_microamp",
+       of_property_read_u32(battery_np, "constant-charge-current-max-microamp",
                             &info->constant_charge_current_max_ua);
-       of_property_read_u32(battery_np, "constant_charge_voltage_max_microvolt",
+       of_property_read_u32(battery_np, "constant-charge-voltage-max-microvolt",
                             &info->constant_charge_voltage_max_uv);
        of_property_read_u32(battery_np, "factory-internal-resistance-micro-ohms",
                             &info->factory_internal_resistance_uohm);
 
        len = of_property_count_u32_elems(battery_np, "ocv-capacity-celsius");
        if (len < 0 && len != -EINVAL) {
-               return len;
+               err = len;
+               goto out_put_node;
        } else if (len > POWER_SUPPLY_OCV_TEMP_MAX) {
                dev_err(&psy->dev, "Too many temperature values\n");
-               return -EINVAL;
+               err = -EINVAL;
+               goto out_put_node;
        } else if (len > 0) {
                of_property_read_u32_array(battery_np, "ocv-capacity-celsius",
                                           info->ocv_temp, len);
@@ -650,7 +654,8 @@ int power_supply_get_battery_info(struct power_supply *psy,
                        dev_err(&psy->dev, "failed to get %s\n", propname);
                        kfree(propname);
                        power_supply_put_battery_info(psy, info);
-                       return -EINVAL;
+                       err = -EINVAL;
+                       goto out_put_node;
                }
 
                kfree(propname);
@@ -661,16 +666,21 @@ int power_supply_get_battery_info(struct power_supply *psy,
                        devm_kcalloc(&psy->dev, tab_len, sizeof(*table), GFP_KERNEL);
                if (!info->ocv_table[index]) {
                        power_supply_put_battery_info(psy, info);
-                       return -ENOMEM;
+                       err = -ENOMEM;
+                       goto out_put_node;
                }
 
                for (i = 0; i < tab_len; i++) {
-                       table[i].ocv = be32_to_cpu(*list++);
-                       table[i].capacity = be32_to_cpu(*list++);
+                       table[i].ocv = be32_to_cpu(*list);
+                       list++;
+                       table[i].capacity = be32_to_cpu(*list);
+                       list++;
                }
        }
 
-       return 0;
+out_put_node:
+       of_node_put(battery_np);
+       return err;
 }
 EXPORT_SYMBOL_GPL(power_supply_get_battery_info);
 
@@ -899,7 +909,7 @@ static int ps_get_max_charge_cntl_limit(struct thermal_cooling_device *tcd,
        return ret;
 }
 
-static int ps_get_cur_chrage_cntl_limit(struct thermal_cooling_device *tcd,
+static int ps_get_cur_charge_cntl_limit(struct thermal_cooling_device *tcd,
                                        unsigned long *state)
 {
        struct power_supply *psy;
@@ -934,7 +944,7 @@ static int ps_set_cur_charge_cntl_limit(struct thermal_cooling_device *tcd,
 
 static const struct thermal_cooling_device_ops psy_tcd_ops = {
        .get_max_state = ps_get_max_charge_cntl_limit,
-       .get_cur_state = ps_get_cur_chrage_cntl_limit,
+       .get_cur_state = ps_get_cur_charge_cntl_limit,
        .set_cur_state = ps_set_cur_charge_cntl_limit,
 };
 
index 5358a80..a704a76 100644 (file)
@@ -56,13 +56,13 @@ static const char * const power_supply_status_text[] = {
 };
 
 static const char * const power_supply_charge_type_text[] = {
-       "Unknown", "N/A", "Trickle", "Fast"
+       "Unknown", "N/A", "Trickle", "Fast", "Standard", "Adaptive", "Custom"
 };
 
 static const char * const power_supply_health_text[] = {
        "Unknown", "Good", "Overheat", "Dead", "Over voltage",
        "Unspecified failure", "Cold", "Watchdog timer expire",
-       "Safety timer expire"
+       "Safety timer expire", "Over current"
 };
 
 static const char * const power_supply_technology_text[] = {
@@ -274,6 +274,8 @@ static struct device_attribute power_supply_attrs[] = {
        POWER_SUPPLY_ATTR(constant_charge_voltage_max),
        POWER_SUPPLY_ATTR(charge_control_limit),
        POWER_SUPPLY_ATTR(charge_control_limit_max),
+       POWER_SUPPLY_ATTR(charge_control_start_threshold),
+       POWER_SUPPLY_ATTR(charge_control_end_threshold),
        POWER_SUPPLY_ATTR(input_current_limit),
        POWER_SUPPLY_ATTR(energy_full_design),
        POWER_SUPPLY_ATTR(energy_empty_design),
diff --git a/drivers/power/supply/ucs1002_power.c b/drivers/power/supply/ucs1002_power.c
new file mode 100644 (file)
index 0000000..1c89d03
--- /dev/null
@@ -0,0 +1,646 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver for UCS1002 Programmable USB Port Power Controller
+ *
+ * Copyright (C) 2019 Zodiac Inflight Innovations
+ */
+#include <linux/bits.h>
+#include <linux/freezer.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+/* UCS1002 Registers */
+#define UCS1002_REG_CURRENT_MEASUREMENT        0x00
+
+/*
+ * The Total Accumulated Charge registers store the total accumulated
+ * charge delivered from the VS source to a portable device. The total
+ * value is calculated using four registers, from 01h to 04h. The bit
+ * weighting of the registers is given in mA/hrs.
+ */
+#define UCS1002_REG_TOTAL_ACC_CHARGE   0x01
+
+/* Other Status Register */
+#define UCS1002_REG_OTHER_STATUS       0x0f
+#  define F_ADET_PIN                   BIT(4)
+#  define F_CHG_ACT                    BIT(3)
+
+/* Interrupt Status */
+#define UCS1002_REG_INTERRUPT_STATUS   0x10
+#  define F_DISCHARGE_ERR              BIT(6)
+#  define F_RESET                      BIT(5)
+#  define F_MIN_KEEP_OUT               BIT(4)
+#  define F_TSD                                BIT(3)
+#  define F_OVER_VOLT                  BIT(2)
+#  define F_BACK_VOLT                  BIT(1)
+#  define F_OVER_ILIM                  BIT(0)
+
+/* Pin Status Register */
+#define UCS1002_REG_PIN_STATUS         0x14
+#  define UCS1002_PWR_STATE_MASK       0x03
+#  define F_PWR_EN_PIN                 BIT(6)
+#  define F_M2_PIN                     BIT(5)
+#  define F_M1_PIN                     BIT(4)
+#  define F_EM_EN_PIN                  BIT(3)
+#  define F_SEL_PIN                    BIT(2)
+#  define F_ACTIVE_MODE_MASK           GENMASK(5, 3)
+#  define F_ACTIVE_MODE_PASSTHROUGH    F_M2_PIN
+#  define F_ACTIVE_MODE_DEDICATED      F_EM_EN_PIN
+#  define F_ACTIVE_MODE_BC12_DCP       (F_M2_PIN | F_EM_EN_PIN)
+#  define F_ACTIVE_MODE_BC12_SDP       F_M1_PIN
+#  define F_ACTIVE_MODE_BC12_CDP       (F_M1_PIN | F_M2_PIN | F_EM_EN_PIN)
+
+/* General Configuration Register */
+#define UCS1002_REG_GENERAL_CFG                0x15
+#  define F_RATION_EN                  BIT(3)
+
+/* Emulation Configuration Register */
+#define UCS1002_REG_EMU_CFG            0x16
+
+/* Switch Configuration Register */
+#define UCS1002_REG_SWITCH_CFG         0x17
+#  define F_PIN_IGNORE                 BIT(7)
+#  define F_EM_EN_SET                  BIT(5)
+#  define F_M2_SET                     BIT(4)
+#  define F_M1_SET                     BIT(3)
+#  define F_S0_SET                     BIT(2)
+#  define F_PWR_EN_SET                 BIT(1)
+#  define F_LATCH_SET                  BIT(0)
+#  define V_SET_ACTIVE_MODE_MASK       GENMASK(5, 3)
+#  define V_SET_ACTIVE_MODE_PASSTHROUGH        F_M2_SET
+#  define V_SET_ACTIVE_MODE_DEDICATED  F_EM_EN_SET
+#  define V_SET_ACTIVE_MODE_BC12_DCP   (F_M2_SET | F_EM_EN_SET)
+#  define V_SET_ACTIVE_MODE_BC12_SDP   F_M1_SET
+#  define V_SET_ACTIVE_MODE_BC12_CDP   (F_M1_SET | F_M2_SET | F_EM_EN_SET)
+
+/* Current Limit Register */
+#define UCS1002_REG_ILIMIT             0x19
+#  define UCS1002_ILIM_SW_MASK         GENMASK(3, 0)
+
+/* Product ID */
+#define UCS1002_REG_PRODUCT_ID         0xfd
+#  define UCS1002_PRODUCT_ID           0x4e
+
+/* Manufacture name */
+#define UCS1002_MANUFACTURER           "SMSC"
+
+struct ucs1002_info {
+       struct power_supply *charger;
+       struct i2c_client *client;
+       struct regmap *regmap;
+       struct regulator_desc *regulator_descriptor;
+       bool present;
+};
+
+static enum power_supply_property ucs1002_props[] = {
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_CHARGE_NOW,
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_CURRENT_MAX,
+       POWER_SUPPLY_PROP_PRESENT, /* the presence of PED */
+       POWER_SUPPLY_PROP_MANUFACTURER,
+       POWER_SUPPLY_PROP_USB_TYPE,
+       POWER_SUPPLY_PROP_HEALTH,
+};
+
+static int ucs1002_get_online(struct ucs1002_info *info,
+                             union power_supply_propval *val)
+{
+       unsigned int reg;
+       int ret;
+
+       ret = regmap_read(info->regmap, UCS1002_REG_OTHER_STATUS, &reg);
+       if (ret)
+               return ret;
+
+       val->intval = !!(reg & F_CHG_ACT);
+
+       return 0;
+}
+
+static int ucs1002_get_charge(struct ucs1002_info *info,
+                             union power_supply_propval *val)
+{
+       /*
+        * To fit within 32 bits some values are rounded (uA/h)
+        *
+        * For Total Accumulated Charge Middle Low Byte register, addr
+        * 03h, byte 2
+        *
+        *   B0: 0.01084 mA/h rounded to 11 uA/h
+        *   B1: 0.02169 mA/h rounded to 22 uA/h
+        *   B2: 0.04340 mA/h rounded to 43 uA/h
+        *   B3: 0.08676 mA/h rounded to 87 uA/h
+        *   B4: 0.17350 mA/h rounded to 173 uÁ/h
+        *
+        * For Total Accumulated Charge Low Byte register, addr 04h,
+        * byte 3
+        *
+        *   B6: 0.00271 mA/h rounded to 3 uA/h
+        *   B7: 0.005422 mA/h rounded to 5 uA/h
+        */
+       static const int bit_weights_uAh[BITS_PER_TYPE(u32)] = {
+               /*
+                * Bit corresponding to low byte (offset 0x04)
+                * B0 B1 B2 B3 B4 B5 B6 B7
+                */
+               0, 0, 0, 0, 0, 0, 3, 5,
+               /*
+                * Bit corresponding to middle low byte (offset 0x03)
+                * B0 B1 B2 B3 B4 B5 B6 B7
+                */
+               11, 22, 43, 87, 173, 347, 694, 1388,
+               /*
+                * Bit corresponding to middle high byte (offset 0x02)
+                * B0 B1 B2 B3 B4 B5 B6 B7
+                */
+               2776, 5552, 11105, 22210, 44420, 88840, 177700, 355400,
+               /*
+                * Bit corresponding to high byte (offset 0x01)
+                * B0 B1 B2 B3 B4 B5 B6 B7
+                */
+               710700, 1421000, 2843000, 5685000, 11371000, 22742000,
+               45484000, 90968000,
+       };
+       unsigned long total_acc_charger;
+       unsigned int reg;
+       int i, ret;
+
+       ret = regmap_bulk_read(info->regmap, UCS1002_REG_TOTAL_ACC_CHARGE,
+                              &reg, sizeof(u32));
+       if (ret)
+               return ret;
+
+       total_acc_charger = be32_to_cpu(reg); /* BE as per offsets above */
+       val->intval = 0;
+
+       for_each_set_bit(i, &total_acc_charger, ARRAY_SIZE(bit_weights_uAh))
+               val->intval += bit_weights_uAh[i];
+
+       return 0;
+}
+
+static int ucs1002_get_current(struct ucs1002_info *info,
+                              union power_supply_propval *val)
+{
+       /*
+        * The Current Measurement register stores the measured
+        * current value delivered to the portable device. The range
+        * is from 9.76 mA to 2.5 A.
+        */
+       static const int bit_weights_uA[BITS_PER_TYPE(u8)] = {
+               9760, 19500, 39000, 78100, 156200, 312300, 624600, 1249300,
+       };
+       unsigned long current_measurement;
+       unsigned int reg;
+       int i, ret;
+
+       ret = regmap_read(info->regmap, UCS1002_REG_CURRENT_MEASUREMENT, &reg);
+       if (ret)
+               return ret;
+
+       current_measurement = reg;
+       val->intval = 0;
+
+       for_each_set_bit(i, &current_measurement, ARRAY_SIZE(bit_weights_uA))
+               val->intval += bit_weights_uA[i];
+
+       return 0;
+}
+
+/*
+ * The Current Limit register stores the maximum current used by the
+ * port switch. The range is from 500mA to 2.5 A.
+ */
+static const u32 ucs1002_current_limit_uA[] = {
+       500000, 900000, 1000000, 1200000, 1500000, 1800000, 2000000, 2500000,
+};
+
+static int ucs1002_get_max_current(struct ucs1002_info *info,
+                                  union power_supply_propval *val)
+{
+       unsigned int reg;
+       int ret;
+
+       ret = regmap_read(info->regmap, UCS1002_REG_ILIMIT, &reg);
+       if (ret)
+               return ret;
+
+       val->intval = ucs1002_current_limit_uA[reg & UCS1002_ILIM_SW_MASK];
+
+       return 0;
+}
+
+static int ucs1002_set_max_current(struct ucs1002_info *info, u32 val)
+{
+       unsigned int reg;
+       int ret, idx;
+
+       for (idx = 0; idx < ARRAY_SIZE(ucs1002_current_limit_uA); idx++) {
+               if (val == ucs1002_current_limit_uA[idx])
+                       break;
+       }
+
+       if (idx == ARRAY_SIZE(ucs1002_current_limit_uA))
+               return -EINVAL;
+
+       ret = regmap_write(info->regmap, UCS1002_REG_ILIMIT, idx);
+       if (ret)
+               return ret;
+       /*
+        * Any current limit setting exceeding the one set via ILIM
+        * pin will be rejected, so we read out freshly changed limit
+        * to make sure that it took effect.
+        */
+       ret = regmap_read(info->regmap, UCS1002_REG_ILIMIT, &reg);
+       if (ret)
+               return ret;
+
+       if (reg != idx)
+               return -EINVAL;
+
+       return 0;
+}
+
+static enum power_supply_usb_type ucs1002_usb_types[] = {
+       POWER_SUPPLY_USB_TYPE_PD,
+       POWER_SUPPLY_USB_TYPE_SDP,
+       POWER_SUPPLY_USB_TYPE_DCP,
+       POWER_SUPPLY_USB_TYPE_CDP,
+       POWER_SUPPLY_USB_TYPE_UNKNOWN,
+};
+
+static int ucs1002_set_usb_type(struct ucs1002_info *info, int val)
+{
+       unsigned int mode;
+
+       if (val < 0 || val >= ARRAY_SIZE(ucs1002_usb_types))
+               return -EINVAL;
+
+       switch (ucs1002_usb_types[val]) {
+       case POWER_SUPPLY_USB_TYPE_PD:
+               mode = V_SET_ACTIVE_MODE_DEDICATED;
+               break;
+       case POWER_SUPPLY_USB_TYPE_SDP:
+               mode = V_SET_ACTIVE_MODE_BC12_SDP;
+               break;
+       case POWER_SUPPLY_USB_TYPE_DCP:
+               mode = V_SET_ACTIVE_MODE_BC12_DCP;
+               break;
+       case POWER_SUPPLY_USB_TYPE_CDP:
+               mode = V_SET_ACTIVE_MODE_BC12_CDP;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return regmap_update_bits(info->regmap, UCS1002_REG_SWITCH_CFG,
+                                 V_SET_ACTIVE_MODE_MASK, mode);
+}
+
+static int ucs1002_get_usb_type(struct ucs1002_info *info,
+                               union power_supply_propval *val)
+{
+       enum power_supply_usb_type type;
+       unsigned int reg;
+       int ret;
+
+       ret = regmap_read(info->regmap, UCS1002_REG_PIN_STATUS, &reg);
+       if (ret)
+               return ret;
+
+       switch (reg & F_ACTIVE_MODE_MASK) {
+       default:
+               type = POWER_SUPPLY_USB_TYPE_UNKNOWN;
+               break;
+       case F_ACTIVE_MODE_DEDICATED:
+               type = POWER_SUPPLY_USB_TYPE_PD;
+               break;
+       case F_ACTIVE_MODE_BC12_SDP:
+               type = POWER_SUPPLY_USB_TYPE_SDP;
+               break;
+       case F_ACTIVE_MODE_BC12_DCP:
+               type = POWER_SUPPLY_USB_TYPE_DCP;
+               break;
+       case F_ACTIVE_MODE_BC12_CDP:
+               type = POWER_SUPPLY_USB_TYPE_CDP;
+               break;
+       };
+
+       val->intval = type;
+
+       return 0;
+}
+
+static int ucs1002_get_health(struct ucs1002_info *info,
+                             union power_supply_propval *val)
+{
+       unsigned int reg;
+       int ret, health;
+
+       ret = regmap_read(info->regmap, UCS1002_REG_INTERRUPT_STATUS, &reg);
+       if (ret)
+               return ret;
+
+       if (reg & F_TSD)
+               health = POWER_SUPPLY_HEALTH_OVERHEAT;
+       else if (reg & (F_OVER_VOLT | F_BACK_VOLT))
+               health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+       else if (reg & F_OVER_ILIM)
+               health = POWER_SUPPLY_HEALTH_OVERCURRENT;
+       else if (reg & (F_DISCHARGE_ERR | F_MIN_KEEP_OUT))
+               health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+       else
+               health = POWER_SUPPLY_HEALTH_GOOD;
+
+       val->intval = health;
+
+       return 0;
+}
+
+static int ucs1002_get_property(struct power_supply *psy,
+                               enum power_supply_property psp,
+                               union power_supply_propval *val)
+{
+       struct ucs1002_info *info = power_supply_get_drvdata(psy);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               return ucs1002_get_online(info, val);
+       case POWER_SUPPLY_PROP_CHARGE_NOW:
+               return ucs1002_get_charge(info, val);
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               return ucs1002_get_current(info, val);
+       case POWER_SUPPLY_PROP_CURRENT_MAX:
+               return ucs1002_get_max_current(info, val);
+       case POWER_SUPPLY_PROP_USB_TYPE:
+               return ucs1002_get_usb_type(info, val);
+       case POWER_SUPPLY_PROP_HEALTH:
+               return ucs1002_get_health(info, val);
+       case POWER_SUPPLY_PROP_PRESENT:
+               val->intval = info->present;
+               return 0;
+       case POWER_SUPPLY_PROP_MANUFACTURER:
+               val->strval = UCS1002_MANUFACTURER;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int ucs1002_set_property(struct power_supply *psy,
+                               enum power_supply_property psp,
+                               const union power_supply_propval *val)
+{
+       struct ucs1002_info *info = power_supply_get_drvdata(psy);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_CURRENT_MAX:
+               return ucs1002_set_max_current(info, val->intval);
+       case POWER_SUPPLY_PROP_USB_TYPE:
+               return ucs1002_set_usb_type(info, val->intval);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int ucs1002_property_is_writeable(struct power_supply *psy,
+                                        enum power_supply_property psp)
+{
+       switch (psp) {
+       case POWER_SUPPLY_PROP_CURRENT_MAX:
+       case POWER_SUPPLY_PROP_USB_TYPE:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static const struct power_supply_desc ucs1002_charger_desc = {
+       .name                   = "ucs1002",
+       .type                   = POWER_SUPPLY_TYPE_USB,
+       .usb_types              = ucs1002_usb_types,
+       .num_usb_types          = ARRAY_SIZE(ucs1002_usb_types),
+       .get_property           = ucs1002_get_property,
+       .set_property           = ucs1002_set_property,
+       .property_is_writeable  = ucs1002_property_is_writeable,
+       .properties             = ucs1002_props,
+       .num_properties         = ARRAY_SIZE(ucs1002_props),
+};
+
+static irqreturn_t ucs1002_charger_irq(int irq, void *data)
+{
+       int ret, regval;
+       bool present;
+       struct ucs1002_info *info = data;
+
+       present = info->present;
+
+       ret = regmap_read(info->regmap, UCS1002_REG_OTHER_STATUS, &regval);
+       if (ret)
+               return IRQ_HANDLED;
+
+       /* update attached status */
+       info->present = regval & F_ADET_PIN;
+
+       /* notify the change */
+       if (present != info->present)
+               power_supply_changed(info->charger);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t ucs1002_alert_irq(int irq, void *data)
+{
+       struct ucs1002_info *info = data;
+
+       power_supply_changed(info->charger);
+
+       return IRQ_HANDLED;
+}
+
+static const struct regulator_ops ucs1002_regulator_ops = {
+       .is_enabled     = regulator_is_enabled_regmap,
+       .enable         = regulator_enable_regmap,
+       .disable        = regulator_disable_regmap,
+};
+
+static const struct regulator_desc ucs1002_regulator_descriptor = {
+       .name           = "ucs1002-vbus",
+       .ops            = &ucs1002_regulator_ops,
+       .type           = REGULATOR_VOLTAGE,
+       .owner          = THIS_MODULE,
+       .enable_reg     = UCS1002_REG_SWITCH_CFG,
+       .enable_mask    = F_PWR_EN_SET,
+       .enable_val     = F_PWR_EN_SET,
+       .fixed_uV       = 5000000,
+       .n_voltages     = 1,
+};
+
+static int ucs1002_probe(struct i2c_client *client,
+                        const struct i2c_device_id *dev_id)
+{
+       struct device *dev = &client->dev;
+       struct power_supply_config charger_config = {};
+       const struct regmap_config regmap_config = {
+               .reg_bits = 8,
+               .val_bits = 8,
+       };
+       struct regulator_config regulator_config = {};
+       int irq_a_det, irq_alert, ret;
+       struct regulator_dev *rdev;
+       struct ucs1002_info *info;
+       unsigned int regval;
+
+       info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       info->regmap = devm_regmap_init_i2c(client, &regmap_config);
+       ret = PTR_ERR_OR_ZERO(info->regmap);
+       if (ret) {
+               dev_err(dev, "Regmap initialization failed: %d\n", ret);
+               return ret;
+       }
+
+       info->client = client;
+
+       irq_a_det = of_irq_get_byname(dev->of_node, "a_det");
+       irq_alert = of_irq_get_byname(dev->of_node, "alert");
+
+       charger_config.of_node = dev->of_node;
+       charger_config.drv_data = info;
+
+       ret = regmap_read(info->regmap, UCS1002_REG_PRODUCT_ID, &regval);
+       if (ret) {
+               dev_err(dev, "Failed to read product ID: %d\n", ret);
+               return ret;
+       }
+
+       if (regval != UCS1002_PRODUCT_ID) {
+               dev_err(dev,
+                       "Product ID does not match (0x%02x != 0x%02x)\n",
+                       regval, UCS1002_PRODUCT_ID);
+               return -ENODEV;
+       }
+
+       /* Enable charge rationing by default */
+       ret = regmap_update_bits(info->regmap, UCS1002_REG_GENERAL_CFG,
+                                F_RATION_EN, F_RATION_EN);
+       if (ret) {
+               dev_err(dev, "Failed to read general config: %d\n", ret);
+               return ret;
+       }
+
+       /*
+        * Ignore the M1, M2, PWR_EN, and EM_EN pin states. Set active
+        * mode selection to BC1.2 CDP.
+        */
+       ret = regmap_update_bits(info->regmap, UCS1002_REG_SWITCH_CFG,
+                                V_SET_ACTIVE_MODE_MASK | F_PIN_IGNORE,
+                                V_SET_ACTIVE_MODE_BC12_CDP | F_PIN_IGNORE);
+       if (ret) {
+               dev_err(dev, "Failed to configure default mode: %d\n", ret);
+               return ret;
+       }
+       /*
+        * Be safe and set initial current limit to 500mA
+        */
+       ret = ucs1002_set_max_current(info, 500000);
+       if (ret) {
+               dev_err(dev, "Failed to set max current default: %d\n", ret);
+               return ret;
+       }
+
+       info->charger = devm_power_supply_register(dev, &ucs1002_charger_desc,
+                                                  &charger_config);
+       ret = PTR_ERR_OR_ZERO(info->charger);
+       if (ret) {
+               dev_err(dev, "Failed to register power supply: %d\n", ret);
+               return ret;
+       }
+
+       ret = regmap_read(info->regmap, UCS1002_REG_PIN_STATUS, &regval);
+       if (ret) {
+               dev_err(dev, "Failed to read pin status: %d\n", ret);
+               return ret;
+       }
+
+       info->regulator_descriptor =
+               devm_kmemdup(dev, &ucs1002_regulator_descriptor,
+                            sizeof(ucs1002_regulator_descriptor),
+                            GFP_KERNEL);
+       if (!info->regulator_descriptor)
+               return -ENOMEM;
+
+       info->regulator_descriptor->enable_is_inverted = !(regval & F_SEL_PIN);
+
+       regulator_config.dev = dev;
+       regulator_config.of_node = dev->of_node;
+       regulator_config.regmap = info->regmap;
+
+       rdev = devm_regulator_register(dev, info->regulator_descriptor,
+                                      &regulator_config);
+       ret = PTR_ERR_OR_ZERO(rdev);
+       if (ret) {
+               dev_err(dev, "Failed to register VBUS regulator: %d\n", ret);
+               return ret;
+       }
+
+       if (irq_a_det > 0) {
+               ret = devm_request_threaded_irq(dev, irq_a_det, NULL,
+                                               ucs1002_charger_irq,
+                                               IRQF_ONESHOT,
+                                               "ucs1002-a_det", info);
+               if (ret) {
+                       dev_err(dev, "Failed to request A_DET threaded irq: %d\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       if (irq_alert > 0) {
+               ret = devm_request_threaded_irq(dev, irq_alert, NULL,
+                                               ucs1002_alert_irq,
+                                               IRQF_ONESHOT,
+                                               "ucs1002-alert", info);
+               if (ret) {
+                       dev_err(dev, "Failed to request ALERT threaded irq: %d\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static const struct of_device_id ucs1002_of_match[] = {
+       { .compatible = "microchip,ucs1002", },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ucs1002_of_match);
+
+static struct i2c_driver ucs1002_driver = {
+       .driver = {
+                  .name = "ucs1002",
+                  .of_match_table = ucs1002_of_match,
+       },
+       .probe = ucs1002_probe,
+};
+module_i2c_driver(ucs1002_driver);
+
+MODULE_DESCRIPTION("Microchip UCS1002 Programmable USB Port Power Controller");
+MODULE_AUTHOR("Enric Balletbo Serra <enric.balletbo@collabora.com>");
+MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
+MODULE_LICENSE("GPL");
index dd5d110..4b64180 100644 (file)
 #include <linux/slab.h>
 #include <linux/pps_kernel.h>
 #include <linux/pps-gpio.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/list.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
 
 /* Info for each registered platform device */
 struct pps_gpio_device_data {
        int irq;                        /* IRQ used as PPS source */
        struct pps_device *pps;         /* PPS source device */
        struct pps_source_info info;    /* PPS source information */
+       struct gpio_desc *gpio_pin;     /* GPIO port descriptors */
+       struct gpio_desc *echo_pin;
+       struct timer_list echo_timer;   /* timer to reset echo active state */
        bool assert_falling_edge;
        bool capture_clear;
-       unsigned int gpio_pin;
+       unsigned int echo_active_ms;    /* PPS echo active duration */
+       unsigned long echo_timeout;     /* timer timeout value in jiffies */
 };
 
 /*
@@ -61,18 +67,101 @@ static irqreturn_t pps_gpio_irq_handler(int irq, void *data)
 
        info = data;
 
-       rising_edge = gpio_get_value(info->gpio_pin);
+       rising_edge = gpiod_get_value(info->gpio_pin);
        if ((rising_edge && !info->assert_falling_edge) ||
                        (!rising_edge && info->assert_falling_edge))
-               pps_event(info->pps, &ts, PPS_CAPTUREASSERT, NULL);
+               pps_event(info->pps, &ts, PPS_CAPTUREASSERT, data);
        else if (info->capture_clear &&
                        ((rising_edge && info->assert_falling_edge) ||
-                        (!rising_edge && !info->assert_falling_edge)))
-               pps_event(info->pps, &ts, PPS_CAPTURECLEAR, NULL);
+                       (!rising_edge && !info->assert_falling_edge)))
+               pps_event(info->pps, &ts, PPS_CAPTURECLEAR, data);
 
        return IRQ_HANDLED;
 }
 
+/* This function will only be called when an ECHO GPIO is defined */
+static void pps_gpio_echo(struct pps_device *pps, int event, void *data)
+{
+       /* add_timer() needs to write into info->echo_timer */
+       struct pps_gpio_device_data *info = data;
+
+       switch (event) {
+       case PPS_CAPTUREASSERT:
+               if (pps->params.mode & PPS_ECHOASSERT)
+                       gpiod_set_value(info->echo_pin, 1);
+               break;
+
+       case PPS_CAPTURECLEAR:
+               if (pps->params.mode & PPS_ECHOCLEAR)
+                       gpiod_set_value(info->echo_pin, 1);
+               break;
+       }
+
+       /* fire the timer */
+       if (info->pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) {
+               info->echo_timer.expires = jiffies + info->echo_timeout;
+               add_timer(&info->echo_timer);
+       }
+}
+
+/* Timer callback to reset the echo pin to the inactive state */
+static void pps_gpio_echo_timer_callback(struct timer_list *t)
+{
+       const struct pps_gpio_device_data *info;
+
+       info = from_timer(info, t, echo_timer);
+
+       gpiod_set_value(info->echo_pin, 0);
+}
+
+static int pps_gpio_setup(struct platform_device *pdev)
+{
+       struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
+       struct device_node *np = pdev->dev.of_node;
+       int ret;
+       u32 value;
+
+       data->gpio_pin = devm_gpiod_get(&pdev->dev,
+               NULL,   /* request "gpios" */
+               GPIOD_IN);
+       if (IS_ERR(data->gpio_pin)) {
+               dev_err(&pdev->dev,
+                       "failed to request PPS GPIO\n");
+               return PTR_ERR(data->gpio_pin);
+       }
+
+       data->echo_pin = devm_gpiod_get_optional(&pdev->dev,
+                       "echo",
+                       GPIOD_OUT_LOW);
+       if (data->echo_pin) {
+               if (IS_ERR(data->echo_pin)) {
+                       dev_err(&pdev->dev, "failed to request ECHO GPIO\n");
+                       return PTR_ERR(data->echo_pin);
+               }
+
+               ret = of_property_read_u32(np,
+                       "echo-active-ms",
+                       &value);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "failed to get echo-active-ms from OF\n");
+                       return ret;
+               }
+               data->echo_active_ms = value;
+               /* sanity check on echo_active_ms */
+               if (!data->echo_active_ms || data->echo_active_ms > 999) {
+                       dev_err(&pdev->dev,
+                               "echo-active-ms: %u - bad value from OF\n",
+                               data->echo_active_ms);
+                       return -EINVAL;
+               }
+       }
+
+       if (of_property_read_bool(np, "assert-falling-edge"))
+               data->assert_falling_edge = true;
+       return 0;
+}
+
 static unsigned long
 get_irqf_trigger_flags(const struct pps_gpio_device_data *data)
 {
@@ -90,53 +179,32 @@ get_irqf_trigger_flags(const struct pps_gpio_device_data *data)
 static int pps_gpio_probe(struct platform_device *pdev)
 {
        struct pps_gpio_device_data *data;
-       const char *gpio_label;
        int ret;
        int pps_default_params;
        const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data;
-       struct device_node *np = pdev->dev.of_node;
 
        /* allocate space for device info */
-       data = devm_kzalloc(&pdev->dev, sizeof(struct pps_gpio_device_data),
-                       GFP_KERNEL);
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
+       platform_set_drvdata(pdev, data);
 
+       /* GPIO setup */
        if (pdata) {
                data->gpio_pin = pdata->gpio_pin;
-               gpio_label = pdata->gpio_label;
+               data->echo_pin = pdata->echo_pin;
 
                data->assert_falling_edge = pdata->assert_falling_edge;
                data->capture_clear = pdata->capture_clear;
+               data->echo_active_ms = pdata->echo_active_ms;
        } else {
-               ret = of_get_gpio(np, 0);
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "failed to get GPIO from device tree\n");
-                       return ret;
-               }
-               data->gpio_pin = ret;
-               gpio_label = PPS_GPIO_NAME;
-
-               if (of_get_property(np, "assert-falling-edge", NULL))
-                       data->assert_falling_edge = true;
-       }
-
-       /* GPIO setup */
-       ret = devm_gpio_request(&pdev->dev, data->gpio_pin, gpio_label);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to request GPIO %u\n",
-                       data->gpio_pin);
-               return ret;
-       }
-
-       ret = gpio_direction_input(data->gpio_pin);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to set pin direction\n");
-               return -EINVAL;
+               ret = pps_gpio_setup(pdev);
+               if (ret)
+                       return -EINVAL;
        }
 
        /* IRQ setup */
-       ret = gpio_to_irq(data->gpio_pin);
+       ret = gpiod_to_irq(data->gpio_pin);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to map GPIO to IRQ: %d\n", ret);
                return -EINVAL;
@@ -152,6 +220,11 @@ static int pps_gpio_probe(struct platform_device *pdev)
        data->info.owner = THIS_MODULE;
        snprintf(data->info.name, PPS_MAX_NAME_LEN - 1, "%s.%d",
                 pdev->name, pdev->id);
+       if (data->echo_pin) {
+               data->info.echo = pps_gpio_echo;
+               data->echo_timeout = msecs_to_jiffies(data->echo_active_ms);
+               timer_setup(&data->echo_timer, pps_gpio_echo_timer_callback, 0);
+       }
 
        /* register PPS source */
        pps_default_params = PPS_CAPTUREASSERT | PPS_OFFSETASSERT;
@@ -173,7 +246,6 @@ static int pps_gpio_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       platform_set_drvdata(pdev, data);
        dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n",
                 data->irq);
 
@@ -185,6 +257,11 @@ static int pps_gpio_remove(struct platform_device *pdev)
        struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
 
        pps_unregister_source(data->pps);
+       if (data->echo_pin) {
+               del_timer_sync(&data->echo_timer);
+               /* reset echo pin in any case */
+               gpiod_set_value(data->echo_pin, 0);
+       }
        dev_info(&pdev->dev, "removed IRQ %d as PPS source\n", data->irq);
        return 0;
 }
@@ -209,4 +286,4 @@ MODULE_AUTHOR("Ricardo Martins <rasm@fe.up.pt>");
 MODULE_AUTHOR("James Nuss <jamesnuss@nanometrics.ca>");
 MODULE_DESCRIPTION("Use GPIO pin as PPS source");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0.0");
+MODULE_VERSION("1.2.0");
index bbf10ae..fa16858 100644 (file)
@@ -35,7 +35,7 @@
 
 #include <asm/div64.h>
 
-#include <mach/platform.h>     /* for ep93xx_pwm_{acquire,release}_gpio() */
+#include <linux/soc/cirrus/ep93xx.h>   /* for ep93xx_pwm_{acquire,release}_gpio() */
 
 #define EP93XX_PWMx_TERM_COUNT 0x00
 #define EP93XX_PWMx_DUTY_CYCLE 0x04
index 1e1f42e..4a4a75f 100644 (file)
@@ -868,7 +868,9 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode,
 
                pinned = get_user_pages_fast(
                                (unsigned long)xfer->loc_addr & PAGE_MASK,
-                               nr_pages, dir == DMA_FROM_DEVICE, page_list);
+                               nr_pages,
+                               dir == DMA_FROM_DEVICE ? FOLL_WRITE : 0,
+                               page_list);
 
                if (pinned != nr_pages) {
                        if (pinned < 0) {
index cf45829..b29fc25 100644 (file)
@@ -2147,6 +2147,14 @@ static int riocm_add_mport(struct device *dev,
        mutex_init(&cm->rx_lock);
        riocm_rx_fill(cm, RIOCM_RX_RING_SIZE);
        cm->rx_wq = create_workqueue(DRV_NAME "/rxq");
+       if (!cm->rx_wq) {
+               riocm_error("failed to allocate IBMBOX_%d on %s",
+                           cmbox, mport->name);
+               rio_release_outb_mbox(mport, cmbox);
+               kfree(cm);
+               return -ENOMEM;
+       }
+
        INIT_WORK(&cm->rx_work, rio_ibmsg_handler);
 
        cm->tx_slot = 0;
index 2ef1f13..99e75d9 100644 (file)
@@ -79,11 +79,11 @@ static int zynqmp_reset_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
-       platform_set_drvdata(pdev, priv);
-
        priv->eemi_ops = zynqmp_pm_get_eemi_ops();
-       if (!priv->eemi_ops)
-               return -ENXIO;
+       if (IS_ERR(priv->eemi_ops))
+               return PTR_ERR(priv->eemi_ops);
+
+       platform_set_drvdata(pdev, priv);
 
        priv->rcdev.ops = &zynqmp_reset_ops;
        priv->rcdev.owner = THIS_MODULE;
index 32994b0..a2941c8 100644 (file)
@@ -403,15 +403,12 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 
 static struct omap_rtc *omap_rtc_power_off_rtc;
 
-/*
- * omap_rtc_poweroff: RTC-controlled power off
- *
- * The RTC can be used to control an external PMIC via the pmic_power_en pin,
- * which can be configured to transition to OFF on ALARM2 events.
- *
- * Called with local interrupts disabled.
+/**
+ * omap_rtc_power_off_program: Set the pmic power off sequence. The RTC
+ * generates pmic_pwr_enable control, which can be used to control an external
+ * PMIC.
  */
-static void omap_rtc_power_off(void)
+int omap_rtc_power_off_program(struct device *dev)
 {
        struct omap_rtc *rtc = omap_rtc_power_off_rtc;
        struct rtc_time tm;
@@ -425,6 +422,9 @@ static void omap_rtc_power_off(void)
        rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN);
 
 again:
+       /* Clear any existing ALARM2 event */
+       rtc_writel(rtc, OMAP_RTC_STATUS_REG, OMAP_RTC_STATUS_ALARM2);
+
        /* set alarm one second from now */
        omap_rtc_read_time_raw(rtc, &tm);
        seconds = tm.tm_sec;
@@ -461,6 +461,39 @@ again:
 
        rtc->type->lock(rtc);
 
+       return 0;
+}
+EXPORT_SYMBOL(omap_rtc_power_off_program);
+
+/*
+ * omap_rtc_poweroff: RTC-controlled power off
+ *
+ * The RTC can be used to control an external PMIC via the pmic_power_en pin,
+ * which can be configured to transition to OFF on ALARM2 events.
+ *
+ * Notes:
+ * The one-second alarm offset is the shortest offset possible as the alarm
+ * registers must be set before the next timer update and the offset
+ * calculation is too heavy for everything to be done within a single access
+ * period (~15 us).
+ *
+ * Called with local interrupts disabled.
+ */
+static void omap_rtc_power_off(void)
+{
+       struct rtc_device *rtc = omap_rtc_power_off_rtc->rtc;
+       u32 val;
+
+       omap_rtc_power_off_program(rtc->dev.parent);
+
+       /* Set PMIC power enable and EXT_WAKEUP in case PB power on is used */
+       omap_rtc_power_off_rtc->type->unlock(omap_rtc_power_off_rtc);
+       val = rtc_readl(omap_rtc_power_off_rtc, OMAP_RTC_PMIC_REG);
+       val |= OMAP_RTC_PMIC_POWER_EN_EN | OMAP_RTC_PMIC_EXT_WKUP_POL(0) |
+                       OMAP_RTC_PMIC_EXT_WKUP_EN(0);
+       rtc_writel(omap_rtc_power_off_rtc, OMAP_RTC_PMIC_REG, val);
+       omap_rtc_power_off_rtc->type->lock(omap_rtc_power_off_rtc);
+
        /*
         * Wait for alarm to trigger (within one second) and external PMIC to
         * power off the system. Add a 500 ms margin for external latencies
index f89f9d0..c09039e 100644 (file)
@@ -3827,7 +3827,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev,
        if ((start_padding_sectors || end_padding_sectors) &&
            (rq_data_dir(req) == WRITE)) {
                DBF_DEV_EVENT(DBF_ERR, basedev,
-                             "raw write not track aligned (%lu,%lu) req %p",
+                             "raw write not track aligned (%llu,%llu) req %p",
                              start_padding_sectors, end_padding_sectors, req);
                return ERR_PTR(-EINVAL);
        }
index 991420c..6a30768 100644 (file)
@@ -66,6 +66,7 @@ struct virtio_ccw_device {
        bool device_lost;
        unsigned int config_ready;
        void *airq_info;
+       u64 dma_mask;
 };
 
 struct vq_info_block_legacy {
@@ -108,7 +109,6 @@ struct virtio_rev_info {
 struct virtio_ccw_vq_info {
        struct virtqueue *vq;
        int num;
-       void *queue;
        union {
                struct vq_info_block s;
                struct vq_info_block_legacy l;
@@ -423,7 +423,6 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw)
        struct virtio_ccw_device *vcdev = to_vc_device(vq->vdev);
        struct virtio_ccw_vq_info *info = vq->priv;
        unsigned long flags;
-       unsigned long size;
        int ret;
        unsigned int index = vq->index;
 
@@ -461,8 +460,6 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw)
                         ret, index);
 
        vring_del_virtqueue(vq);
-       size = PAGE_ALIGN(vring_size(info->num, KVM_VIRTIO_CCW_RING_ALIGN));
-       free_pages_exact(info->queue, size);
        kfree(info->info_block);
        kfree(info);
 }
@@ -494,8 +491,9 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
        int err;
        struct virtqueue *vq = NULL;
        struct virtio_ccw_vq_info *info;
-       unsigned long size = 0; /* silence the compiler */
+       u64 queue;
        unsigned long flags;
+       bool may_reduce;
 
        /* Allocate queue. */
        info = kzalloc(sizeof(struct virtio_ccw_vq_info), GFP_KERNEL);
@@ -516,37 +514,34 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
                err = info->num;
                goto out_err;
        }
-       size = PAGE_ALIGN(vring_size(info->num, KVM_VIRTIO_CCW_RING_ALIGN));
-       info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
-       if (info->queue == NULL) {
-               dev_warn(&vcdev->cdev->dev, "no queue\n");
-               err = -ENOMEM;
-               goto out_err;
-       }
+       may_reduce = vcdev->revision > 0;
+       vq = vring_create_virtqueue(i, info->num, KVM_VIRTIO_CCW_RING_ALIGN,
+                                   vdev, true, may_reduce, ctx,
+                                   virtio_ccw_kvm_notify, callback, name);
 
-       vq = vring_new_virtqueue(i, info->num, KVM_VIRTIO_CCW_RING_ALIGN, vdev,
-                                true, ctx, info->queue, virtio_ccw_kvm_notify,
-                                callback, name);
        if (!vq) {
                /* For now, we fail if we can't get the requested size. */
                dev_warn(&vcdev->cdev->dev, "no vq\n");
                err = -ENOMEM;
                goto out_err;
        }
+       /* it may have been reduced */
+       info->num = virtqueue_get_vring_size(vq);
 
        /* Register it with the host. */
+       queue = virtqueue_get_desc_addr(vq);
        if (vcdev->revision == 0) {
-               info->info_block->l.queue = (__u64)info->queue;
+               info->info_block->l.queue = queue;
                info->info_block->l.align = KVM_VIRTIO_CCW_RING_ALIGN;
                info->info_block->l.index = i;
                info->info_block->l.num = info->num;
                ccw->count = sizeof(info->info_block->l);
        } else {
-               info->info_block->s.desc = (__u64)info->queue;
+               info->info_block->s.desc = queue;
                info->info_block->s.index = i;
                info->info_block->s.num = info->num;
-               info->info_block->s.avail = (__u64)virtqueue_get_avail(vq);
-               info->info_block->s.used = (__u64)virtqueue_get_used(vq);
+               info->info_block->s.avail = (__u64)virtqueue_get_avail_addr(vq);
+               info->info_block->s.used = (__u64)virtqueue_get_used_addr(vq);
                ccw->count = sizeof(info->info_block->s);
        }
        ccw->cmd_code = CCW_CMD_SET_VQ;
@@ -572,8 +567,6 @@ out_err:
        if (vq)
                vring_del_virtqueue(vq);
        if (info) {
-               if (info->queue)
-                       free_pages_exact(info->queue, size);
                kfree(info->info_block);
        }
        kfree(info);
@@ -780,12 +773,8 @@ out_free:
 static void ccw_transport_features(struct virtio_device *vdev)
 {
        /*
-        * Packed ring isn't enabled on virtio_ccw for now,
-        * because virtio_ccw uses some legacy accessors,
-        * e.g. virtqueue_get_avail() and virtqueue_get_used()
-        * which aren't available in packed ring currently.
+        * Currently nothing to do here.
         */
-       __virtio_clear_bit(vdev, VIRTIO_F_RING_PACKED);
 }
 
 static int virtio_ccw_finalize_features(struct virtio_device *vdev)
@@ -1266,6 +1255,16 @@ static int virtio_ccw_online(struct ccw_device *cdev)
                ret = -ENOMEM;
                goto out_free;
        }
+
+       vcdev->vdev.dev.parent = &cdev->dev;
+       cdev->dev.dma_mask = &vcdev->dma_mask;
+       /* we are fine with common virtio infrastructure using 64 bit DMA */
+       ret = dma_set_mask_and_coherent(&cdev->dev, DMA_BIT_MASK(64));
+       if (ret) {
+               dev_warn(&cdev->dev, "Failed to enable 64-bit DMA.\n");
+               goto out_free;
+       }
+
        vcdev->config_block = kzalloc(sizeof(*vcdev->config_block),
                                   GFP_DMA | GFP_KERNEL);
        if (!vcdev->config_block) {
@@ -1280,7 +1279,6 @@ static int virtio_ccw_online(struct ccw_device *cdev)
 
        vcdev->is_thinint = virtio_ccw_use_airq; /* at least try */
 
-       vcdev->vdev.dev.parent = &cdev->dev;
        vcdev->vdev.dev.release = virtio_ccw_release_dev;
        vcdev->vdev.config = &virtio_ccw_config_ops;
        vcdev->cdev = cdev;
index acd9ba4..8090dc9 100644 (file)
@@ -437,7 +437,7 @@ static int dax_lock_page(void *va, struct page **p)
 
        dax_dbg("uva %p", va);
 
-       ret = get_user_pages_fast((unsigned long)va, 1, 1, p);
+       ret = get_user_pages_fast((unsigned long)va, 1, FOLL_WRITE, p);
        if (ret == 1) {
                dax_dbg("locked page %p, for VA %p", *p, va);
                return 0;
index 19c022e..3c6a18a 100644 (file)
@@ -4922,7 +4922,8 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
 
         /* Try to fault in all of the necessary pages */
         /* rw==READ means read from drive, write into memory area */
-       res = get_user_pages_fast(uaddr, nr_pages, rw == READ, pages);
+       res = get_user_pages_fast(uaddr, nr_pages, rw == READ ? FOLL_WRITE : 0,
+                                 pages);
 
        /* Errors and no page mapped should return here */
        if (res < nr_pages)
index e649cea..87d69e7 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/stat.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include "internals.h"
 
 static void __iomem *uimask;
index c07b4a8..75bdbb2 100644 (file)
@@ -2,10 +2,12 @@ menu "SOC (System On Chip) specific Drivers"
 
 source "drivers/soc/actions/Kconfig"
 source "drivers/soc/amlogic/Kconfig"
+source "drivers/soc/aspeed/Kconfig"
 source "drivers/soc/atmel/Kconfig"
 source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/fsl/Kconfig"
 source "drivers/soc/imx/Kconfig"
+source "drivers/soc/ixp4xx/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/renesas/Kconfig"
index 90b686e..524ecdc 100644 (file)
@@ -4,6 +4,7 @@
 #
 
 obj-$(CONFIG_ARCH_ACTIONS)     += actions/
+obj-$(CONFIG_SOC_ASPEED)       += aspeed/
 obj-$(CONFIG_ARCH_AT91)                += atmel/
 obj-y                          += bcm/
 obj-$(CONFIG_ARCH_DOVE)                += dove/
@@ -11,6 +12,7 @@ obj-$(CONFIG_MACH_DOVE)               += dove/
 obj-y                          += fsl/
 obj-$(CONFIG_ARCH_GEMINI)      += gemini/
 obj-$(CONFIG_ARCH_MXC)         += imx/
+obj-$(CONFIG_ARCH_IXP4XX)      += ixp4xx/
 obj-$(CONFIG_SOC_XWAY)         += lantiq/
 obj-y                          += mediatek/
 obj-y                          += amlogic/
index 6289965..511b685 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/bitfield.h>
 #include <linux/regmap.h>
 #include <linux/mfd/syscon.h>
+#include <linux/of_device.h>
 #include <linux/reset.h>
 #include <linux/clk.h>
 
@@ -26,6 +27,7 @@
 #define HHI_MEM_PD_REG0                        (0x40 << 2)
 #define HHI_VPU_MEM_PD_REG0            (0x41 << 2)
 #define HHI_VPU_MEM_PD_REG1            (0x42 << 2)
+#define HHI_VPU_MEM_PD_REG2            (0x4d << 2)
 
 struct meson_gx_pwrc_vpu {
        struct generic_pm_domain genpd;
@@ -54,12 +56,55 @@ static int meson_gx_pwrc_vpu_power_off(struct generic_pm_domain *genpd)
        /* Power Down Memories */
        for (i = 0; i < 32; i += 2) {
                regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
-                                  0x2 << i, 0x3 << i);
+                                  0x3 << i, 0x3 << i);
                udelay(5);
        }
        for (i = 0; i < 32; i += 2) {
                regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
-                                  0x2 << i, 0x3 << i);
+                                  0x3 << i, 0x3 << i);
+               udelay(5);
+       }
+       for (i = 8; i < 16; i++) {
+               regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0,
+                                  BIT(i), BIT(i));
+               udelay(5);
+       }
+       udelay(20);
+
+       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+                          GEN_PWR_VPU_HDMI, GEN_PWR_VPU_HDMI);
+
+       msleep(20);
+
+       clk_disable_unprepare(pd->vpu_clk);
+       clk_disable_unprepare(pd->vapb_clk);
+
+       return 0;
+}
+
+static int meson_g12a_pwrc_vpu_power_off(struct generic_pm_domain *genpd)
+{
+       struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd);
+       int i;
+
+       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+                          GEN_PWR_VPU_HDMI_ISO, GEN_PWR_VPU_HDMI_ISO);
+       udelay(20);
+
+       /* Power Down Memories */
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
+                                  0x3 << i, 0x3 << i);
+               udelay(5);
+       }
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
+                                  0x3 << i, 0x3 << i);
+               udelay(5);
+       }
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG2,
+                                  0x3 << i, 0x3 << i);
                udelay(5);
        }
        for (i = 8; i < 16; i++) {
@@ -108,13 +153,67 @@ static int meson_gx_pwrc_vpu_power_on(struct generic_pm_domain *genpd)
        /* Power Up Memories */
        for (i = 0; i < 32; i += 2) {
                regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
-                                  0x2 << i, 0);
+                                  0x3 << i, 0);
+               udelay(5);
+       }
+
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
+                                  0x3 << i, 0);
+               udelay(5);
+       }
+
+       for (i = 8; i < 16; i++) {
+               regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0,
+                                  BIT(i), 0);
+               udelay(5);
+       }
+       udelay(20);
+
+       ret = reset_control_assert(pd->rstc);
+       if (ret)
+               return ret;
+
+       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+                          GEN_PWR_VPU_HDMI_ISO, 0);
+
+       ret = reset_control_deassert(pd->rstc);
+       if (ret)
+               return ret;
+
+       ret = meson_gx_pwrc_vpu_setup_clk(pd);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int meson_g12a_pwrc_vpu_power_on(struct generic_pm_domain *genpd)
+{
+       struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd);
+       int ret;
+       int i;
+
+       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+                          GEN_PWR_VPU_HDMI, 0);
+       udelay(20);
+
+       /* Power Up Memories */
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
+                                  0x3 << i, 0);
                udelay(5);
        }
 
        for (i = 0; i < 32; i += 2) {
                regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
-                                  0x2 << i, 0);
+                                  0x3 << i, 0);
+               udelay(5);
+       }
+
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG2,
+                                  0x3 << i, 0);
                udelay(5);
        }
 
@@ -160,15 +259,37 @@ static struct meson_gx_pwrc_vpu vpu_hdmi_pd = {
        },
 };
 
+static struct meson_gx_pwrc_vpu vpu_hdmi_pd_g12a = {
+       .genpd = {
+               .name = "vpu_hdmi",
+               .power_off = meson_g12a_pwrc_vpu_power_off,
+               .power_on = meson_g12a_pwrc_vpu_power_on,
+       },
+};
+
 static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
 {
+       const struct meson_gx_pwrc_vpu *vpu_pd_match;
        struct regmap *regmap_ao, *regmap_hhi;
+       struct meson_gx_pwrc_vpu *vpu_pd;
        struct reset_control *rstc;
        struct clk *vpu_clk;
        struct clk *vapb_clk;
        bool powered_off;
        int ret;
 
+       vpu_pd_match = of_device_get_match_data(&pdev->dev);
+       if (!vpu_pd_match) {
+               dev_err(&pdev->dev, "failed to get match data\n");
+               return -ENODEV;
+       }
+
+       vpu_pd = devm_kzalloc(&pdev->dev, sizeof(*vpu_pd), GFP_KERNEL);
+       if (!vpu_pd)
+               return -ENOMEM;
+
+       memcpy(vpu_pd, vpu_pd_match, sizeof(*vpu_pd));
+
        regmap_ao = syscon_node_to_regmap(of_get_parent(pdev->dev.of_node));
        if (IS_ERR(regmap_ao)) {
                dev_err(&pdev->dev, "failed to get regmap\n");
@@ -201,39 +322,46 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
                return PTR_ERR(vapb_clk);
        }
 
-       vpu_hdmi_pd.regmap_ao = regmap_ao;
-       vpu_hdmi_pd.regmap_hhi = regmap_hhi;
-       vpu_hdmi_pd.rstc = rstc;
-       vpu_hdmi_pd.vpu_clk = vpu_clk;
-       vpu_hdmi_pd.vapb_clk = vapb_clk;
+       vpu_pd->regmap_ao = regmap_ao;
+       vpu_pd->regmap_hhi = regmap_hhi;
+       vpu_pd->rstc = rstc;
+       vpu_pd->vpu_clk = vpu_clk;
+       vpu_pd->vapb_clk = vapb_clk;
+
+       platform_set_drvdata(pdev, vpu_pd);
 
-       powered_off = meson_gx_pwrc_vpu_get_power(&vpu_hdmi_pd);
+       powered_off = meson_gx_pwrc_vpu_get_power(vpu_pd);
 
        /* If already powered, sync the clock states */
        if (!powered_off) {
-               ret = meson_gx_pwrc_vpu_setup_clk(&vpu_hdmi_pd);
+               ret = meson_gx_pwrc_vpu_setup_clk(vpu_pd);
                if (ret)
                        return ret;
        }
 
-       pm_genpd_init(&vpu_hdmi_pd.genpd, &pm_domain_always_on_gov,
+       pm_genpd_init(&vpu_pd->genpd, &pm_domain_always_on_gov,
                      powered_off);
 
        return of_genpd_add_provider_simple(pdev->dev.of_node,
-                                           &vpu_hdmi_pd.genpd);
+                                           &vpu_pd->genpd);
 }
 
 static void meson_gx_pwrc_vpu_shutdown(struct platform_device *pdev)
 {
+       struct meson_gx_pwrc_vpu *vpu_pd = platform_get_drvdata(pdev);
        bool powered_off;
 
-       powered_off = meson_gx_pwrc_vpu_get_power(&vpu_hdmi_pd);
+       powered_off = meson_gx_pwrc_vpu_get_power(vpu_pd);
        if (!powered_off)
-               meson_gx_pwrc_vpu_power_off(&vpu_hdmi_pd.genpd);
+               vpu_pd->genpd.power_off(&vpu_pd->genpd);
 }
 
 static const struct of_device_id meson_gx_pwrc_vpu_match_table[] = {
-       { .compatible = "amlogic,meson-gx-pwrc-vpu" },
+       { .compatible = "amlogic,meson-gx-pwrc-vpu", .data = &vpu_hdmi_pd },
+       {
+         .compatible = "amlogic,meson-g12a-pwrc-vpu",
+         .data = &vpu_hdmi_pd_g12a
+       },
        { /* sentinel */ }
 };
 
index 37ea0a1..bca3495 100644 (file)
@@ -37,26 +37,34 @@ static const struct meson_gx_soc_id {
        { "AXG", 0x25 },
        { "GXLX", 0x26 },
        { "TXHD", 0x27 },
+       { "G12A", 0x28 },
+       { "G12B", 0x29 },
 };
 
 static const struct meson_gx_package_id {
        const char *name;
        unsigned int major_id;
        unsigned int pack_id;
+       unsigned int pack_mask;
 } soc_packages[] = {
-       { "S905", 0x1f, 0 },
-       { "S905H", 0x1f, 0x13 },
-       { "S905M", 0x1f, 0x20 },
-       { "S905D", 0x21, 0 },
-       { "S905X", 0x21, 0x80 },
-       { "S905W", 0x21, 0xa0 },
-       { "S905L", 0x21, 0xc0 },
-       { "S905M2", 0x21, 0xe0 },
-       { "S912", 0x22, 0 },
-       { "962X", 0x24, 0x10 },
-       { "962E", 0x24, 0x20 },
-       { "A113X", 0x25, 0x37 },
-       { "A113D", 0x25, 0x22 },
+       { "S905", 0x1f, 0, 0x20 }, /* pack_id != 0x20 */
+       { "S905H", 0x1f, 0x3, 0xf }, /* pack_id & 0xf == 0x3 */
+       { "S905M", 0x1f, 0x20, 0xf0 }, /* pack_id == 0x20 */
+       { "S905D", 0x21, 0, 0xf0 },
+       { "S905X", 0x21, 0x80, 0xf0 },
+       { "S905W", 0x21, 0xa0, 0xf0 },
+       { "S905L", 0x21, 0xc0, 0xf0 },
+       { "S905M2", 0x21, 0xe0, 0xf0 },
+       { "S805X", 0x21, 0x30, 0xf0 },
+       { "S805Y", 0x21, 0xb0, 0xf0 },
+       { "S912", 0x22, 0, 0x0 }, /* Only S912 is known for GXM */
+       { "962X", 0x24, 0x10, 0xf0 },
+       { "962E", 0x24, 0x20, 0xf0 },
+       { "A113X", 0x25, 0x37, 0xff },
+       { "A113D", 0x25, 0x22, 0xff },
+       { "S905D2", 0x28, 0x10, 0xf0 },
+       { "S905X2", 0x28, 0x40, 0xf0 },
+       { "S922X", 0x29, 0x40, 0xf0 },
 };
 
 static inline unsigned int socinfo_to_major(u32 socinfo)
@@ -81,13 +89,14 @@ static inline unsigned int socinfo_to_misc(u32 socinfo)
 
 static const char *socinfo_to_package_id(u32 socinfo)
 {
-       unsigned int pack = socinfo_to_pack(socinfo) & 0xf0;
+       unsigned int pack = socinfo_to_pack(socinfo);
        unsigned int major = socinfo_to_major(socinfo);
        int i;
 
        for (i = 0 ; i < ARRAY_SIZE(soc_packages) ; ++i) {
                if (soc_packages[i].major_id == major &&
-                   soc_packages[i].pack_id == pack)
+                   soc_packages[i].pack_id ==
+                               (pack & soc_packages[i].pack_mask))
                        return soc_packages[i].name;
        }
 
@@ -123,8 +132,10 @@ static int __init meson_gx_socinfo_init(void)
                return -ENODEV;
 
        /* check if interface is enabled */
-       if (!of_device_is_available(np))
+       if (!of_device_is_available(np)) {
+               of_node_put(np);
                return -ENODEV;
+       }
 
        /* check if chip-id is available */
        if (!of_property_read_bool(np, "amlogic,has-chip-id"))
diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig
new file mode 100644 (file)
index 0000000..765d101
--- /dev/null
@@ -0,0 +1,31 @@
+menu "Aspeed SoC drivers"
+
+config SOC_ASPEED
+       def_bool y
+       depends on ARCH_ASPEED || COMPILE_TEST
+
+config ASPEED_LPC_CTRL
+       depends on SOC_ASPEED && REGMAP && MFD_SYSCON
+       tristate "Aspeed ast2400/2500 HOST LPC to BMC bridge control"
+       ---help---
+         Control Aspeed ast2400/2500 HOST LPC to BMC mappings through
+         ioctl()s, the driver also provides a read/write interface to a BMC ram
+         region where the host LPC read/write region can be buffered.
+
+config ASPEED_LPC_SNOOP
+       tristate "Aspeed ast2500 HOST LPC snoop support"
+       depends on SOC_ASPEED && REGMAP && MFD_SYSCON
+       help
+         Provides a driver to control the LPC snoop interface which
+         allows the BMC to listen on and save the data written by
+         the host to an arbitrary LPC I/O port.
+
+config ASPEED_P2A_CTRL
+       depends on SOC_ASPEED && REGMAP && MFD_SYSCON
+       tristate "Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC bridge control"
+       help
+         Control Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC mappings through
+         ioctl()s, the driver also provides an interface for userspace mappings to
+         a pre-defined region.
+
+endmenu
diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile
new file mode 100644 (file)
index 0000000..2f7b6da
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_ASPEED_LPC_CTRL)  += aspeed-lpc-ctrl.o
+obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
+obj-$(CONFIG_ASPEED_P2A_CTRL)  += aspeed-p2a-ctrl.o
diff --git a/drivers/soc/aspeed/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c
new file mode 100644 (file)
index 0000000..a024f80
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2017 IBM 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/regmap.h>
+
+#include <linux/aspeed-lpc-ctrl.h>
+
+#define DEVICE_NAME    "aspeed-lpc-ctrl"
+
+#define HICR5 0x0
+#define HICR5_ENL2H    BIT(8)
+#define HICR5_ENFWH    BIT(10)
+
+#define HICR7 0x8
+#define HICR8 0xc
+
+struct aspeed_lpc_ctrl {
+       struct miscdevice       miscdev;
+       struct regmap           *regmap;
+       struct clk              *clk;
+       phys_addr_t             mem_base;
+       resource_size_t         mem_size;
+       u32             pnor_size;
+       u32             pnor_base;
+};
+
+static struct aspeed_lpc_ctrl *file_aspeed_lpc_ctrl(struct file *file)
+{
+       return container_of(file->private_data, struct aspeed_lpc_ctrl,
+                       miscdev);
+}
+
+static int aspeed_lpc_ctrl_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct aspeed_lpc_ctrl *lpc_ctrl = file_aspeed_lpc_ctrl(file);
+       unsigned long vsize = vma->vm_end - vma->vm_start;
+       pgprot_t prot = vma->vm_page_prot;
+
+       if (vma->vm_pgoff + vsize > lpc_ctrl->mem_base + lpc_ctrl->mem_size)
+               return -EINVAL;
+
+       /* ast2400/2500 AHB accesses are not cache coherent */
+       prot = pgprot_noncached(prot);
+
+       if (remap_pfn_range(vma, vma->vm_start,
+               (lpc_ctrl->mem_base >> PAGE_SHIFT) + vma->vm_pgoff,
+               vsize, prot))
+               return -EAGAIN;
+
+       return 0;
+}
+
+static long aspeed_lpc_ctrl_ioctl(struct file *file, unsigned int cmd,
+               unsigned long param)
+{
+       struct aspeed_lpc_ctrl *lpc_ctrl = file_aspeed_lpc_ctrl(file);
+       void __user *p = (void __user *)param;
+       struct aspeed_lpc_ctrl_mapping map;
+       u32 addr;
+       u32 size;
+       long rc;
+
+       if (copy_from_user(&map, p, sizeof(map)))
+               return -EFAULT;
+
+       if (map.flags != 0)
+               return -EINVAL;
+
+       switch (cmd) {
+       case ASPEED_LPC_CTRL_IOCTL_GET_SIZE:
+               /* The flash windows don't report their size */
+               if (map.window_type != ASPEED_LPC_CTRL_WINDOW_MEMORY)
+                       return -EINVAL;
+
+               /* Support more than one window id in the future */
+               if (map.window_id != 0)
+                       return -EINVAL;
+
+               map.size = lpc_ctrl->mem_size;
+
+               return copy_to_user(p, &map, sizeof(map)) ? -EFAULT : 0;
+       case ASPEED_LPC_CTRL_IOCTL_MAP:
+
+               /*
+                * The top half of HICR7 is the MSB of the BMC address of the
+                * mapping.
+                * The bottom half of HICR7 is the MSB of the HOST LPC
+                * firmware space address of the mapping.
+                *
+                * The 1 bits in the top of half of HICR8 represent the bits
+                * (in the requested address) that should be ignored and
+                * replaced with those from the top half of HICR7.
+                * The 1 bits in the bottom half of HICR8 represent the bits
+                * (in the requested address) that should be kept and pass
+                * into the BMC address space.
+                */
+
+               /*
+                * It doesn't make sense to talk about a size or offset with
+                * low 16 bits set. Both HICR7 and HICR8 talk about the top 16
+                * bits of addresses and sizes.
+                */
+
+               if ((map.size & 0x0000ffff) || (map.offset & 0x0000ffff))
+                       return -EINVAL;
+
+               /*
+                * Because of the way the masks work in HICR8 offset has to
+                * be a multiple of size.
+                */
+               if (map.offset & (map.size - 1))
+                       return -EINVAL;
+
+               if (map.window_type == ASPEED_LPC_CTRL_WINDOW_FLASH) {
+                       addr = lpc_ctrl->pnor_base;
+                       size = lpc_ctrl->pnor_size;
+               } else if (map.window_type == ASPEED_LPC_CTRL_WINDOW_MEMORY) {
+                       addr = lpc_ctrl->mem_base;
+                       size = lpc_ctrl->mem_size;
+               } else {
+                       return -EINVAL;
+               }
+
+               /* Check overflow first! */
+               if (map.offset + map.size < map.offset ||
+                       map.offset + map.size > size)
+                       return -EINVAL;
+
+               if (map.size == 0 || map.size > size)
+                       return -EINVAL;
+
+               addr += map.offset;
+
+               /*
+                * addr (host lpc address) is safe regardless of values. This
+                * simply changes the address the host has to request on its
+                * side of the LPC bus. This cannot impact the hosts own
+                * memory space by surprise as LPC specific accessors are
+                * required. The only strange thing that could be done is
+                * setting the lower 16 bits but the shift takes care of that.
+                */
+
+               rc = regmap_write(lpc_ctrl->regmap, HICR7,
+                               (addr | (map.addr >> 16)));
+               if (rc)
+                       return rc;
+
+               rc = regmap_write(lpc_ctrl->regmap, HICR8,
+                               (~(map.size - 1)) | ((map.size >> 16) - 1));
+               if (rc)
+                       return rc;
+
+               /*
+                * Enable LPC FHW cycles. This is required for the host to
+                * access the regions specified.
+                */
+               return regmap_update_bits(lpc_ctrl->regmap, HICR5,
+                               HICR5_ENFWH | HICR5_ENL2H,
+                               HICR5_ENFWH | HICR5_ENL2H);
+       }
+
+       return -EINVAL;
+}
+
+static const struct file_operations aspeed_lpc_ctrl_fops = {
+       .owner          = THIS_MODULE,
+       .mmap           = aspeed_lpc_ctrl_mmap,
+       .unlocked_ioctl = aspeed_lpc_ctrl_ioctl,
+};
+
+static int aspeed_lpc_ctrl_probe(struct platform_device *pdev)
+{
+       struct aspeed_lpc_ctrl *lpc_ctrl;
+       struct device_node *node;
+       struct resource resm;
+       struct device *dev;
+       int rc;
+
+       dev = &pdev->dev;
+
+       lpc_ctrl = devm_kzalloc(dev, sizeof(*lpc_ctrl), GFP_KERNEL);
+       if (!lpc_ctrl)
+               return -ENOMEM;
+
+       node = of_parse_phandle(dev->of_node, "flash", 0);
+       if (!node) {
+               dev_err(dev, "Didn't find host pnor flash node\n");
+               return -ENODEV;
+       }
+
+       rc = of_address_to_resource(node, 1, &resm);
+       of_node_put(node);
+       if (rc) {
+               dev_err(dev, "Couldn't address to resource for flash\n");
+               return rc;
+       }
+
+       lpc_ctrl->pnor_size = resource_size(&resm);
+       lpc_ctrl->pnor_base = resm.start;
+
+       dev_set_drvdata(&pdev->dev, lpc_ctrl);
+
+       node = of_parse_phandle(dev->of_node, "memory-region", 0);
+       if (!node) {
+               dev_err(dev, "Didn't find reserved memory\n");
+               return -EINVAL;
+       }
+
+       rc = of_address_to_resource(node, 0, &resm);
+       of_node_put(node);
+       if (rc) {
+               dev_err(dev, "Couldn't address to resource for reserved memory\n");
+               return -ENOMEM;
+       }
+
+       lpc_ctrl->mem_size = resource_size(&resm);
+       lpc_ctrl->mem_base = resm.start;
+
+       lpc_ctrl->regmap = syscon_node_to_regmap(
+                       pdev->dev.parent->of_node);
+       if (IS_ERR(lpc_ctrl->regmap)) {
+               dev_err(dev, "Couldn't get regmap\n");
+               return -ENODEV;
+       }
+
+       lpc_ctrl->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(lpc_ctrl->clk)) {
+               dev_err(dev, "couldn't get clock\n");
+               return PTR_ERR(lpc_ctrl->clk);
+       }
+       rc = clk_prepare_enable(lpc_ctrl->clk);
+       if (rc) {
+               dev_err(dev, "couldn't enable clock\n");
+               return rc;
+       }
+
+       lpc_ctrl->miscdev.minor = MISC_DYNAMIC_MINOR;
+       lpc_ctrl->miscdev.name = DEVICE_NAME;
+       lpc_ctrl->miscdev.fops = &aspeed_lpc_ctrl_fops;
+       lpc_ctrl->miscdev.parent = dev;
+       rc = misc_register(&lpc_ctrl->miscdev);
+       if (rc) {
+               dev_err(dev, "Unable to register device\n");
+               goto err;
+       }
+
+       dev_info(dev, "Loaded at %pr\n", &resm);
+
+       return 0;
+
+err:
+       clk_disable_unprepare(lpc_ctrl->clk);
+       return rc;
+}
+
+static int aspeed_lpc_ctrl_remove(struct platform_device *pdev)
+{
+       struct aspeed_lpc_ctrl *lpc_ctrl = dev_get_drvdata(&pdev->dev);
+
+       misc_deregister(&lpc_ctrl->miscdev);
+       clk_disable_unprepare(lpc_ctrl->clk);
+
+       return 0;
+}
+
+static const struct of_device_id aspeed_lpc_ctrl_match[] = {
+       { .compatible = "aspeed,ast2400-lpc-ctrl" },
+       { .compatible = "aspeed,ast2500-lpc-ctrl" },
+       { },
+};
+
+static struct platform_driver aspeed_lpc_ctrl_driver = {
+       .driver = {
+               .name           = DEVICE_NAME,
+               .of_match_table = aspeed_lpc_ctrl_match,
+       },
+       .probe = aspeed_lpc_ctrl_probe,
+       .remove = aspeed_lpc_ctrl_remove,
+};
+
+module_platform_driver(aspeed_lpc_ctrl_driver);
+
+MODULE_DEVICE_TABLE(of, aspeed_lpc_ctrl_match);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Cyril Bur <cyrilbur@gmail.com>");
+MODULE_DESCRIPTION("Control for aspeed 2400/2500 LPC HOST to BMC mappings");
diff --git a/drivers/soc/aspeed/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c
new file mode 100644 (file)
index 0000000..2feb434
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * Copyright 2017 Google 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.
+ *
+ * Provides a simple driver to control the ASPEED LPC snoop interface which
+ * allows the BMC to listen on and save the data written by
+ * the host to an arbitrary LPC I/O port.
+ *
+ * Typically used by the BMC to "watch" host boot progress via port
+ * 0x80 writes made by the BIOS during the boot process.
+ */
+
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/kfifo.h>
+#include <linux/mfd/syscon.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/regmap.h>
+
+#define DEVICE_NAME    "aspeed-lpc-snoop"
+
+#define NUM_SNOOP_CHANNELS 2
+#define SNOOP_FIFO_SIZE 2048
+
+#define HICR5  0x0
+#define HICR5_EN_SNP0W         BIT(0)
+#define HICR5_ENINT_SNP0W      BIT(1)
+#define HICR5_EN_SNP1W         BIT(2)
+#define HICR5_ENINT_SNP1W      BIT(3)
+
+#define HICR6  0x4
+#define HICR6_STR_SNP0W                BIT(0)
+#define HICR6_STR_SNP1W                BIT(1)
+#define SNPWADR        0x10
+#define SNPWADR_CH0_MASK       GENMASK(15, 0)
+#define SNPWADR_CH0_SHIFT      0
+#define SNPWADR_CH1_MASK       GENMASK(31, 16)
+#define SNPWADR_CH1_SHIFT      16
+#define SNPWDR 0x14
+#define SNPWDR_CH0_MASK                GENMASK(7, 0)
+#define SNPWDR_CH0_SHIFT       0
+#define SNPWDR_CH1_MASK                GENMASK(15, 8)
+#define SNPWDR_CH1_SHIFT       8
+#define HICRB  0x80
+#define HICRB_ENSNP0D          BIT(14)
+#define HICRB_ENSNP1D          BIT(15)
+
+struct aspeed_lpc_snoop_model_data {
+       /* The ast2400 has bits 14 and 15 as reserved, whereas the ast2500
+        * can use them.
+        */
+       unsigned int has_hicrb_ensnp;
+};
+
+struct aspeed_lpc_snoop_channel {
+       struct kfifo            fifo;
+       wait_queue_head_t       wq;
+       struct miscdevice       miscdev;
+};
+
+struct aspeed_lpc_snoop {
+       struct regmap           *regmap;
+       int                     irq;
+       struct aspeed_lpc_snoop_channel chan[NUM_SNOOP_CHANNELS];
+};
+
+static struct aspeed_lpc_snoop_channel *snoop_file_to_chan(struct file *file)
+{
+       return container_of(file->private_data,
+                           struct aspeed_lpc_snoop_channel,
+                           miscdev);
+}
+
+static ssize_t snoop_file_read(struct file *file, char __user *buffer,
+                               size_t count, loff_t *ppos)
+{
+       struct aspeed_lpc_snoop_channel *chan = snoop_file_to_chan(file);
+       unsigned int copied;
+       int ret = 0;
+
+       if (kfifo_is_empty(&chan->fifo)) {
+               if (file->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+               ret = wait_event_interruptible(chan->wq,
+                               !kfifo_is_empty(&chan->fifo));
+               if (ret == -ERESTARTSYS)
+                       return -EINTR;
+       }
+       ret = kfifo_to_user(&chan->fifo, buffer, count, &copied);
+
+       return ret ? ret : copied;
+}
+
+static unsigned int snoop_file_poll(struct file *file,
+                                   struct poll_table_struct *pt)
+{
+       struct aspeed_lpc_snoop_channel *chan = snoop_file_to_chan(file);
+
+       poll_wait(file, &chan->wq, pt);
+       return !kfifo_is_empty(&chan->fifo) ? POLLIN : 0;
+}
+
+static const struct file_operations snoop_fops = {
+       .owner  = THIS_MODULE,
+       .read   = snoop_file_read,
+       .poll   = snoop_file_poll,
+       .llseek = noop_llseek,
+};
+
+/* Save a byte to a FIFO and discard the oldest byte if FIFO is full */
+static void put_fifo_with_discard(struct aspeed_lpc_snoop_channel *chan, u8 val)
+{
+       if (!kfifo_initialized(&chan->fifo))
+               return;
+       if (kfifo_is_full(&chan->fifo))
+               kfifo_skip(&chan->fifo);
+       kfifo_put(&chan->fifo, val);
+       wake_up_interruptible(&chan->wq);
+}
+
+static irqreturn_t aspeed_lpc_snoop_irq(int irq, void *arg)
+{
+       struct aspeed_lpc_snoop *lpc_snoop = arg;
+       u32 reg, data;
+
+       if (regmap_read(lpc_snoop->regmap, HICR6, &reg))
+               return IRQ_NONE;
+
+       /* Check if one of the snoop channels is interrupting */
+       reg &= (HICR6_STR_SNP0W | HICR6_STR_SNP1W);
+       if (!reg)
+               return IRQ_NONE;
+
+       /* Ack pending IRQs */
+       regmap_write(lpc_snoop->regmap, HICR6, reg);
+
+       /* Read and save most recent snoop'ed data byte to FIFO */
+       regmap_read(lpc_snoop->regmap, SNPWDR, &data);
+
+       if (reg & HICR6_STR_SNP0W) {
+               u8 val = (data & SNPWDR_CH0_MASK) >> SNPWDR_CH0_SHIFT;
+
+               put_fifo_with_discard(&lpc_snoop->chan[0], val);
+       }
+       if (reg & HICR6_STR_SNP1W) {
+               u8 val = (data & SNPWDR_CH1_MASK) >> SNPWDR_CH1_SHIFT;
+
+               put_fifo_with_discard(&lpc_snoop->chan[1], val);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int aspeed_lpc_snoop_config_irq(struct aspeed_lpc_snoop *lpc_snoop,
+                                      struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       int rc;
+
+       lpc_snoop->irq = platform_get_irq(pdev, 0);
+       if (!lpc_snoop->irq)
+               return -ENODEV;
+
+       rc = devm_request_irq(dev, lpc_snoop->irq,
+                             aspeed_lpc_snoop_irq, IRQF_SHARED,
+                             DEVICE_NAME, lpc_snoop);
+       if (rc < 0) {
+               dev_warn(dev, "Unable to request IRQ %d\n", lpc_snoop->irq);
+               lpc_snoop->irq = 0;
+               return rc;
+       }
+
+       return 0;
+}
+
+static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
+                                  struct device *dev,
+                                  int channel, u16 lpc_port)
+{
+       int rc = 0;
+       u32 hicr5_en, snpwadr_mask, snpwadr_shift, hicrb_en;
+       const struct aspeed_lpc_snoop_model_data *model_data =
+               of_device_get_match_data(dev);
+
+       init_waitqueue_head(&lpc_snoop->chan[channel].wq);
+       /* Create FIFO datastructure */
+       rc = kfifo_alloc(&lpc_snoop->chan[channel].fifo,
+                        SNOOP_FIFO_SIZE, GFP_KERNEL);
+       if (rc)
+               return rc;
+
+       lpc_snoop->chan[channel].miscdev.minor = MISC_DYNAMIC_MINOR;
+       lpc_snoop->chan[channel].miscdev.name =
+               devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, channel);
+       lpc_snoop->chan[channel].miscdev.fops = &snoop_fops;
+       lpc_snoop->chan[channel].miscdev.parent = dev;
+       rc = misc_register(&lpc_snoop->chan[channel].miscdev);
+       if (rc)
+               return rc;
+
+       /* Enable LPC snoop channel at requested port */
+       switch (channel) {
+       case 0:
+               hicr5_en = HICR5_EN_SNP0W | HICR5_ENINT_SNP0W;
+               snpwadr_mask = SNPWADR_CH0_MASK;
+               snpwadr_shift = SNPWADR_CH0_SHIFT;
+               hicrb_en = HICRB_ENSNP0D;
+               break;
+       case 1:
+               hicr5_en = HICR5_EN_SNP1W | HICR5_ENINT_SNP1W;
+               snpwadr_mask = SNPWADR_CH1_MASK;
+               snpwadr_shift = SNPWADR_CH1_SHIFT;
+               hicrb_en = HICRB_ENSNP1D;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       regmap_update_bits(lpc_snoop->regmap, HICR5, hicr5_en, hicr5_en);
+       regmap_update_bits(lpc_snoop->regmap, SNPWADR, snpwadr_mask,
+                          lpc_port << snpwadr_shift);
+       if (model_data->has_hicrb_ensnp)
+               regmap_update_bits(lpc_snoop->regmap, HICRB,
+                               hicrb_en, hicrb_en);
+
+       return rc;
+}
+
+static void aspeed_lpc_disable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
+                                    int channel)
+{
+       switch (channel) {
+       case 0:
+               regmap_update_bits(lpc_snoop->regmap, HICR5,
+                                  HICR5_EN_SNP0W | HICR5_ENINT_SNP0W,
+                                  0);
+               break;
+       case 1:
+               regmap_update_bits(lpc_snoop->regmap, HICR5,
+                                  HICR5_EN_SNP1W | HICR5_ENINT_SNP1W,
+                                  0);
+               break;
+       default:
+               return;
+       }
+
+       kfifo_free(&lpc_snoop->chan[channel].fifo);
+       misc_deregister(&lpc_snoop->chan[channel].miscdev);
+}
+
+static int aspeed_lpc_snoop_probe(struct platform_device *pdev)
+{
+       struct aspeed_lpc_snoop *lpc_snoop;
+       struct device *dev;
+       u32 port;
+       int rc;
+
+       dev = &pdev->dev;
+
+       lpc_snoop = devm_kzalloc(dev, sizeof(*lpc_snoop), GFP_KERNEL);
+       if (!lpc_snoop)
+               return -ENOMEM;
+
+       lpc_snoop->regmap = syscon_node_to_regmap(
+                       pdev->dev.parent->of_node);
+       if (IS_ERR(lpc_snoop->regmap)) {
+               dev_err(dev, "Couldn't get regmap\n");
+               return -ENODEV;
+       }
+
+       dev_set_drvdata(&pdev->dev, lpc_snoop);
+
+       rc = of_property_read_u32_index(dev->of_node, "snoop-ports", 0, &port);
+       if (rc) {
+               dev_err(dev, "no snoop ports configured\n");
+               return -ENODEV;
+       }
+
+       rc = aspeed_lpc_snoop_config_irq(lpc_snoop, pdev);
+       if (rc)
+               return rc;
+
+       rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 0, port);
+       if (rc)
+               return rc;
+
+       /* Configuration of 2nd snoop channel port is optional */
+       if (of_property_read_u32_index(dev->of_node, "snoop-ports",
+                                      1, &port) == 0) {
+               rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 1, port);
+               if (rc)
+                       aspeed_lpc_disable_snoop(lpc_snoop, 0);
+       }
+
+       return rc;
+}
+
+static int aspeed_lpc_snoop_remove(struct platform_device *pdev)
+{
+       struct aspeed_lpc_snoop *lpc_snoop = dev_get_drvdata(&pdev->dev);
+
+       /* Disable both snoop channels */
+       aspeed_lpc_disable_snoop(lpc_snoop, 0);
+       aspeed_lpc_disable_snoop(lpc_snoop, 1);
+
+       return 0;
+}
+
+static const struct aspeed_lpc_snoop_model_data ast2400_model_data = {
+       .has_hicrb_ensnp = 0,
+};
+
+static const struct aspeed_lpc_snoop_model_data ast2500_model_data = {
+       .has_hicrb_ensnp = 1,
+};
+
+static const struct of_device_id aspeed_lpc_snoop_match[] = {
+       { .compatible = "aspeed,ast2400-lpc-snoop",
+         .data = &ast2400_model_data },
+       { .compatible = "aspeed,ast2500-lpc-snoop",
+         .data = &ast2500_model_data },
+       { },
+};
+
+static struct platform_driver aspeed_lpc_snoop_driver = {
+       .driver = {
+               .name           = DEVICE_NAME,
+               .of_match_table = aspeed_lpc_snoop_match,
+       },
+       .probe = aspeed_lpc_snoop_probe,
+       .remove = aspeed_lpc_snoop_remove,
+};
+
+module_platform_driver(aspeed_lpc_snoop_driver);
+
+MODULE_DEVICE_TABLE(of, aspeed_lpc_snoop_match);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Robert Lippert <rlippert@google.com>");
+MODULE_DESCRIPTION("Linux driver to control Aspeed LPC snoop functionality");
diff --git a/drivers/soc/aspeed/aspeed-p2a-ctrl.c b/drivers/soc/aspeed/aspeed-p2a-ctrl.c
new file mode 100644 (file)
index 0000000..b60fbea
--- /dev/null
@@ -0,0 +1,444 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Google 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.
+ *
+ * Provides a simple driver to control the ASPEED P2A interface which allows
+ * the host to read and write to various regions of the BMC's memory.
+ */
+
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <linux/aspeed-p2a-ctrl.h>
+
+#define DEVICE_NAME    "aspeed-p2a-ctrl"
+
+/* SCU2C is a Misc. Control Register. */
+#define SCU2C 0x2c
+/* SCU180 is the PCIe Configuration Setting Control Register. */
+#define SCU180 0x180
+/* Bit 1 controls the P2A bridge, while bit 0 controls the entire VGA device
+ * on the PCI bus.
+ */
+#define SCU180_ENP2A BIT(1)
+
+/* The ast2400/2500 both have six ranges. */
+#define P2A_REGION_COUNT 6
+
+struct region {
+       u64 min;
+       u64 max;
+       u32 bit;
+};
+
+struct aspeed_p2a_model_data {
+       /* min, max, bit */
+       struct region regions[P2A_REGION_COUNT];
+};
+
+struct aspeed_p2a_ctrl {
+       struct miscdevice miscdev;
+       struct regmap *regmap;
+
+       const struct aspeed_p2a_model_data *config;
+
+       /* Access to these needs to be locked, held via probe, mapping ioctl,
+        * and release, remove.
+        */
+       struct mutex tracking;
+       u32 readers;
+       u32 readerwriters[P2A_REGION_COUNT];
+
+       phys_addr_t mem_base;
+       resource_size_t mem_size;
+};
+
+struct aspeed_p2a_user {
+       struct file *file;
+       struct aspeed_p2a_ctrl *parent;
+
+       /* The entire memory space is opened for reading once the bridge is
+        * enabled, therefore this needs only to be tracked once per user.
+        * If any user has it open for read, the bridge must stay enabled.
+        */
+       u32 read;
+
+       /* Each entry of the array corresponds to a P2A Region.  If the user
+        * opens for read or readwrite, the reference goes up here.  On
+        * release, this array is walked and references adjusted accordingly.
+        */
+       u32 readwrite[P2A_REGION_COUNT];
+};
+
+static void aspeed_p2a_enable_bridge(struct aspeed_p2a_ctrl *p2a_ctrl)
+{
+       regmap_update_bits(p2a_ctrl->regmap,
+               SCU180, SCU180_ENP2A, SCU180_ENP2A);
+}
+
+static void aspeed_p2a_disable_bridge(struct aspeed_p2a_ctrl *p2a_ctrl)
+{
+       regmap_update_bits(p2a_ctrl->regmap, SCU180, SCU180_ENP2A, 0);
+}
+
+static int aspeed_p2a_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       unsigned long vsize;
+       pgprot_t prot;
+       struct aspeed_p2a_user *priv = file->private_data;
+       struct aspeed_p2a_ctrl *ctrl = priv->parent;
+
+       if (ctrl->mem_base == 0 && ctrl->mem_size == 0)
+               return -EINVAL;
+
+       vsize = vma->vm_end - vma->vm_start;
+       prot = vma->vm_page_prot;
+
+       if (vma->vm_pgoff + vsize > ctrl->mem_base + ctrl->mem_size)
+               return -EINVAL;
+
+       /* ast2400/2500 AHB accesses are not cache coherent */
+       prot = pgprot_noncached(prot);
+
+       if (remap_pfn_range(vma, vma->vm_start,
+               (ctrl->mem_base >> PAGE_SHIFT) + vma->vm_pgoff,
+               vsize, prot))
+               return -EAGAIN;
+
+       return 0;
+}
+
+static bool aspeed_p2a_region_acquire(struct aspeed_p2a_user *priv,
+               struct aspeed_p2a_ctrl *ctrl,
+               struct aspeed_p2a_ctrl_mapping *map)
+{
+       int i;
+       u64 base, end;
+       bool matched = false;
+
+       base = map->addr;
+       end = map->addr + (map->length - 1);
+
+       /* If the value is a legal u32, it will find a match. */
+       for (i = 0; i < P2A_REGION_COUNT; i++) {
+               const struct region *curr = &ctrl->config->regions[i];
+
+               /* If the top of this region is lower than your base, skip it.
+                */
+               if (curr->max < base)
+                       continue;
+
+               /* If the bottom of this region is higher than your end, bail.
+                */
+               if (curr->min > end)
+                       break;
+
+               /* Lock this and update it, therefore it someone else is
+                * closing their file out, this'll preserve the increment.
+                */
+               mutex_lock(&ctrl->tracking);
+               ctrl->readerwriters[i] += 1;
+               mutex_unlock(&ctrl->tracking);
+
+               /* Track with the user, so when they close their file, we can
+                * decrement properly.
+                */
+               priv->readwrite[i] += 1;
+
+               /* Enable the region as read-write. */
+               regmap_update_bits(ctrl->regmap, SCU2C, curr->bit, 0);
+               matched = true;
+       }
+
+       return matched;
+}
+
+static long aspeed_p2a_ioctl(struct file *file, unsigned int cmd,
+               unsigned long data)
+{
+       struct aspeed_p2a_user *priv = file->private_data;
+       struct aspeed_p2a_ctrl *ctrl = priv->parent;
+       void __user *arg = (void __user *)data;
+       struct aspeed_p2a_ctrl_mapping map;
+
+       if (copy_from_user(&map, arg, sizeof(map)))
+               return -EFAULT;
+
+       switch (cmd) {
+       case ASPEED_P2A_CTRL_IOCTL_SET_WINDOW:
+               /* If they want a region to be read-only, since the entire
+                * region is read-only once enabled, we just need to track this
+                * user wants to read from the bridge, and if it's not enabled.
+                * Enable it.
+                */
+               if (map.flags == ASPEED_P2A_CTRL_READ_ONLY) {
+                       mutex_lock(&ctrl->tracking);
+                       ctrl->readers += 1;
+                       mutex_unlock(&ctrl->tracking);
+
+                       /* Track with the user, so when they close their file,
+                        * we can decrement properly.
+                        */
+                       priv->read += 1;
+               } else if (map.flags == ASPEED_P2A_CTRL_READWRITE) {
+                       /* If we don't acquire any region return error. */
+                       if (!aspeed_p2a_region_acquire(priv, ctrl, &map)) {
+                               return -EINVAL;
+                       }
+               } else {
+                       /* Invalid map flags. */
+                       return -EINVAL;
+               }
+
+               aspeed_p2a_enable_bridge(ctrl);
+               return 0;
+       case ASPEED_P2A_CTRL_IOCTL_GET_MEMORY_CONFIG:
+               /* This is a request for the memory-region and corresponding
+                * length that is used by the driver for mmap.
+                */
+
+               map.flags = 0;
+               map.addr = ctrl->mem_base;
+               map.length = ctrl->mem_size;
+
+               return copy_to_user(arg, &map, sizeof(map)) ? -EFAULT : 0;
+       }
+
+       return -EINVAL;
+}
+
+
+/*
+ * When a user opens this file, we create a structure to track their mappings.
+ *
+ * A user can map a region as read-only (bridge enabled), or read-write (bit
+ * flipped, and bridge enabled).  Either way, this tracking is used, s.t. when
+ * they release the device references are handled.
+ *
+ * The bridge is not enabled until a user calls an ioctl to map a region,
+ * simply opening the device does not enable it.
+ */
+static int aspeed_p2a_open(struct inode *inode, struct file *file)
+{
+       struct aspeed_p2a_user *priv;
+
+       priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->file = file;
+       priv->read = 0;
+       memset(priv->readwrite, 0, sizeof(priv->readwrite));
+
+       /* The file's private_data is initialized to the p2a_ctrl. */
+       priv->parent = file->private_data;
+
+       /* Set the file's private_data to the user's data. */
+       file->private_data = priv;
+
+       return 0;
+}
+
+/*
+ * This will close the users mappings.  It will go through what they had opened
+ * for readwrite, and decrement those counts.  If at the end, this is the last
+ * user, it'll close the bridge.
+ */
+static int aspeed_p2a_release(struct inode *inode, struct file *file)
+{
+       int i;
+       u32 bits = 0;
+       bool open_regions = false;
+       struct aspeed_p2a_user *priv = file->private_data;
+
+       /* Lock others from changing these values until everything is updated
+        * in one pass.
+        */
+       mutex_lock(&priv->parent->tracking);
+
+       priv->parent->readers -= priv->read;
+
+       for (i = 0; i < P2A_REGION_COUNT; i++) {
+               priv->parent->readerwriters[i] -= priv->readwrite[i];
+
+               if (priv->parent->readerwriters[i] > 0)
+                       open_regions = true;
+               else
+                       bits |= priv->parent->config->regions[i].bit;
+       }
+
+       /* Setting a bit to 1 disables the region, so let's just OR with the
+        * above to disable any.
+        */
+
+       /* Note, if another user is trying to ioctl, they can't grab tracking,
+        * and therefore can't grab either register mutex.
+        * If another user is trying to close, they can't grab tracking either.
+        */
+       regmap_update_bits(priv->parent->regmap, SCU2C, bits, bits);
+
+       /* If parent->readers is zero and open windows is 0, disable the
+        * bridge.
+        */
+       if (!open_regions && priv->parent->readers == 0)
+               aspeed_p2a_disable_bridge(priv->parent);
+
+       mutex_unlock(&priv->parent->tracking);
+
+       kfree(priv);
+
+       return 0;
+}
+
+static const struct file_operations aspeed_p2a_ctrl_fops = {
+       .owner = THIS_MODULE,
+       .mmap = aspeed_p2a_mmap,
+       .unlocked_ioctl = aspeed_p2a_ioctl,
+       .open = aspeed_p2a_open,
+       .release = aspeed_p2a_release,
+};
+
+/* The regions are controlled by SCU2C */
+static void aspeed_p2a_disable_all(struct aspeed_p2a_ctrl *p2a_ctrl)
+{
+       int i;
+       u32 value = 0;
+
+       for (i = 0; i < P2A_REGION_COUNT; i++)
+               value |= p2a_ctrl->config->regions[i].bit;
+
+       regmap_update_bits(p2a_ctrl->regmap, SCU2C, value, value);
+
+       /* Disable the bridge. */
+       aspeed_p2a_disable_bridge(p2a_ctrl);
+}
+
+static int aspeed_p2a_ctrl_probe(struct platform_device *pdev)
+{
+       struct aspeed_p2a_ctrl *misc_ctrl;
+       struct device *dev;
+       struct resource resm;
+       struct device_node *node;
+       int rc = 0;
+
+       dev = &pdev->dev;
+
+       misc_ctrl = devm_kzalloc(dev, sizeof(*misc_ctrl), GFP_KERNEL);
+       if (!misc_ctrl)
+               return -ENOMEM;
+
+       mutex_init(&misc_ctrl->tracking);
+
+       /* optional. */
+       node = of_parse_phandle(dev->of_node, "memory-region", 0);
+       if (node) {
+               rc = of_address_to_resource(node, 0, &resm);
+               of_node_put(node);
+               if (rc) {
+                       dev_err(dev, "Couldn't address to resource for reserved memory\n");
+                       return -ENODEV;
+               }
+
+               misc_ctrl->mem_size = resource_size(&resm);
+               misc_ctrl->mem_base = resm.start;
+       }
+
+       misc_ctrl->regmap = syscon_node_to_regmap(pdev->dev.parent->of_node);
+       if (IS_ERR(misc_ctrl->regmap)) {
+               dev_err(dev, "Couldn't get regmap\n");
+               return -ENODEV;
+       }
+
+       misc_ctrl->config = of_device_get_match_data(dev);
+
+       dev_set_drvdata(&pdev->dev, misc_ctrl);
+
+       aspeed_p2a_disable_all(misc_ctrl);
+
+       misc_ctrl->miscdev.minor = MISC_DYNAMIC_MINOR;
+       misc_ctrl->miscdev.name = DEVICE_NAME;
+       misc_ctrl->miscdev.fops = &aspeed_p2a_ctrl_fops;
+       misc_ctrl->miscdev.parent = dev;
+
+       rc = misc_register(&misc_ctrl->miscdev);
+       if (rc)
+               dev_err(dev, "Unable to register device\n");
+
+       return rc;
+}
+
+static int aspeed_p2a_ctrl_remove(struct platform_device *pdev)
+{
+       struct aspeed_p2a_ctrl *p2a_ctrl = dev_get_drvdata(&pdev->dev);
+
+       misc_deregister(&p2a_ctrl->miscdev);
+
+       return 0;
+}
+
+#define SCU2C_DRAM     BIT(25)
+#define SCU2C_SPI      BIT(24)
+#define SCU2C_SOC      BIT(23)
+#define SCU2C_FLASH    BIT(22)
+
+static const struct aspeed_p2a_model_data ast2400_model_data = {
+       .regions = {
+               {0x00000000, 0x17FFFFFF, SCU2C_FLASH},
+               {0x18000000, 0x1FFFFFFF, SCU2C_SOC},
+               {0x20000000, 0x2FFFFFFF, SCU2C_FLASH},
+               {0x30000000, 0x3FFFFFFF, SCU2C_SPI},
+               {0x40000000, 0x5FFFFFFF, SCU2C_DRAM},
+               {0x60000000, 0xFFFFFFFF, SCU2C_SOC},
+       }
+};
+
+static const struct aspeed_p2a_model_data ast2500_model_data = {
+       .regions = {
+               {0x00000000, 0x0FFFFFFF, SCU2C_FLASH},
+               {0x10000000, 0x1FFFFFFF, SCU2C_SOC},
+               {0x20000000, 0x3FFFFFFF, SCU2C_FLASH},
+               {0x40000000, 0x5FFFFFFF, SCU2C_SOC},
+               {0x60000000, 0x7FFFFFFF, SCU2C_SPI},
+               {0x80000000, 0xFFFFFFFF, SCU2C_DRAM},
+       }
+};
+
+static const struct of_device_id aspeed_p2a_ctrl_match[] = {
+       { .compatible = "aspeed,ast2400-p2a-ctrl",
+         .data = &ast2400_model_data },
+       { .compatible = "aspeed,ast2500-p2a-ctrl",
+         .data = &ast2500_model_data },
+       { },
+};
+
+static struct platform_driver aspeed_p2a_ctrl_driver = {
+       .driver = {
+               .name           = DEVICE_NAME,
+               .of_match_table = aspeed_p2a_ctrl_match,
+       },
+       .probe = aspeed_p2a_ctrl_probe,
+       .remove = aspeed_p2a_ctrl_remove,
+};
+
+module_platform_driver(aspeed_p2a_ctrl_driver);
+
+MODULE_DEVICE_TABLE(of, aspeed_p2a_ctrl_match);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick Venture <venture@google.com>");
+MODULE_DESCRIPTION("Control for aspeed 2400/2500 P2A VGA HOST to BMC mappings");
index 506a6f3..d6b529e 100644 (file)
@@ -1,2 +1,3 @@
 obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
 obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
+obj-$(CONFIG_ARCH_MXC) += soc-imx8.o
index 7d14a4b..d9231bd 100644 (file)
@@ -406,7 +406,6 @@ static int imx_gpc_probe(struct platform_device *pdev)
        const struct imx_gpc_dt_data *of_id_data = of_id->data;
        struct device_node *pgc_node;
        struct regmap *regmap;
-       struct resource *res;
        void __iomem *base;
        int ret;
 
@@ -417,8 +416,7 @@ static int imx_gpc_probe(struct platform_device *pdev)
            !pgc_node)
                return 0;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       base = devm_ioremap_resource(&pdev->dev, res);
+       base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(base))
                return PTR_ERR(base);
 
@@ -431,10 +429,19 @@ static int imx_gpc_probe(struct platform_device *pdev)
                return ret;
        }
 
-       /* Disable PU power down in normal operation if ERR009619 is present */
+       /*
+        * Disable PU power down by runtime PM if ERR009619 is present.
+        *
+        * The PRE clock will be paused for several cycles when turning on the
+        * PU domain LDO from power down state. If PRE is in use at that time,
+        * the IPU/PRG cannot get the correct display data from the PRE.
+        *
+        * This is not a concern when the whole system enters suspend state, so
+        * it's safe to power down PU in this case.
+        */
        if (of_id_data->err009619_present)
                imx_gpc_domains[GPC_PGC_DOMAIN_PU].base.flags |=
-                               GENPD_FLAG_ALWAYS_ON;
+                               GENPD_FLAG_RPM_ALWAYS_ON;
 
        /* Keep DISP always on if ERR006287 is present */
        if (of_id_data->err006287_present)
index 176f473..31b8d00 100644 (file)
@@ -136,8 +136,8 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
                GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ;
        const bool enable_power_control = !on;
        const bool has_regulator = !IS_ERR(domain->regulator);
-       unsigned long deadline;
        int i, ret = 0;
+       u32 pxx_req;
 
        regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
                           domain->bits.map, domain->bits.map);
@@ -169,30 +169,19 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
         * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
         * for PUP_REQ/PDN_REQ bit to be cleared
         */
-       deadline = jiffies + msecs_to_jiffies(1);
-       while (true) {
-               u32 pxx_req;
-
-               regmap_read(domain->regmap, offset, &pxx_req);
-
-               if (!(pxx_req & domain->bits.pxx))
-                       break;
-
-               if (time_after(jiffies, deadline)) {
-                       dev_err(domain->dev, "falied to command PGC\n");
-                       ret = -ETIMEDOUT;
-                       /*
-                        * If we were in a process of enabling a
-                        * domain and failed we might as well disable
-                        * the regulator we just enabled. And if it
-                        * was the opposite situation and we failed to
-                        * power down -- keep the regulator on
-                        */
-                       on = !on;
-                       break;
-               }
-
-               cpu_relax();
+       ret = regmap_read_poll_timeout(domain->regmap, offset, pxx_req,
+                                      !(pxx_req & domain->bits.pxx),
+                                      0, USEC_PER_MSEC);
+       if (ret) {
+               dev_err(domain->dev, "failed to command PGC\n");
+               /*
+                * If we were in a process of enabling a
+                * domain and failed we might as well disable
+                * the regulator we just enabled. And if it
+                * was the opposite situation and we failed to
+                * power down -- keep the regulator on
+                */
+               on = !on;
        }
 
        if (enable_power_control)
@@ -574,7 +563,6 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct device_node *pgc_np, *np;
        struct regmap *regmap;
-       struct resource *res;
        void __iomem *base;
        int ret;
 
@@ -584,8 +572,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       res  = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       base = devm_ioremap_resource(dev, res);
+       base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(base))
                return PTR_ERR(base);
 
diff --git a/drivers/soc/imx/soc-imx8.c b/drivers/soc/imx/soc-imx8.c
new file mode 100644 (file)
index 0000000..fc6429f
--- /dev/null
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 NXP.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+
+#define REV_B1                         0x21
+
+#define IMX8MQ_SW_INFO_B1              0x40
+#define IMX8MQ_SW_MAGIC_B1             0xff0055aa
+
+struct imx8_soc_data {
+       char *name;
+       u32 (*soc_revision)(void);
+};
+
+static u32 __init imx8mq_soc_revision(void)
+{
+       struct device_node *np;
+       void __iomem *ocotp_base;
+       u32 magic;
+       u32 rev = 0;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
+       if (!np)
+               goto out;
+
+       ocotp_base = of_iomap(np, 0);
+       WARN_ON(!ocotp_base);
+
+       magic = readl_relaxed(ocotp_base + IMX8MQ_SW_INFO_B1);
+       if (magic == IMX8MQ_SW_MAGIC_B1)
+               rev = REV_B1;
+
+       iounmap(ocotp_base);
+
+out:
+       of_node_put(np);
+       return rev;
+}
+
+static const struct imx8_soc_data imx8mq_soc_data = {
+       .name = "i.MX8MQ",
+       .soc_revision = imx8mq_soc_revision,
+};
+
+static const struct of_device_id imx8_soc_match[] = {
+       { .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, },
+       { }
+};
+
+#define imx8_revision(soc_rev) \
+       soc_rev ? \
+       kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf,  soc_rev & 0xf) : \
+       "unknown"
+
+static int __init imx8_soc_init(void)
+{
+       struct soc_device_attribute *soc_dev_attr;
+       struct soc_device *soc_dev;
+       struct device_node *root;
+       const struct of_device_id *id;
+       u32 soc_rev = 0;
+       const struct imx8_soc_data *data;
+       int ret;
+
+       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+       if (!soc_dev_attr)
+               return -ENODEV;
+
+       soc_dev_attr->family = "Freescale i.MX";
+
+       root = of_find_node_by_path("/");
+       ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
+       if (ret)
+               goto free_soc;
+
+       id = of_match_node(imx8_soc_match, root);
+       if (!id)
+               goto free_soc;
+
+       of_node_put(root);
+
+       data = id->data;
+       if (data) {
+               soc_dev_attr->soc_id = data->name;
+               if (data->soc_revision)
+                       soc_rev = data->soc_revision();
+       }
+
+       soc_dev_attr->revision = imx8_revision(soc_rev);
+       if (!soc_dev_attr->revision)
+               goto free_soc;
+
+       soc_dev = soc_device_register(soc_dev_attr);
+       if (IS_ERR(soc_dev))
+               goto free_rev;
+
+       return 0;
+
+free_rev:
+       kfree(soc_dev_attr->revision);
+free_soc:
+       kfree(soc_dev_attr);
+       of_node_put(root);
+       return -ENODEV;
+}
+device_initcall(imx8_soc_init);
diff --git a/drivers/soc/ixp4xx/Kconfig b/drivers/soc/ixp4xx/Kconfig
new file mode 100644 (file)
index 0000000..de6becd
--- /dev/null
@@ -0,0 +1,16 @@
+menu "IXP4xx SoC drivers"
+
+config IXP4XX_QMGR
+       tristate "IXP4xx Queue Manager support"
+       help
+         This driver supports IXP4xx built-in hardware queue manager
+         and is automatically selected by Ethernet and HSS drivers.
+
+config IXP4XX_NPE
+       tristate "IXP4xx Network Processor Engine support"
+       select FW_LOADER
+       help
+         This driver supports IXP4xx built-in network coprocessors
+         and is automatically selected by Ethernet and HSS drivers.
+
+endmenu
diff --git a/drivers/soc/ixp4xx/Makefile b/drivers/soc/ixp4xx/Makefile
new file mode 100644 (file)
index 0000000..d20d99e
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IXP4XX_QMGR)      += ixp4xx-qmgr.o
+obj-$(CONFIG_IXP4XX_NPE)       += ixp4xx-npe.o
diff --git a/drivers/soc/ixp4xx/ixp4xx-npe.c b/drivers/soc/ixp4xx/ixp4xx-npe.c
new file mode 100644 (file)
index 0000000..15979d4
--- /dev/null
@@ -0,0 +1,762 @@
+/*
+ * Intel IXP4xx Network Processor Engine driver for Linux
+ *
+ * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * The code is based on publicly available information:
+ * - Intel IXP4xx Developer's Manual and other e-papers
+ * - Intel IXP400 Access Library Software (BSD license)
+ * - previous works by Christian Hohnstaedt <chohnstaedt@innominate.com>
+ *   Thanks, Christian.
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/soc/ixp4xx/npe.h>
+
+#define DEBUG_MSG                      0
+#define DEBUG_FW                       0
+
+#define NPE_COUNT                      3
+#define MAX_RETRIES                    1000    /* microseconds */
+#define NPE_42X_DATA_SIZE              0x800   /* in dwords */
+#define NPE_46X_DATA_SIZE              0x1000
+#define NPE_A_42X_INSTR_SIZE           0x1000
+#define NPE_B_AND_C_42X_INSTR_SIZE     0x800
+#define NPE_46X_INSTR_SIZE             0x1000
+#define REGS_SIZE                      0x1000
+
+#define NPE_PHYS_REG                   32
+
+#define FW_MAGIC                       0xFEEDF00D
+#define FW_BLOCK_TYPE_INSTR            0x0
+#define FW_BLOCK_TYPE_DATA             0x1
+#define FW_BLOCK_TYPE_EOF              0xF
+
+/* NPE exec status (read) and command (write) */
+#define CMD_NPE_STEP                   0x01
+#define CMD_NPE_START                  0x02
+#define CMD_NPE_STOP                   0x03
+#define CMD_NPE_CLR_PIPE               0x04
+#define CMD_CLR_PROFILE_CNT            0x0C
+#define CMD_RD_INS_MEM                 0x10 /* instruction memory */
+#define CMD_WR_INS_MEM                 0x11
+#define CMD_RD_DATA_MEM                        0x12 /* data memory */
+#define CMD_WR_DATA_MEM                        0x13
+#define CMD_RD_ECS_REG                 0x14 /* exec access register */
+#define CMD_WR_ECS_REG                 0x15
+
+#define STAT_RUN                       0x80000000
+#define STAT_STOP                      0x40000000
+#define STAT_CLEAR                     0x20000000
+#define STAT_ECS_K                     0x00800000 /* pipeline clean */
+
+#define NPE_STEVT                      0x1B
+#define NPE_STARTPC                    0x1C
+#define NPE_REGMAP                     0x1E
+#define NPE_CINDEX                     0x1F
+
+#define INSTR_WR_REG_SHORT             0x0000C000
+#define INSTR_WR_REG_BYTE              0x00004000
+#define INSTR_RD_FIFO                  0x0F888220
+#define INSTR_RESET_MBOX               0x0FAC8210
+
+#define ECS_BG_CTXT_REG_0              0x00 /* Background Executing Context */
+#define ECS_BG_CTXT_REG_1              0x01 /*         Stack level */
+#define ECS_BG_CTXT_REG_2              0x02
+#define ECS_PRI_1_CTXT_REG_0           0x04 /* Priority 1 Executing Context */
+#define ECS_PRI_1_CTXT_REG_1           0x05 /*         Stack level */
+#define ECS_PRI_1_CTXT_REG_2           0x06
+#define ECS_PRI_2_CTXT_REG_0           0x08 /* Priority 2 Executing Context */
+#define ECS_PRI_2_CTXT_REG_1           0x09 /*         Stack level */
+#define ECS_PRI_2_CTXT_REG_2           0x0A
+#define ECS_DBG_CTXT_REG_0             0x0C /* Debug Executing Context */
+#define ECS_DBG_CTXT_REG_1             0x0D /*         Stack level */
+#define ECS_DBG_CTXT_REG_2             0x0E
+#define ECS_INSTRUCT_REG               0x11 /* NPE Instruction Register */
+
+#define ECS_REG_0_ACTIVE               0x80000000 /* all levels */
+#define ECS_REG_0_NEXTPC_MASK          0x1FFF0000 /* BG/PRI1/PRI2 levels */
+#define ECS_REG_0_LDUR_BITS            8
+#define ECS_REG_0_LDUR_MASK            0x00000700 /* all levels */
+#define ECS_REG_1_CCTXT_BITS           16
+#define ECS_REG_1_CCTXT_MASK           0x000F0000 /* all levels */
+#define ECS_REG_1_SELCTXT_BITS         0
+#define ECS_REG_1_SELCTXT_MASK         0x0000000F /* all levels */
+#define ECS_DBG_REG_2_IF               0x00100000 /* debug level */
+#define ECS_DBG_REG_2_IE               0x00080000 /* debug level */
+
+/* NPE watchpoint_fifo register bit */
+#define WFIFO_VALID                    0x80000000
+
+/* NPE messaging_status register bit definitions */
+#define MSGSTAT_OFNE   0x00010000 /* OutFifoNotEmpty */
+#define MSGSTAT_IFNF   0x00020000 /* InFifoNotFull */
+#define MSGSTAT_OFNF   0x00040000 /* OutFifoNotFull */
+#define MSGSTAT_IFNE   0x00080000 /* InFifoNotEmpty */
+#define MSGSTAT_MBINT  0x00100000 /* Mailbox interrupt */
+#define MSGSTAT_IFINT  0x00200000 /* InFifo interrupt */
+#define MSGSTAT_OFINT  0x00400000 /* OutFifo interrupt */
+#define MSGSTAT_WFINT  0x00800000 /* WatchFifo interrupt */
+
+/* NPE messaging_control register bit definitions */
+#define MSGCTL_OUT_FIFO                        0x00010000 /* enable output FIFO */
+#define MSGCTL_IN_FIFO                 0x00020000 /* enable input FIFO */
+#define MSGCTL_OUT_FIFO_WRITE          0x01000000 /* enable FIFO + WRITE */
+#define MSGCTL_IN_FIFO_WRITE           0x02000000
+
+/* NPE mailbox_status value for reset */
+#define RESET_MBOX_STAT                        0x0000F0F0
+
+#define NPE_A_FIRMWARE "NPE-A"
+#define NPE_B_FIRMWARE "NPE-B"
+#define NPE_C_FIRMWARE "NPE-C"
+
+const char *npe_names[] = { NPE_A_FIRMWARE, NPE_B_FIRMWARE, NPE_C_FIRMWARE };
+
+#define print_npe(pri, npe, fmt, ...)                                  \
+       printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__)
+
+#if DEBUG_MSG
+#define debug_msg(npe, fmt, ...)                                       \
+       print_npe(KERN_DEBUG, npe, fmt, ## __VA_ARGS__)
+#else
+#define debug_msg(npe, fmt, ...)
+#endif
+
+static struct {
+       u32 reg, val;
+} ecs_reset[] = {
+       { ECS_BG_CTXT_REG_0,    0xA0000000 },
+       { ECS_BG_CTXT_REG_1,    0x01000000 },
+       { ECS_BG_CTXT_REG_2,    0x00008000 },
+       { ECS_PRI_1_CTXT_REG_0, 0x20000080 },
+       { ECS_PRI_1_CTXT_REG_1, 0x01000000 },
+       { ECS_PRI_1_CTXT_REG_2, 0x00008000 },
+       { ECS_PRI_2_CTXT_REG_0, 0x20000080 },
+       { ECS_PRI_2_CTXT_REG_1, 0x01000000 },
+       { ECS_PRI_2_CTXT_REG_2, 0x00008000 },
+       { ECS_DBG_CTXT_REG_0,   0x20000000 },
+       { ECS_DBG_CTXT_REG_1,   0x00000000 },
+       { ECS_DBG_CTXT_REG_2,   0x001E0000 },
+       { ECS_INSTRUCT_REG,     0x1003C00F },
+};
+
+static struct npe npe_tab[NPE_COUNT] = {
+       {
+               .id     = 0,
+       }, {
+               .id     = 1,
+       }, {
+               .id     = 2,
+       }
+};
+
+int npe_running(struct npe *npe)
+{
+       return (__raw_readl(&npe->regs->exec_status_cmd) & STAT_RUN) != 0;
+}
+
+static void npe_cmd_write(struct npe *npe, u32 addr, int cmd, u32 data)
+{
+       __raw_writel(data, &npe->regs->exec_data);
+       __raw_writel(addr, &npe->regs->exec_addr);
+       __raw_writel(cmd, &npe->regs->exec_status_cmd);
+}
+
+static u32 npe_cmd_read(struct npe *npe, u32 addr, int cmd)
+{
+       __raw_writel(addr, &npe->regs->exec_addr);
+       __raw_writel(cmd, &npe->regs->exec_status_cmd);
+       /* Iintroduce extra read cycles after issuing read command to NPE
+          so that we read the register after the NPE has updated it.
+          This is to overcome race condition between XScale and NPE */
+       __raw_readl(&npe->regs->exec_data);
+       __raw_readl(&npe->regs->exec_data);
+       return __raw_readl(&npe->regs->exec_data);
+}
+
+static void npe_clear_active(struct npe *npe, u32 reg)
+{
+       u32 val = npe_cmd_read(npe, reg, CMD_RD_ECS_REG);
+       npe_cmd_write(npe, reg, CMD_WR_ECS_REG, val & ~ECS_REG_0_ACTIVE);
+}
+
+static void npe_start(struct npe *npe)
+{
+       /* ensure only Background Context Stack Level is active */
+       npe_clear_active(npe, ECS_PRI_1_CTXT_REG_0);
+       npe_clear_active(npe, ECS_PRI_2_CTXT_REG_0);
+       npe_clear_active(npe, ECS_DBG_CTXT_REG_0);
+
+       __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
+       __raw_writel(CMD_NPE_START, &npe->regs->exec_status_cmd);
+}
+
+static void npe_stop(struct npe *npe)
+{
+       __raw_writel(CMD_NPE_STOP, &npe->regs->exec_status_cmd);
+       __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd); /*FIXME?*/
+}
+
+static int __must_check npe_debug_instr(struct npe *npe, u32 instr, u32 ctx,
+                                       u32 ldur)
+{
+       u32 wc;
+       int i;
+
+       /* set the Active bit, and the LDUR, in the debug level */
+       npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG,
+                     ECS_REG_0_ACTIVE | (ldur << ECS_REG_0_LDUR_BITS));
+
+       /* set CCTXT at ECS DEBUG L3 to specify in which context to execute
+          the instruction, and set SELCTXT at ECS DEBUG Level to specify
+          which context store to access.
+          Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
+       */
+       npe_cmd_write(npe, ECS_DBG_CTXT_REG_1, CMD_WR_ECS_REG,
+                     (ctx << ECS_REG_1_CCTXT_BITS) |
+                     (ctx << ECS_REG_1_SELCTXT_BITS));
+
+       /* clear the pipeline */
+       __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
+
+       /* load NPE instruction into the instruction register */
+       npe_cmd_write(npe, ECS_INSTRUCT_REG, CMD_WR_ECS_REG, instr);
+
+       /* we need this value later to wait for completion of NPE execution
+          step */
+       wc = __raw_readl(&npe->regs->watch_count);
+
+       /* issue a Step One command via the Execution Control register */
+       __raw_writel(CMD_NPE_STEP, &npe->regs->exec_status_cmd);
+
+       /* Watch Count register increments when NPE completes an instruction */
+       for (i = 0; i < MAX_RETRIES; i++) {
+               if (wc != __raw_readl(&npe->regs->watch_count))
+                       return 0;
+               udelay(1);
+       }
+
+       print_npe(KERN_ERR, npe, "reset: npe_debug_instr(): timeout\n");
+       return -ETIMEDOUT;
+}
+
+static int __must_check npe_logical_reg_write8(struct npe *npe, u32 addr,
+                                              u8 val, u32 ctx)
+{
+       /* here we build the NPE assembler instruction: mov8 d0, #0 */
+       u32 instr = INSTR_WR_REG_BYTE | /* OpCode */
+               addr << 9 |             /* base Operand */
+               (val & 0x1F) << 4 |     /* lower 5 bits to immediate data */
+               (val & ~0x1F) << (18 - 5);/* higher 3 bits to CoProc instr. */
+       return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
+}
+
+static int __must_check npe_logical_reg_write16(struct npe *npe, u32 addr,
+                                               u16 val, u32 ctx)
+{
+       /* here we build the NPE assembler instruction: mov16 d0, #0 */
+       u32 instr = INSTR_WR_REG_SHORT | /* OpCode */
+               addr << 9 |             /* base Operand */
+               (val & 0x1F) << 4 |     /* lower 5 bits to immediate data */
+               (val & ~0x1F) << (18 - 5);/* higher 11 bits to CoProc instr. */
+       return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
+}
+
+static int __must_check npe_logical_reg_write32(struct npe *npe, u32 addr,
+                                               u32 val, u32 ctx)
+{
+       /* write in 16 bit steps first the high and then the low value */
+       if (npe_logical_reg_write16(npe, addr, val >> 16, ctx))
+               return -ETIMEDOUT;
+       return npe_logical_reg_write16(npe, addr + 2, val & 0xFFFF, ctx);
+}
+
+static int npe_reset(struct npe *npe)
+{
+       u32 val, ctl, exec_count, ctx_reg2;
+       int i;
+
+       ctl = (__raw_readl(&npe->regs->messaging_control) | 0x3F000000) &
+               0x3F3FFFFF;
+
+       /* disable parity interrupt */
+       __raw_writel(ctl & 0x3F00FFFF, &npe->regs->messaging_control);
+
+       /* pre exec - debug instruction */
+       /* turn off the halt bit by clearing Execution Count register. */
+       exec_count = __raw_readl(&npe->regs->exec_count);
+       __raw_writel(0, &npe->regs->exec_count);
+       /* ensure that IF and IE are on (temporarily), so that we don't end up
+          stepping forever */
+       ctx_reg2 = npe_cmd_read(npe, ECS_DBG_CTXT_REG_2, CMD_RD_ECS_REG);
+       npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2 |
+                     ECS_DBG_REG_2_IF | ECS_DBG_REG_2_IE);
+
+       /* clear the FIFOs */
+       while (__raw_readl(&npe->regs->watchpoint_fifo) & WFIFO_VALID)
+               ;
+       while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE)
+               /* read from the outFIFO until empty */
+               print_npe(KERN_DEBUG, npe, "npe_reset: read FIFO = 0x%X\n",
+                         __raw_readl(&npe->regs->in_out_fifo));
+
+       while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)
+               /* step execution of the NPE intruction to read inFIFO using
+                  the Debug Executing Context stack */
+               if (npe_debug_instr(npe, INSTR_RD_FIFO, 0, 0))
+                       return -ETIMEDOUT;
+
+       /* reset the mailbox reg from the XScale side */
+       __raw_writel(RESET_MBOX_STAT, &npe->regs->mailbox_status);
+       /* from NPE side */
+       if (npe_debug_instr(npe, INSTR_RESET_MBOX, 0, 0))
+               return -ETIMEDOUT;
+
+       /* Reset the physical registers in the NPE register file */
+       for (val = 0; val < NPE_PHYS_REG; val++) {
+               if (npe_logical_reg_write16(npe, NPE_REGMAP, val >> 1, 0))
+                       return -ETIMEDOUT;
+               /* address is either 0 or 4 */
+               if (npe_logical_reg_write32(npe, (val & 1) * 4, 0, 0))
+                       return -ETIMEDOUT;
+       }
+
+       /* Reset the context store = each context's Context Store registers */
+
+       /* Context 0 has no STARTPC. Instead, this value is used to set NextPC
+          for Background ECS, to set where NPE starts executing code */
+       val = npe_cmd_read(npe, ECS_BG_CTXT_REG_0, CMD_RD_ECS_REG);
+       val &= ~ECS_REG_0_NEXTPC_MASK;
+       val |= (0 /* NextPC */ << 16) & ECS_REG_0_NEXTPC_MASK;
+       npe_cmd_write(npe, ECS_BG_CTXT_REG_0, CMD_WR_ECS_REG, val);
+
+       for (i = 0; i < 16; i++) {
+               if (i) {        /* Context 0 has no STEVT nor STARTPC */
+                       /* STEVT = off, 0x80 */
+                       if (npe_logical_reg_write8(npe, NPE_STEVT, 0x80, i))
+                               return -ETIMEDOUT;
+                       if (npe_logical_reg_write16(npe, NPE_STARTPC, 0, i))
+                               return -ETIMEDOUT;
+               }
+               /* REGMAP = d0->p0, d8->p2, d16->p4 */
+               if (npe_logical_reg_write16(npe, NPE_REGMAP, 0x820, i))
+                       return -ETIMEDOUT;
+               if (npe_logical_reg_write8(npe, NPE_CINDEX, 0, i))
+                       return -ETIMEDOUT;
+       }
+
+       /* post exec */
+       /* clear active bit in debug level */
+       npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG, 0);
+       /* clear the pipeline */
+       __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
+       /* restore previous values */
+       __raw_writel(exec_count, &npe->regs->exec_count);
+       npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2);
+
+       /* write reset values to Execution Context Stack registers */
+       for (val = 0; val < ARRAY_SIZE(ecs_reset); val++)
+               npe_cmd_write(npe, ecs_reset[val].reg, CMD_WR_ECS_REG,
+                             ecs_reset[val].val);
+
+       /* clear the profile counter */
+       __raw_writel(CMD_CLR_PROFILE_CNT, &npe->regs->exec_status_cmd);
+
+       __raw_writel(0, &npe->regs->exec_count);
+       __raw_writel(0, &npe->regs->action_points[0]);
+       __raw_writel(0, &npe->regs->action_points[1]);
+       __raw_writel(0, &npe->regs->action_points[2]);
+       __raw_writel(0, &npe->regs->action_points[3]);
+       __raw_writel(0, &npe->regs->watch_count);
+
+       val = ixp4xx_read_feature_bits();
+       /* reset the NPE */
+       ixp4xx_write_feature_bits(val &
+                                 ~(IXP4XX_FEATURE_RESET_NPEA << npe->id));
+       /* deassert reset */
+       ixp4xx_write_feature_bits(val |
+                                 (IXP4XX_FEATURE_RESET_NPEA << npe->id));
+       for (i = 0; i < MAX_RETRIES; i++) {
+               if (ixp4xx_read_feature_bits() &
+                   (IXP4XX_FEATURE_RESET_NPEA << npe->id))
+                       break;  /* NPE is back alive */
+               udelay(1);
+       }
+       if (i == MAX_RETRIES)
+               return -ETIMEDOUT;
+
+       npe_stop(npe);
+
+       /* restore NPE configuration bus Control Register - parity settings */
+       __raw_writel(ctl, &npe->regs->messaging_control);
+       return 0;
+}
+
+
+int npe_send_message(struct npe *npe, const void *msg, const char *what)
+{
+       const u32 *send = msg;
+       int cycles = 0;
+
+       debug_msg(npe, "Trying to send message %s [%08X:%08X]\n",
+                 what, send[0], send[1]);
+
+       if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE) {
+               debug_msg(npe, "NPE input FIFO not empty\n");
+               return -EIO;
+       }
+
+       __raw_writel(send[0], &npe->regs->in_out_fifo);
+
+       if (!(__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNF)) {
+               debug_msg(npe, "NPE input FIFO full\n");
+               return -EIO;
+       }
+
+       __raw_writel(send[1], &npe->regs->in_out_fifo);
+
+       while ((cycles < MAX_RETRIES) &&
+              (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)) {
+               udelay(1);
+               cycles++;
+       }
+
+       if (cycles == MAX_RETRIES) {
+               debug_msg(npe, "Timeout sending message\n");
+               return -ETIMEDOUT;
+       }
+
+#if DEBUG_MSG > 1
+       debug_msg(npe, "Sending a message took %i cycles\n", cycles);
+#endif
+       return 0;
+}
+
+int npe_recv_message(struct npe *npe, void *msg, const char *what)
+{
+       u32 *recv = msg;
+       int cycles = 0, cnt = 0;
+
+       debug_msg(npe, "Trying to receive message %s\n", what);
+
+       while (cycles < MAX_RETRIES) {
+               if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE) {
+                       recv[cnt++] = __raw_readl(&npe->regs->in_out_fifo);
+                       if (cnt == 2)
+                               break;
+               } else {
+                       udelay(1);
+                       cycles++;
+               }
+       }
+
+       switch(cnt) {
+       case 1:
+               debug_msg(npe, "Received [%08X]\n", recv[0]);
+               break;
+       case 2:
+               debug_msg(npe, "Received [%08X:%08X]\n", recv[0], recv[1]);
+               break;
+       }
+
+       if (cycles == MAX_RETRIES) {
+               debug_msg(npe, "Timeout waiting for message\n");
+               return -ETIMEDOUT;
+       }
+
+#if DEBUG_MSG > 1
+       debug_msg(npe, "Receiving a message took %i cycles\n", cycles);
+#endif
+       return 0;
+}
+
+int npe_send_recv_message(struct npe *npe, void *msg, const char *what)
+{
+       int result;
+       u32 *send = msg, recv[2];
+
+       if ((result = npe_send_message(npe, msg, what)) != 0)
+               return result;
+       if ((result = npe_recv_message(npe, recv, what)) != 0)
+               return result;
+
+       if ((recv[0] != send[0]) || (recv[1] != send[1])) {
+               debug_msg(npe, "Message %s: unexpected message received\n",
+                         what);
+               return -EIO;
+       }
+       return 0;
+}
+
+
+int npe_load_firmware(struct npe *npe, const char *name, struct device *dev)
+{
+       const struct firmware *fw_entry;
+
+       struct dl_block {
+               u32 type;
+               u32 offset;
+       } *blk;
+
+       struct dl_image {
+               u32 magic;
+               u32 id;
+               u32 size;
+               union {
+                       u32 data[0];
+                       struct dl_block blocks[0];
+               };
+       } *image;
+
+       struct dl_codeblock {
+               u32 npe_addr;
+               u32 size;
+               u32 data[0];
+       } *cb;
+
+       int i, j, err, data_size, instr_size, blocks, table_end;
+       u32 cmd;
+
+       if ((err = request_firmware(&fw_entry, name, dev)) != 0)
+               return err;
+
+       err = -EINVAL;
+       if (fw_entry->size < sizeof(struct dl_image)) {
+               print_npe(KERN_ERR, npe, "incomplete firmware file\n");
+               goto err;
+       }
+       image = (struct dl_image*)fw_entry->data;
+
+#if DEBUG_FW
+       print_npe(KERN_DEBUG, npe, "firmware: %08X %08X %08X (0x%X bytes)\n",
+                 image->magic, image->id, image->size, image->size * 4);
+#endif
+
+       if (image->magic == swab32(FW_MAGIC)) { /* swapped file */
+               image->id = swab32(image->id);
+               image->size = swab32(image->size);
+       } else if (image->magic != FW_MAGIC) {
+               print_npe(KERN_ERR, npe, "bad firmware file magic: 0x%X\n",
+                         image->magic);
+               goto err;
+       }
+       if ((image->size * 4 + sizeof(struct dl_image)) != fw_entry->size) {
+               print_npe(KERN_ERR, npe,
+                         "inconsistent size of firmware file\n");
+               goto err;
+       }
+       if (((image->id >> 24) & 0xF /* NPE ID */) != npe->id) {
+               print_npe(KERN_ERR, npe, "firmware file NPE ID mismatch\n");
+               goto err;
+       }
+       if (image->magic == swab32(FW_MAGIC))
+               for (i = 0; i < image->size; i++)
+                       image->data[i] = swab32(image->data[i]);
+
+       if (cpu_is_ixp42x() && ((image->id >> 28) & 0xF /* device ID */)) {
+               print_npe(KERN_INFO, npe, "IXP43x/IXP46x firmware ignored on "
+                         "IXP42x\n");
+               goto err;
+       }
+
+       if (npe_running(npe)) {
+               print_npe(KERN_INFO, npe, "unable to load firmware, NPE is "
+                         "already running\n");
+               err = -EBUSY;
+               goto err;
+       }
+#if 0
+       npe_stop(npe);
+       npe_reset(npe);
+#endif
+
+       print_npe(KERN_INFO, npe, "firmware functionality 0x%X, "
+                 "revision 0x%X:%X\n", (image->id >> 16) & 0xFF,
+                 (image->id >> 8) & 0xFF, image->id & 0xFF);
+
+       if (cpu_is_ixp42x()) {
+               if (!npe->id)
+                       instr_size = NPE_A_42X_INSTR_SIZE;
+               else
+                       instr_size = NPE_B_AND_C_42X_INSTR_SIZE;
+               data_size = NPE_42X_DATA_SIZE;
+       } else {
+               instr_size = NPE_46X_INSTR_SIZE;
+               data_size = NPE_46X_DATA_SIZE;
+       }
+
+       for (blocks = 0; blocks * sizeof(struct dl_block) / 4 < image->size;
+            blocks++)
+               if (image->blocks[blocks].type == FW_BLOCK_TYPE_EOF)
+                       break;
+       if (blocks * sizeof(struct dl_block) / 4 >= image->size) {
+               print_npe(KERN_INFO, npe, "firmware EOF block marker not "
+                         "found\n");
+               goto err;
+       }
+
+#if DEBUG_FW
+       print_npe(KERN_DEBUG, npe, "%i firmware blocks found\n", blocks);
+#endif
+
+       table_end = blocks * sizeof(struct dl_block) / 4 + 1 /* EOF marker */;
+       for (i = 0, blk = image->blocks; i < blocks; i++, blk++) {
+               if (blk->offset > image->size - sizeof(struct dl_codeblock) / 4
+                   || blk->offset < table_end) {
+                       print_npe(KERN_INFO, npe, "invalid offset 0x%X of "
+                                 "firmware block #%i\n", blk->offset, i);
+                       goto err;
+               }
+
+               cb = (struct dl_codeblock*)&image->data[blk->offset];
+               if (blk->type == FW_BLOCK_TYPE_INSTR) {
+                       if (cb->npe_addr + cb->size > instr_size)
+                               goto too_big;
+                       cmd = CMD_WR_INS_MEM;
+               } else if (blk->type == FW_BLOCK_TYPE_DATA) {
+                       if (cb->npe_addr + cb->size > data_size)
+                               goto too_big;
+                       cmd = CMD_WR_DATA_MEM;
+               } else {
+                       print_npe(KERN_INFO, npe, "invalid firmware block #%i "
+                                 "type 0x%X\n", i, blk->type);
+                       goto err;
+               }
+               if (blk->offset + sizeof(*cb) / 4 + cb->size > image->size) {
+                       print_npe(KERN_INFO, npe, "firmware block #%i doesn't "
+                                 "fit in firmware image: type %c, start 0x%X,"
+                                 " length 0x%X\n", i,
+                                 blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
+                                 cb->npe_addr, cb->size);
+                       goto err;
+               }
+
+               for (j = 0; j < cb->size; j++)
+                       npe_cmd_write(npe, cb->npe_addr + j, cmd, cb->data[j]);
+       }
+
+       npe_start(npe);
+       if (!npe_running(npe))
+               print_npe(KERN_ERR, npe, "unable to start\n");
+       release_firmware(fw_entry);
+       return 0;
+
+too_big:
+       print_npe(KERN_INFO, npe, "firmware block #%i doesn't fit in NPE "
+                 "memory: type %c, start 0x%X, length 0x%X\n", i,
+                 blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
+                 cb->npe_addr, cb->size);
+err:
+       release_firmware(fw_entry);
+       return err;
+}
+
+
+struct npe *npe_request(unsigned id)
+{
+       if (id < NPE_COUNT)
+               if (npe_tab[id].valid)
+                       if (try_module_get(THIS_MODULE))
+                               return &npe_tab[id];
+       return NULL;
+}
+
+void npe_release(struct npe *npe)
+{
+       module_put(THIS_MODULE);
+}
+
+static int ixp4xx_npe_probe(struct platform_device *pdev)
+{
+       int i, found = 0;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+
+       for (i = 0; i < NPE_COUNT; i++) {
+               struct npe *npe = &npe_tab[i];
+
+               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+               if (!res)
+                       return -ENODEV;
+
+               if (!(ixp4xx_read_feature_bits() &
+                     (IXP4XX_FEATURE_RESET_NPEA << i))) {
+                       dev_info(dev, "NPE%d at 0x%08x-0x%08x not available\n",
+                                i, res->start, res->end);
+                       continue; /* NPE already disabled or not present */
+               }
+               npe->regs = devm_ioremap_resource(dev, res);
+               if (!npe->regs)
+                       return -ENOMEM;
+
+               if (npe_reset(npe)) {
+                       dev_info(dev, "NPE%d at 0x%08x-0x%08x does not reset\n",
+                                i, res->start, res->end);
+                       continue;
+               }
+               npe->valid = 1;
+               dev_info(dev, "NPE%d at 0x%08x-0x%08x registered\n",
+                        i, res->start, res->end);
+               found++;
+       }
+
+       if (!found)
+               return -ENODEV;
+       return 0;
+}
+
+static int ixp4xx_npe_remove(struct platform_device *pdev)
+{
+       int i;
+
+       for (i = 0; i < NPE_COUNT; i++)
+               if (npe_tab[i].regs) {
+                       npe_reset(&npe_tab[i]);
+               }
+
+       return 0;
+}
+
+static const struct of_device_id ixp4xx_npe_of_match[] = {
+       {
+               .compatible = "intel,ixp4xx-network-processing-engine",
+        },
+       {},
+};
+
+static struct platform_driver ixp4xx_npe_driver = {
+       .driver = {
+               .name           = "ixp4xx-npe",
+               .of_match_table = of_match_ptr(ixp4xx_npe_of_match),
+       },
+       .probe = ixp4xx_npe_probe,
+       .remove = ixp4xx_npe_remove,
+};
+module_platform_driver(ixp4xx_npe_driver);
+
+MODULE_AUTHOR("Krzysztof Halasa");
+MODULE_LICENSE("GPL v2");
+MODULE_FIRMWARE(NPE_A_FIRMWARE);
+MODULE_FIRMWARE(NPE_B_FIRMWARE);
+MODULE_FIRMWARE(NPE_C_FIRMWARE);
+
+EXPORT_SYMBOL(npe_names);
+EXPORT_SYMBOL(npe_running);
+EXPORT_SYMBOL(npe_request);
+EXPORT_SYMBOL(npe_release);
+EXPORT_SYMBOL(npe_load_firmware);
+EXPORT_SYMBOL(npe_send_message);
+EXPORT_SYMBOL(npe_recv_message);
+EXPORT_SYMBOL(npe_send_recv_message);
diff --git a/drivers/soc/ixp4xx/ixp4xx-qmgr.c b/drivers/soc/ixp4xx/ixp4xx-qmgr.c
new file mode 100644 (file)
index 0000000..13a8a13
--- /dev/null
@@ -0,0 +1,488 @@
+/*
+ * Intel IXP4xx Queue Manager driver for Linux
+ *
+ * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/soc/ixp4xx/qmgr.h>
+
+static struct qmgr_regs __iomem *qmgr_regs;
+static int qmgr_irq_1;
+static int qmgr_irq_2;
+static spinlock_t qmgr_lock;
+static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
+static void (*irq_handlers[QUEUES])(void *pdev);
+static void *irq_pdevs[QUEUES];
+
+#if DEBUG_QMGR
+char qmgr_queue_descs[QUEUES][32];
+#endif
+
+void qmgr_put_entry(unsigned int queue, u32 val)
+{
+#if DEBUG_QMGR
+       BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
+
+       printk(KERN_DEBUG "Queue %s(%i) put %X\n",
+              qmgr_queue_descs[queue], queue, val);
+#endif
+       __raw_writel(val, &qmgr_regs->acc[queue][0]);
+}
+
+u32 qmgr_get_entry(unsigned int queue)
+{
+       u32 val;
+       val = __raw_readl(&qmgr_regs->acc[queue][0]);
+#if DEBUG_QMGR
+       BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
+
+       printk(KERN_DEBUG "Queue %s(%i) get %X\n",
+              qmgr_queue_descs[queue], queue, val);
+#endif
+       return val;
+}
+
+static int __qmgr_get_stat1(unsigned int queue)
+{
+       return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
+               >> ((queue & 7) << 2)) & 0xF;
+}
+
+static int __qmgr_get_stat2(unsigned int queue)
+{
+       BUG_ON(queue >= HALF_QUEUES);
+       return (__raw_readl(&qmgr_regs->stat2[queue >> 4])
+               >> ((queue & 0xF) << 1)) & 0x3;
+}
+
+/**
+ * qmgr_stat_empty() - checks if a hardware queue is empty
+ * @queue:     queue number
+ *
+ * Returns non-zero value if the queue is empty.
+ */
+int qmgr_stat_empty(unsigned int queue)
+{
+       BUG_ON(queue >= HALF_QUEUES);
+       return __qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY;
+}
+
+/**
+ * qmgr_stat_below_low_watermark() - checks if a queue is below low watermark
+ * @queue:     queue number
+ *
+ * Returns non-zero value if the queue is below low watermark.
+ */
+int qmgr_stat_below_low_watermark(unsigned int queue)
+{
+       if (queue >= HALF_QUEUES)
+               return (__raw_readl(&qmgr_regs->statne_h) >>
+                       (queue - HALF_QUEUES)) & 0x01;
+       return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY;
+}
+
+/**
+ * qmgr_stat_full() - checks if a hardware queue is full
+ * @queue:     queue number
+ *
+ * Returns non-zero value if the queue is full.
+ */
+int qmgr_stat_full(unsigned int queue)
+{
+       if (queue >= HALF_QUEUES)
+               return (__raw_readl(&qmgr_regs->statf_h) >>
+                       (queue - HALF_QUEUES)) & 0x01;
+       return __qmgr_get_stat1(queue) & QUEUE_STAT1_FULL;
+}
+
+/**
+ * qmgr_stat_overflow() - checks if a hardware queue experienced overflow
+ * @queue:     queue number
+ *
+ * Returns non-zero value if the queue experienced overflow.
+ */
+int qmgr_stat_overflow(unsigned int queue)
+{
+       return __qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW;
+}
+
+void qmgr_set_irq(unsigned int queue, int src,
+                 void (*handler)(void *pdev), void *pdev)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&qmgr_lock, flags);
+       if (queue < HALF_QUEUES) {
+               u32 __iomem *reg;
+               int bit;
+               BUG_ON(src > QUEUE_IRQ_SRC_NOT_FULL);
+               reg = &qmgr_regs->irqsrc[queue >> 3]; /* 8 queues per u32 */
+               bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
+               __raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit),
+                            reg);
+       } else
+               /* IRQ source for queues 32-63 is fixed */
+               BUG_ON(src != QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY);
+
+       irq_handlers[queue] = handler;
+       irq_pdevs[queue] = pdev;
+       spin_unlock_irqrestore(&qmgr_lock, flags);
+}
+
+
+static irqreturn_t qmgr_irq1_a0(int irq, void *pdev)
+{
+       int i, ret = 0;
+       u32 en_bitmap, src, stat;
+
+       /* ACK - it may clear any bits so don't rely on it */
+       __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[0]);
+
+       en_bitmap = qmgr_regs->irqen[0];
+       while (en_bitmap) {
+               i = __fls(en_bitmap); /* number of the last "low" queue */
+               en_bitmap &= ~BIT(i);
+               src = qmgr_regs->irqsrc[i >> 3];
+               stat = qmgr_regs->stat1[i >> 3];
+               if (src & 4) /* the IRQ condition is inverted */
+                       stat = ~stat;
+               if (stat & BIT(src & 3)) {
+                       irq_handlers[i](irq_pdevs[i]);
+                       ret = IRQ_HANDLED;
+               }
+       }
+       return ret;
+}
+
+
+static irqreturn_t qmgr_irq2_a0(int irq, void *pdev)
+{
+       int i, ret = 0;
+       u32 req_bitmap;
+
+       /* ACK - it may clear any bits so don't rely on it */
+       __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[1]);
+
+       req_bitmap = qmgr_regs->irqen[1] & qmgr_regs->statne_h;
+       while (req_bitmap) {
+               i = __fls(req_bitmap); /* number of the last "high" queue */
+               req_bitmap &= ~BIT(i);
+               irq_handlers[HALF_QUEUES + i](irq_pdevs[HALF_QUEUES + i]);
+               ret = IRQ_HANDLED;
+       }
+       return ret;
+}
+
+
+static irqreturn_t qmgr_irq(int irq, void *pdev)
+{
+       int i, half = (irq == qmgr_irq_1 ? 0 : 1);
+       u32 req_bitmap = __raw_readl(&qmgr_regs->irqstat[half]);
+
+       if (!req_bitmap)
+               return 0;
+       __raw_writel(req_bitmap, &qmgr_regs->irqstat[half]); /* ACK */
+
+       while (req_bitmap) {
+               i = __fls(req_bitmap); /* number of the last queue */
+               req_bitmap &= ~BIT(i);
+               i += half * HALF_QUEUES;
+               irq_handlers[i](irq_pdevs[i]);
+       }
+       return IRQ_HANDLED;
+}
+
+
+void qmgr_enable_irq(unsigned int queue)
+{
+       unsigned long flags;
+       int half = queue / 32;
+       u32 mask = 1 << (queue & (HALF_QUEUES - 1));
+
+       spin_lock_irqsave(&qmgr_lock, flags);
+       __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) | mask,
+                    &qmgr_regs->irqen[half]);
+       spin_unlock_irqrestore(&qmgr_lock, flags);
+}
+
+void qmgr_disable_irq(unsigned int queue)
+{
+       unsigned long flags;
+       int half = queue / 32;
+       u32 mask = 1 << (queue & (HALF_QUEUES - 1));
+
+       spin_lock_irqsave(&qmgr_lock, flags);
+       __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) & ~mask,
+                    &qmgr_regs->irqen[half]);
+       __raw_writel(mask, &qmgr_regs->irqstat[half]); /* clear */
+       spin_unlock_irqrestore(&qmgr_lock, flags);
+}
+
+static inline void shift_mask(u32 *mask)
+{
+       mask[3] = mask[3] << 1 | mask[2] >> 31;
+       mask[2] = mask[2] << 1 | mask[1] >> 31;
+       mask[1] = mask[1] << 1 | mask[0] >> 31;
+       mask[0] <<= 1;
+}
+
+#if DEBUG_QMGR
+int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
+                      unsigned int nearly_empty_watermark,
+                      unsigned int nearly_full_watermark,
+                      const char *desc_format, const char* name)
+#else
+int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
+                        unsigned int nearly_empty_watermark,
+                        unsigned int nearly_full_watermark)
+#endif
+{
+       u32 cfg, addr = 0, mask[4]; /* in 16-dwords */
+       int err;
+
+       BUG_ON(queue >= QUEUES);
+
+       if ((nearly_empty_watermark | nearly_full_watermark) & ~7)
+               return -EINVAL;
+
+       switch (len) {
+       case  16:
+               cfg = 0 << 24;
+               mask[0] = 0x1;
+               break;
+       case  32:
+               cfg = 1 << 24;
+               mask[0] = 0x3;
+               break;
+       case  64:
+               cfg = 2 << 24;
+               mask[0] = 0xF;
+               break;
+       case 128:
+               cfg = 3 << 24;
+               mask[0] = 0xFF;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       cfg |= nearly_empty_watermark << 26;
+       cfg |= nearly_full_watermark << 29;
+       len /= 16;              /* in 16-dwords: 1, 2, 4 or 8 */
+       mask[1] = mask[2] = mask[3] = 0;
+
+       if (!try_module_get(THIS_MODULE))
+               return -ENODEV;
+
+       spin_lock_irq(&qmgr_lock);
+       if (__raw_readl(&qmgr_regs->sram[queue])) {
+               err = -EBUSY;
+               goto err;
+       }
+
+       while (1) {
+               if (!(used_sram_bitmap[0] & mask[0]) &&
+                   !(used_sram_bitmap[1] & mask[1]) &&
+                   !(used_sram_bitmap[2] & mask[2]) &&
+                   !(used_sram_bitmap[3] & mask[3]))
+                       break; /* found free space */
+
+               addr++;
+               shift_mask(mask);
+               if (addr + len > ARRAY_SIZE(qmgr_regs->sram)) {
+                       printk(KERN_ERR "qmgr: no free SRAM space for"
+                              " queue %i\n", queue);
+                       err = -ENOMEM;
+                       goto err;
+               }
+       }
+
+       used_sram_bitmap[0] |= mask[0];
+       used_sram_bitmap[1] |= mask[1];
+       used_sram_bitmap[2] |= mask[2];
+       used_sram_bitmap[3] |= mask[3];
+       __raw_writel(cfg | (addr << 14), &qmgr_regs->sram[queue]);
+#if DEBUG_QMGR
+       snprintf(qmgr_queue_descs[queue], sizeof(qmgr_queue_descs[0]),
+                desc_format, name);
+       printk(KERN_DEBUG "qmgr: requested queue %s(%i) addr = 0x%02X\n",
+              qmgr_queue_descs[queue], queue, addr);
+#endif
+       spin_unlock_irq(&qmgr_lock);
+       return 0;
+
+err:
+       spin_unlock_irq(&qmgr_lock);
+       module_put(THIS_MODULE);
+       return err;
+}
+
+void qmgr_release_queue(unsigned int queue)
+{
+       u32 cfg, addr, mask[4];
+
+       BUG_ON(queue >= QUEUES); /* not in valid range */
+
+       spin_lock_irq(&qmgr_lock);
+       cfg = __raw_readl(&qmgr_regs->sram[queue]);
+       addr = (cfg >> 14) & 0xFF;
+
+       BUG_ON(!addr);          /* not requested */
+
+       switch ((cfg >> 24) & 3) {
+       case 0: mask[0] = 0x1; break;
+       case 1: mask[0] = 0x3; break;
+       case 2: mask[0] = 0xF; break;
+       case 3: mask[0] = 0xFF; break;
+       }
+
+       mask[1] = mask[2] = mask[3] = 0;
+
+       while (addr--)
+               shift_mask(mask);
+
+#if DEBUG_QMGR
+       printk(KERN_DEBUG "qmgr: releasing queue %s(%i)\n",
+              qmgr_queue_descs[queue], queue);
+       qmgr_queue_descs[queue][0] = '\x0';
+#endif
+
+       while ((addr = qmgr_get_entry(queue)))
+               printk(KERN_ERR "qmgr: released queue %i not empty: 0x%08X\n",
+                      queue, addr);
+
+       __raw_writel(0, &qmgr_regs->sram[queue]);
+
+       used_sram_bitmap[0] &= ~mask[0];
+       used_sram_bitmap[1] &= ~mask[1];
+       used_sram_bitmap[2] &= ~mask[2];
+       used_sram_bitmap[3] &= ~mask[3];
+       irq_handlers[queue] = NULL; /* catch IRQ bugs */
+       spin_unlock_irq(&qmgr_lock);
+
+       module_put(THIS_MODULE);
+}
+
+static int ixp4xx_qmgr_probe(struct platform_device *pdev)
+{
+       int i, err;
+       irq_handler_t handler1, handler2;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       int irq1, irq2;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+       qmgr_regs = devm_ioremap_resource(dev, res);
+       if (!qmgr_regs)
+               return -ENOMEM;
+
+       irq1 = platform_get_irq(pdev, 0);
+       if (irq1 <= 0)
+               return irq1 ? irq1 : -EINVAL;
+       qmgr_irq_1 = irq1;
+       irq2 = platform_get_irq(pdev, 1);
+       if (irq2 <= 0)
+               return irq2 ? irq2 : -EINVAL;
+       qmgr_irq_2 = irq2;
+
+       /* reset qmgr registers */
+       for (i = 0; i < 4; i++) {
+               __raw_writel(0x33333333, &qmgr_regs->stat1[i]);
+               __raw_writel(0, &qmgr_regs->irqsrc[i]);
+       }
+       for (i = 0; i < 2; i++) {
+               __raw_writel(0, &qmgr_regs->stat2[i]);
+               __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[i]); /* clear */
+               __raw_writel(0, &qmgr_regs->irqen[i]);
+       }
+
+       __raw_writel(0xFFFFFFFF, &qmgr_regs->statne_h);
+       __raw_writel(0, &qmgr_regs->statf_h);
+
+       for (i = 0; i < QUEUES; i++)
+               __raw_writel(0, &qmgr_regs->sram[i]);
+
+       if (cpu_is_ixp42x_rev_a0()) {
+               handler1 = qmgr_irq1_a0;
+               handler2 = qmgr_irq2_a0;
+       } else
+               handler1 = handler2 = qmgr_irq;
+
+       err = devm_request_irq(dev, irq1, handler1, 0, "IXP4xx Queue Manager",
+                              NULL);
+       if (err) {
+               dev_err(dev, "failed to request IRQ%i (%i)\n",
+                       irq1, err);
+               return err;
+       }
+
+       err = devm_request_irq(dev, irq2, handler2, 0, "IXP4xx Queue Manager",
+                              NULL);
+       if (err) {
+               dev_err(dev, "failed to request IRQ%i (%i)\n",
+                       irq2, err);
+               return err;
+       }
+
+       used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */
+       spin_lock_init(&qmgr_lock);
+
+       dev_info(dev, "IXP4xx Queue Manager initialized.\n");
+       return 0;
+}
+
+static int ixp4xx_qmgr_remove(struct platform_device *pdev)
+{
+       synchronize_irq(qmgr_irq_1);
+       synchronize_irq(qmgr_irq_2);
+       return 0;
+}
+
+static const struct of_device_id ixp4xx_qmgr_of_match[] = {
+       {
+               .compatible = "intel,ixp4xx-ahb-queue-manager",
+        },
+       {},
+};
+
+static struct platform_driver ixp4xx_qmgr_driver = {
+       .driver = {
+               .name           = "ixp4xx-qmgr",
+               .of_match_table = of_match_ptr(ixp4xx_qmgr_of_match),
+       },
+       .probe = ixp4xx_qmgr_probe,
+       .remove = ixp4xx_qmgr_remove,
+};
+module_platform_driver(ixp4xx_qmgr_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Krzysztof Halasa");
+
+EXPORT_SYMBOL(qmgr_put_entry);
+EXPORT_SYMBOL(qmgr_get_entry);
+EXPORT_SYMBOL(qmgr_stat_empty);
+EXPORT_SYMBOL(qmgr_stat_below_low_watermark);
+EXPORT_SYMBOL(qmgr_stat_full);
+EXPORT_SYMBOL(qmgr_stat_overflow);
+EXPORT_SYMBOL(qmgr_set_irq);
+EXPORT_SYMBOL(qmgr_enable_irq);
+EXPORT_SYMBOL(qmgr_disable_irq);
+#if DEBUG_QMGR
+EXPORT_SYMBOL(qmgr_queue_descs);
+EXPORT_SYMBOL(qmgr_request_queue);
+#else
+EXPORT_SYMBOL(__qmgr_request_queue);
+#endif
+EXPORT_SYMBOL(qmgr_release_queue);
index 8236a6c..c4449a1 100644 (file)
@@ -381,6 +381,10 @@ enum pwrap_regs {
        PWRAP_EXT_GPS_AUXADC_RDATA_ADDR,
        PWRAP_GPSINF_0_STA,
        PWRAP_GPSINF_1_STA,
+
+       /* MT8516 only regs */
+       PWRAP_OP_TYPE,
+       PWRAP_MSB_FIRST,
 };
 
 static int mt2701_regs[] = {
@@ -852,6 +856,91 @@ static int mt8183_regs[] = {
        [PWRAP_WACS2_VLDCLR] =                  0xC28,
 };
 
+static int mt8516_regs[] = {
+       [PWRAP_MUX_SEL] =               0x0,
+       [PWRAP_WRAP_EN] =               0x4,
+       [PWRAP_DIO_EN] =                0x8,
+       [PWRAP_SIDLY] =                 0xc,
+       [PWRAP_RDDMY] =                 0x10,
+       [PWRAP_SI_CK_CON] =             0x14,
+       [PWRAP_CSHEXT_WRITE] =          0x18,
+       [PWRAP_CSHEXT_READ] =           0x1c,
+       [PWRAP_CSLEXT_START] =          0x20,
+       [PWRAP_CSLEXT_END] =            0x24,
+       [PWRAP_STAUPD_PRD] =            0x28,
+       [PWRAP_STAUPD_GRPEN] =          0x2c,
+       [PWRAP_STAUPD_MAN_TRIG] =       0x40,
+       [PWRAP_STAUPD_STA] =            0x44,
+       [PWRAP_WRAP_STA] =              0x48,
+       [PWRAP_HARB_INIT] =             0x4c,
+       [PWRAP_HARB_HPRIO] =            0x50,
+       [PWRAP_HIPRIO_ARB_EN] =         0x54,
+       [PWRAP_HARB_STA0] =             0x58,
+       [PWRAP_HARB_STA1] =             0x5c,
+       [PWRAP_MAN_EN] =                0x60,
+       [PWRAP_MAN_CMD] =               0x64,
+       [PWRAP_MAN_RDATA] =             0x68,
+       [PWRAP_MAN_VLDCLR] =            0x6c,
+       [PWRAP_WACS0_EN] =              0x70,
+       [PWRAP_INIT_DONE0] =            0x74,
+       [PWRAP_WACS0_CMD] =             0x78,
+       [PWRAP_WACS0_RDATA] =           0x7c,
+       [PWRAP_WACS0_VLDCLR] =          0x80,
+       [PWRAP_WACS1_EN] =              0x84,
+       [PWRAP_INIT_DONE1] =            0x88,
+       [PWRAP_WACS1_CMD] =             0x8c,
+       [PWRAP_WACS1_RDATA] =           0x90,
+       [PWRAP_WACS1_VLDCLR] =          0x94,
+       [PWRAP_WACS2_EN] =              0x98,
+       [PWRAP_INIT_DONE2] =            0x9c,
+       [PWRAP_WACS2_CMD] =             0xa0,
+       [PWRAP_WACS2_RDATA] =           0xa4,
+       [PWRAP_WACS2_VLDCLR] =          0xa8,
+       [PWRAP_INT_EN] =                0xac,
+       [PWRAP_INT_FLG_RAW] =           0xb0,
+       [PWRAP_INT_FLG] =               0xb4,
+       [PWRAP_INT_CLR] =               0xb8,
+       [PWRAP_SIG_ADR] =               0xbc,
+       [PWRAP_SIG_MODE] =              0xc0,
+       [PWRAP_SIG_VALUE] =             0xc4,
+       [PWRAP_SIG_ERRVAL] =            0xc8,
+       [PWRAP_CRC_EN] =                0xcc,
+       [PWRAP_TIMER_EN] =              0xd0,
+       [PWRAP_TIMER_STA] =             0xd4,
+       [PWRAP_WDT_UNIT] =              0xd8,
+       [PWRAP_WDT_SRC_EN] =            0xdc,
+       [PWRAP_WDT_FLG] =               0xe0,
+       [PWRAP_DEBUG_INT_SEL] =         0xe4,
+       [PWRAP_DVFS_ADR0] =             0xe8,
+       [PWRAP_DVFS_WDATA0] =           0xec,
+       [PWRAP_DVFS_ADR1] =             0xf0,
+       [PWRAP_DVFS_WDATA1] =           0xf4,
+       [PWRAP_DVFS_ADR2] =             0xf8,
+       [PWRAP_DVFS_WDATA2] =           0xfc,
+       [PWRAP_DVFS_ADR3] =             0x100,
+       [PWRAP_DVFS_WDATA3] =           0x104,
+       [PWRAP_DVFS_ADR4] =             0x108,
+       [PWRAP_DVFS_WDATA4] =           0x10c,
+       [PWRAP_DVFS_ADR5] =             0x110,
+       [PWRAP_DVFS_WDATA5] =           0x114,
+       [PWRAP_DVFS_ADR6] =             0x118,
+       [PWRAP_DVFS_WDATA6] =           0x11c,
+       [PWRAP_DVFS_ADR7] =             0x120,
+       [PWRAP_DVFS_WDATA7] =           0x124,
+       [PWRAP_SPMINF_STA] =            0x128,
+       [PWRAP_CIPHER_KEY_SEL] =        0x12c,
+       [PWRAP_CIPHER_IV_SEL] =         0x130,
+       [PWRAP_CIPHER_EN] =             0x134,
+       [PWRAP_CIPHER_RDY] =            0x138,
+       [PWRAP_CIPHER_MODE] =           0x13c,
+       [PWRAP_CIPHER_SWRST] =          0x140,
+       [PWRAP_DCM_EN] =                0x144,
+       [PWRAP_DCM_DBC_PRD] =           0x148,
+       [PWRAP_SW_RST] =                0x168,
+       [PWRAP_OP_TYPE] =               0x16c,
+       [PWRAP_MSB_FIRST] =             0x170,
+};
+
 enum pmic_type {
        PMIC_MT6323,
        PMIC_MT6351,
@@ -869,6 +958,7 @@ enum pwrap_type {
        PWRAP_MT8135,
        PWRAP_MT8173,
        PWRAP_MT8183,
+       PWRAP_MT8516,
 };
 
 struct pmic_wrapper;
@@ -1281,7 +1371,7 @@ static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
 static int pwrap_init_cipher(struct pmic_wrapper *wrp)
 {
        int ret;
-       u32 rdata;
+       u32 rdata = 0;
 
        pwrap_writel(wrp, 0x1, PWRAP_CIPHER_SWRST);
        pwrap_writel(wrp, 0x0, PWRAP_CIPHER_SWRST);
@@ -1297,6 +1387,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
        case PWRAP_MT6765:
        case PWRAP_MT6797:
        case PWRAP_MT8173:
+       case PWRAP_MT8516:
                pwrap_writel(wrp, 1, PWRAP_CIPHER_EN);
                break;
        case PWRAP_MT7622:
@@ -1478,7 +1569,8 @@ static int pwrap_init(struct pmic_wrapper *wrp)
 {
        int ret;
 
-       reset_control_reset(wrp->rstc);
+       if (wrp->rstc)
+               reset_control_reset(wrp->rstc);
        if (wrp->rstc_bridge)
                reset_control_reset(wrp->rstc_bridge);
 
@@ -1764,6 +1856,18 @@ static const struct pmic_wrapper_type pwrap_mt8183 = {
        .init_soc_specific = pwrap_mt8183_init_soc_specific,
 };
 
+static struct pmic_wrapper_type pwrap_mt8516 = {
+       .regs = mt8516_regs,
+       .type = PWRAP_MT8516,
+       .arb_en_all = 0xff,
+       .int_en_all = ~(u32)(BIT(31) | BIT(2)),
+       .spi_w = PWRAP_MAN_CMD_SPI_WRITE,
+       .wdt_src = PWRAP_WDT_SRC_MASK_ALL,
+       .caps = PWRAP_CAP_DCM,
+       .init_reg_clock = pwrap_mt2701_init_reg_clock,
+       .init_soc_specific = NULL,
+};
+
 static const struct of_device_id of_pwrap_match_tbl[] = {
        {
                .compatible = "mediatek,mt2701-pwrap",
@@ -1786,6 +1890,9 @@ static const struct of_device_id of_pwrap_match_tbl[] = {
        }, {
                .compatible = "mediatek,mt8183-pwrap",
                .data = &pwrap_mt8183,
+       }, {
+               .compatible = "mediatek,mt8516-pwrap",
+               .data = &pwrap_mt8516,
        }, {
                /* sentinel */
        }
index c701b3b..f6c3d17 100644 (file)
@@ -248,8 +248,8 @@ static int cmd_db_dev_probe(struct platform_device *pdev)
        }
 
        cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WB);
-       if (IS_ERR_OR_NULL(cmd_db_header)) {
-               ret = PTR_ERR(cmd_db_header);
+       if (!cmd_db_header) {
+               ret = -ENOMEM;
                cmd_db_header = NULL;
                return ret;
        }
index c239a28..f9e309f 100644 (file)
@@ -345,8 +345,7 @@ int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout)
        struct qmi_handle *qmi = txn->qmi;
        int ret;
 
-       ret = wait_for_completion_interruptible_timeout(&txn->completion,
-                                                       timeout);
+       ret = wait_for_completion_timeout(&txn->completion, timeout);
 
        mutex_lock(&qmi->txn_lock);
        mutex_lock(&txn->lock);
@@ -354,9 +353,7 @@ int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout)
        mutex_unlock(&txn->lock);
        mutex_unlock(&qmi->txn_lock);
 
-       if (ret < 0)
-               return ret;
-       else if (ret == 0)
+       if (ret == 0)
                return -ETIMEDOUT;
        else
                return txn->result;
index 7200d76..6f5e8be 100644 (file)
@@ -137,6 +137,26 @@ static struct class rmtfs_class = {
        .name           = "rmtfs",
 };
 
+static int qcom_rmtfs_mem_mmap(struct file *filep, struct vm_area_struct *vma)
+{
+       struct qcom_rmtfs_mem *rmtfs_mem = filep->private_data;
+
+       if (vma->vm_end - vma->vm_start > rmtfs_mem->size) {
+               dev_dbg(&rmtfs_mem->dev,
+                       "vm_end[%lu] - vm_start[%lu] [%lu] > mem->size[%pa]\n",
+                       vma->vm_end, vma->vm_start,
+                       (vma->vm_end - vma->vm_start), &rmtfs_mem->size);
+               return -EINVAL;
+       }
+
+       vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+       return remap_pfn_range(vma,
+                              vma->vm_start,
+                              rmtfs_mem->addr >> PAGE_SHIFT,
+                              vma->vm_end - vma->vm_start,
+                              vma->vm_page_prot);
+}
+
 static const struct file_operations qcom_rmtfs_mem_fops = {
        .owner = THIS_MODULE,
        .open = qcom_rmtfs_mem_open,
@@ -144,6 +164,7 @@ static const struct file_operations qcom_rmtfs_mem_fops = {
        .write = qcom_rmtfs_mem_write,
        .release = qcom_rmtfs_mem_release,
        .llseek = default_llseek,
+       .mmap = qcom_rmtfs_mem_mmap,
 };
 
 static void qcom_rmtfs_mem_release_device(struct device *dev)
index 75bd9a8..e278fc1 100644 (file)
@@ -459,7 +459,7 @@ static int find_slots(struct tcs_group *tcs, const struct tcs_request *msg,
        do {
                slot = bitmap_find_next_zero_area(tcs->slots, MAX_TCS_SLOTS,
                                                  i, msg->num_cmds, 0);
-               if (slot == tcs->num_tcs * tcs->ncpt)
+               if (slot >= tcs->num_tcs * tcs->ncpt)
                        return -ENOMEM;
                i += tcs->ncpt;
        } while (slot + msg->num_cmds - 1 >= i);
index 4af96e6..3299cf5 100644 (file)
@@ -335,6 +335,9 @@ static int __init renesas_soc_init(void)
                /* R-Car M3-W ES1.1 incorrectly identifies as ES2.0 */
                if ((product & 0x7fff) == 0x5210)
                        product ^= 0x11;
+               /* R-Car M3-W ES1.3 incorrectly identifies as ES2.1 */
+               if ((product & 0x7fff) == 0x5211)
+                       product ^= 0x12;
                if (soc->id && ((product >> 8) & 0xff) != soc->id) {
                        pr_warn("SoC mismatch (product = 0x%x)\n", product);
                        return -ENODEV;
index 96882ff..3b81e1d 100644 (file)
@@ -66,9 +66,11 @@ static const struct rockchip_grf_info rk3228_grf __initconst = {
 };
 
 #define RK3288_GRF_SOC_CON0            0x244
+#define RK3288_GRF_SOC_CON2            0x24c
 
 static const struct rockchip_grf_value rk3288_defaults[] __initconst = {
        { "jtag switching", RK3288_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 12) },
+       { "pwm select", RK3288_GRF_SOC_CON2, HIWORD_UPDATE(1, 1, 0) },
 };
 
 static const struct rockchip_grf_info rk3288_grf __initconst = {
index 0df2585..5648e5c 100644 (file)
@@ -268,6 +268,14 @@ static const char * const tegra186_reset_levels[] = {
 };
 
 static const char * const tegra30_reset_sources[] = {
+       "POWER_ON_RESET",
+       "WATCHDOG",
+       "SENSOR",
+       "SW_MAIN",
+       "LP0"
+};
+
+static const char * const tegra210_reset_sources[] = {
        "POWER_ON_RESET",
        "WATCHDOG",
        "SENSOR",
@@ -656,10 +664,15 @@ static int tegra_genpd_power_on(struct generic_pm_domain *domain)
        int err;
 
        err = tegra_powergate_power_up(pg, true);
-       if (err)
+       if (err) {
                dev_err(dev, "failed to turn on PM domain %s: %d\n",
                        pg->genpd.name, err);
+               goto out;
+       }
+
+       reset_control_release(pg->reset);
 
+out:
        return err;
 }
 
@@ -669,10 +682,18 @@ static int tegra_genpd_power_off(struct generic_pm_domain *domain)
        struct device *dev = pg->pmc->dev;
        int err;
 
+       err = reset_control_acquire(pg->reset);
+       if (err < 0) {
+               pr_err("failed to acquire resets: %d\n", err);
+               return err;
+       }
+
        err = tegra_powergate_power_down(pg);
-       if (err)
+       if (err) {
                dev_err(dev, "failed to turn off PM domain %s: %d\n",
                        pg->genpd.name, err);
+               reset_control_release(pg->reset);
+       }
 
        return err;
 }
@@ -937,38 +958,53 @@ static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
        struct device *dev = pg->pmc->dev;
        int err;
 
-       pg->reset = of_reset_control_array_get_exclusive(np);
+       pg->reset = of_reset_control_array_get_exclusive_released(np);
        if (IS_ERR(pg->reset)) {
                err = PTR_ERR(pg->reset);
                dev_err(dev, "failed to get device resets: %d\n", err);
                return err;
        }
 
-       if (off)
+       err = reset_control_acquire(pg->reset);
+       if (err < 0) {
+               pr_err("failed to acquire resets: %d\n", err);
+               goto out;
+       }
+
+       if (off) {
                err = reset_control_assert(pg->reset);
-       else
+       } else {
                err = reset_control_deassert(pg->reset);
+               if (err < 0)
+                       goto out;
 
-       if (err)
+               reset_control_release(pg->reset);
+       }
+
+out:
+       if (err) {
+               reset_control_release(pg->reset);
                reset_control_put(pg->reset);
+       }
 
        return err;
 }
 
-static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
+static int tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
 {
        struct device *dev = pmc->dev;
        struct tegra_powergate *pg;
-       int id, err;
+       int id, err = 0;
        bool off;
 
        pg = kzalloc(sizeof(*pg), GFP_KERNEL);
        if (!pg)
-               return;
+               return -ENOMEM;
 
        id = tegra_powergate_lookup(pmc, np->name);
        if (id < 0) {
                dev_err(dev, "powergate lookup failed for %pOFn: %d\n", np, id);
+               err = -ENODEV;
                goto free_mem;
        }
 
@@ -1021,7 +1057,7 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
 
        dev_dbg(dev, "added PM domain %s\n", pg->genpd.name);
 
-       return;
+       return 0;
 
 remove_genpd:
        pm_genpd_remove(&pg->genpd);
@@ -1040,25 +1076,67 @@ set_available:
 
 free_mem:
        kfree(pg);
+
+       return err;
 }
 
-static void tegra_powergate_init(struct tegra_pmc *pmc,
-                                struct device_node *parent)
+static int tegra_powergate_init(struct tegra_pmc *pmc,
+                               struct device_node *parent)
 {
        struct device_node *np, *child;
-       unsigned int i;
+       int err = 0;
+
+       np = of_get_child_by_name(parent, "powergates");
+       if (!np)
+               return 0;
+
+       for_each_child_of_node(np, child) {
+               err = tegra_powergate_add(pmc, child);
+               if (err < 0) {
+                       of_node_put(child);
+                       break;
+               }
+       }
+
+       of_node_put(np);
+
+       return err;
+}
+
+static void tegra_powergate_remove(struct generic_pm_domain *genpd)
+{
+       struct tegra_powergate *pg = to_powergate(genpd);
+
+       reset_control_put(pg->reset);
+
+       while (pg->num_clks--)
+               clk_put(pg->clks[pg->num_clks]);
+
+       kfree(pg->clks);
 
-       /* Create a bitmap of the available and valid partitions */
-       for (i = 0; i < pmc->soc->num_powergates; i++)
-               if (pmc->soc->powergates[i])
-                       set_bit(i, pmc->powergates_available);
+       set_bit(pg->id, pmc->powergates_available);
+
+       kfree(pg);
+}
+
+static void tegra_powergate_remove_all(struct device_node *parent)
+{
+       struct generic_pm_domain *genpd;
+       struct device_node *np, *child;
 
        np = of_get_child_by_name(parent, "powergates");
        if (!np)
                return;
 
-       for_each_child_of_node(np, child)
-               tegra_powergate_add(pmc, child);
+       for_each_child_of_node(np, child) {
+               of_genpd_del_provider(child);
+
+               genpd = of_genpd_remove_last(child);
+               if (IS_ERR(genpd))
+                       continue;
+
+               tegra_powergate_remove(genpd);
+       }
 
        of_node_put(np);
 }
@@ -1709,13 +1787,16 @@ static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
 static ssize_t reset_reason_show(struct device *dev,
                                 struct device_attribute *attr, char *buf)
 {
-       u32 value, rst_src;
+       u32 value;
 
        value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
-       rst_src = (value & pmc->soc->regs->rst_source_mask) >>
-                       pmc->soc->regs->rst_source_shift;
+       value &= pmc->soc->regs->rst_source_mask;
+       value >>= pmc->soc->regs->rst_source_shift;
+
+       if (WARN_ON(value >= pmc->soc->num_reset_sources))
+               return sprintf(buf, "%s\n", "UNKNOWN");
 
-       return sprintf(buf, "%s\n", pmc->soc->reset_sources[rst_src]);
+       return sprintf(buf, "%s\n", pmc->soc->reset_sources[value]);
 }
 
 static DEVICE_ATTR_RO(reset_reason);
@@ -1723,13 +1804,16 @@ static DEVICE_ATTR_RO(reset_reason);
 static ssize_t reset_level_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       u32 value, rst_lvl;
+       u32 value;
 
        value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
-       rst_lvl = (value & pmc->soc->regs->rst_level_mask) >>
-                       pmc->soc->regs->rst_level_shift;
+       value &= pmc->soc->regs->rst_level_mask;
+       value >>= pmc->soc->regs->rst_level_shift;
 
-       return sprintf(buf, "%s\n", pmc->soc->reset_levels[rst_lvl]);
+       if (WARN_ON(value >= pmc->soc->num_reset_levels))
+               return sprintf(buf, "%s\n", "UNKNOWN");
+
+       return sprintf(buf, "%s\n", pmc->soc->reset_levels[value]);
 }
 
 static DEVICE_ATTR_RO(reset_level);
@@ -1999,7 +2083,7 @@ static int tegra_pmc_probe(struct platform_device *pdev)
        if (IS_ENABLED(CONFIG_DEBUG_FS)) {
                err = tegra_powergate_debugfs_init();
                if (err < 0)
-                       return err;
+                       goto cleanup_sysfs;
        }
 
        err = register_restart_handler(&tegra_pmc_restart_handler);
@@ -2013,9 +2097,13 @@ static int tegra_pmc_probe(struct platform_device *pdev)
        if (err)
                goto cleanup_restart_handler;
 
+       err = tegra_powergate_init(pmc, pdev->dev.of_node);
+       if (err < 0)
+               goto cleanup_powergates;
+
        err = tegra_pmc_irq_init(pmc);
        if (err < 0)
-               goto cleanup_restart_handler;
+               goto cleanup_powergates;
 
        mutex_lock(&pmc->powergates_lock);
        iounmap(pmc->base);
@@ -2026,10 +2114,15 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 
        return 0;
 
+cleanup_powergates:
+       tegra_powergate_remove_all(pdev->dev.of_node);
 cleanup_restart_handler:
        unregister_restart_handler(&tegra_pmc_restart_handler);
 cleanup_debugfs:
        debugfs_remove(pmc->debugfs);
+cleanup_sysfs:
+       device_remove_file(&pdev->dev, &dev_attr_reset_reason);
+       device_remove_file(&pdev->dev, &dev_attr_reset_level);
        return err;
 }
 
@@ -2185,7 +2278,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
        .init = tegra20_pmc_init,
        .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
        .reset_sources = tegra30_reset_sources,
-       .num_reset_sources = 5,
+       .num_reset_sources = ARRAY_SIZE(tegra30_reset_sources),
        .reset_levels = NULL,
        .num_reset_levels = 0,
 };
@@ -2236,7 +2329,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
        .init = tegra20_pmc_init,
        .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
        .reset_sources = tegra30_reset_sources,
-       .num_reset_sources = 5,
+       .num_reset_sources = ARRAY_SIZE(tegra30_reset_sources),
        .reset_levels = NULL,
        .num_reset_levels = 0,
 };
@@ -2347,7 +2440,7 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
        .init = tegra20_pmc_init,
        .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
        .reset_sources = tegra30_reset_sources,
-       .num_reset_sources = 5,
+       .num_reset_sources = ARRAY_SIZE(tegra30_reset_sources),
        .reset_levels = NULL,
        .num_reset_levels = 0,
 };
@@ -2452,8 +2545,8 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
        .regs = &tegra20_pmc_regs,
        .init = tegra20_pmc_init,
        .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
-       .reset_sources = tegra30_reset_sources,
-       .num_reset_sources = 5,
+       .reset_sources = tegra210_reset_sources,
+       .num_reset_sources = ARRAY_SIZE(tegra210_reset_sources),
        .reset_levels = NULL,
        .num_reset_levels = 0,
 };
@@ -2578,9 +2671,9 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
        .init = NULL,
        .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
        .reset_sources = tegra186_reset_sources,
-       .num_reset_sources = 14,
+       .num_reset_sources = ARRAY_SIZE(tegra186_reset_sources),
        .reset_levels = tegra186_reset_levels,
-       .num_reset_levels = 3,
+       .num_reset_levels = ARRAY_SIZE(tegra186_reset_levels),
        .num_wake_events = ARRAY_SIZE(tegra186_wake_events),
        .wake_events = tegra186_wake_events,
 };
@@ -2719,6 +2812,7 @@ static int __init tegra_pmc_early_init(void)
        const struct of_device_id *match;
        struct device_node *np;
        struct resource regs;
+       unsigned int i;
        bool invert;
 
        mutex_init(&pmc->powergates_lock);
@@ -2775,7 +2869,10 @@ static int __init tegra_pmc_early_init(void)
                if (pmc->soc->maybe_tz_only)
                        pmc->tz_only = tegra_pmc_detect_tz_only(pmc);
 
-               tegra_powergate_init(pmc, np);
+               /* Create a bitmap of the available and valid partitions */
+               for (i = 0; i < pmc->soc->num_powergates; i++)
+                       if (pmc->soc->powergates[i])
+                               set_bit(i, pmc->powergates_available);
 
                /*
                 * Invert the interrupt polarity if a PMC device tree node
index be4570b..57960e9 100644 (file)
@@ -45,11 +45,12 @@ config KEYSTONE_NAVIGATOR_DMA
 config AMX3_PM
        tristate "AMx3 Power Management"
        depends on SOC_AM33XX || SOC_AM43XX
-       depends on WKUP_M3_IPC && TI_EMIF_SRAM && SRAM
+       depends on WKUP_M3_IPC && TI_EMIF_SRAM && SRAM && RTC_DRV_OMAP
        help
          Enable power management on AM335x and AM437x. Required for suspend to mem
          and standby states on both AM335x and AM437x platforms and for deeper cpuidle
-         c-states on AM335x.
+         c-states on AM335x. Also required for rtc and ddr in self-refresh low
+         power mode on AM437x platforms.
 
 config WKUP_M3_IPC
        tristate "TI AMx3 Wkup-M3 IPC Driver"
index d0dab32..fc5802c 100644 (file)
@@ -6,6 +6,7 @@
  *     Vaibhav Bedia, Dave Gerlach
  */
 
+#include <linux/clk.h>
 #include <linux/cpu.h>
 #include <linux/err.h>
 #include <linux/genalloc.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/nvmem-consumer.h>
 #include <linux/of.h>
 #include <linux/platform_data/pm33xx.h>
 #include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/rtc/rtc-omap.h>
 #include <linux/sizes.h>
 #include <linux/sram.h>
 #include <linux/suspend.h>
 #define AMX3_PM_SRAM_SYMBOL_OFFSET(sym) ((unsigned long)(sym) - \
                                         (unsigned long)pm_sram->do_wfi)
 
+#define RTC_SCRATCH_RESUME_REG 0
+#define RTC_SCRATCH_MAGIC_REG  1
+#define RTC_REG_BOOT_MAGIC     0x8cd0 /* RTC */
+#define GIC_INT_SET_PENDING_BASE 0x200
+#define AM43XX_GIC_DIST_BASE   0x48241000
+
+static u32 rtc_magic_val;
+
 static int (*am33xx_do_wfi_sram)(unsigned long unused);
 static phys_addr_t am33xx_do_wfi_sram_phys;
 
 static struct gen_pool *sram_pool, *sram_pool_data;
 static unsigned long ocmcram_location, ocmcram_location_data;
 
+static struct rtc_device *omap_rtc;
+static void __iomem *gic_dist_base;
+
 static struct am33xx_pm_platform_data *pm_ops;
 static struct am33xx_pm_sram_addr *pm_sram;
 
 static struct device *pm33xx_dev;
 static struct wkup_m3_ipc *m3_ipc;
 
+#ifdef CONFIG_SUSPEND
+static int rtc_only_idle;
+static int retrigger_irq;
 static unsigned long suspend_wfi_flags;
 
+static struct wkup_m3_wakeup_src wakeup_src = {.irq_nr = 0,
+       .src = "Unknown",
+};
+
+static struct wkup_m3_wakeup_src rtc_alarm_wakeup = {
+       .irq_nr = 108, .src = "RTC Alarm",
+};
+
+static struct wkup_m3_wakeup_src rtc_ext_wakeup = {
+       .irq_nr = 0, .src = "Ext wakeup",
+};
+#endif
+
 static u32 sram_suspend_address(unsigned long addr)
 {
        return ((unsigned long)am33xx_do_wfi_sram +
                AMX3_PM_SRAM_SYMBOL_OFFSET(addr));
 }
 
+static int am33xx_push_sram_idle(void)
+{
+       struct am33xx_pm_ro_sram_data ro_sram_data;
+       int ret;
+       u32 table_addr, ro_data_addr;
+       void *copy_addr;
+
+       ro_sram_data.amx3_pm_sram_data_virt = ocmcram_location_data;
+       ro_sram_data.amx3_pm_sram_data_phys =
+               gen_pool_virt_to_phys(sram_pool_data, ocmcram_location_data);
+       ro_sram_data.rtc_base_virt = pm_ops->get_rtc_base_addr();
+
+       /* Save physical address to calculate resume offset during pm init */
+       am33xx_do_wfi_sram_phys = gen_pool_virt_to_phys(sram_pool,
+                                                       ocmcram_location);
+
+       am33xx_do_wfi_sram = sram_exec_copy(sram_pool, (void *)ocmcram_location,
+                                           pm_sram->do_wfi,
+                                           *pm_sram->do_wfi_sz);
+       if (!am33xx_do_wfi_sram) {
+               dev_err(pm33xx_dev,
+                       "PM: %s: am33xx_do_wfi copy to sram failed\n",
+                       __func__);
+               return -ENODEV;
+       }
+
+       table_addr =
+               sram_suspend_address((unsigned long)pm_sram->emif_sram_table);
+       ret = ti_emif_copy_pm_function_table(sram_pool, (void *)table_addr);
+       if (ret) {
+               dev_dbg(pm33xx_dev,
+                       "PM: %s: EMIF function copy failed\n", __func__);
+               return -EPROBE_DEFER;
+       }
+
+       ro_data_addr =
+               sram_suspend_address((unsigned long)pm_sram->ro_sram_data);
+       copy_addr = sram_exec_copy(sram_pool, (void *)ro_data_addr,
+                                  &ro_sram_data,
+                                  sizeof(ro_sram_data));
+       if (!copy_addr) {
+               dev_err(pm33xx_dev,
+                       "PM: %s: ro_sram_data copy to sram failed\n",
+                       __func__);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int __init am43xx_map_gic(void)
+{
+       gic_dist_base = ioremap(AM43XX_GIC_DIST_BASE, SZ_4K);
+
+       if (!gic_dist_base)
+               return -ENOMEM;
+
+       return 0;
+}
+
 #ifdef CONFIG_SUSPEND
+struct wkup_m3_wakeup_src rtc_wake_src(void)
+{
+       u32 i;
+
+       i = __raw_readl(pm_ops->get_rtc_base_addr() + 0x44) & 0x40;
+
+       if (i) {
+               retrigger_irq = rtc_alarm_wakeup.irq_nr;
+               return rtc_alarm_wakeup;
+       }
+
+       retrigger_irq = rtc_ext_wakeup.irq_nr;
+
+       return rtc_ext_wakeup;
+}
+
+int am33xx_rtc_only_idle(unsigned long wfi_flags)
+{
+       omap_rtc_power_off_program(&omap_rtc->dev);
+       am33xx_do_wfi_sram(wfi_flags);
+       return 0;
+}
+
 static int am33xx_pm_suspend(suspend_state_t suspend_state)
 {
        int i, ret = 0;
 
-       ret = pm_ops->soc_suspend((unsigned long)suspend_state,
-                                 am33xx_do_wfi_sram, suspend_wfi_flags);
+       if (suspend_state == PM_SUSPEND_MEM &&
+           pm_ops->check_off_mode_enable()) {
+               pm_ops->prepare_rtc_suspend();
+               pm_ops->save_context();
+               suspend_wfi_flags |= WFI_FLAG_RTC_ONLY;
+               clk_save_context();
+               ret = pm_ops->soc_suspend(suspend_state, am33xx_rtc_only_idle,
+                                         suspend_wfi_flags);
+
+               suspend_wfi_flags &= ~WFI_FLAG_RTC_ONLY;
+
+               if (!ret) {
+                       clk_restore_context();
+                       pm_ops->restore_context();
+                       m3_ipc->ops->set_rtc_only(m3_ipc);
+                       am33xx_push_sram_idle();
+               }
+       } else {
+               ret = pm_ops->soc_suspend(suspend_state, am33xx_do_wfi_sram,
+                                         suspend_wfi_flags);
+       }
 
        if (ret) {
                dev_err(pm33xx_dev, "PM: Kernel suspend failure\n");
@@ -77,8 +210,20 @@ static int am33xx_pm_suspend(suspend_state_t suspend_state)
                                "PM: CM3 returned unknown result = %d\n", i);
                        ret = -1;
                }
+
+               /* print the wakeup reason */
+               if (rtc_only_idle) {
+                       wakeup_src = rtc_wake_src();
+                       pr_info("PM: Wakeup source %s\n", wakeup_src.src);
+               } else {
+                       pr_info("PM: Wakeup source %s\n",
+                               m3_ipc->ops->request_wake_src(m3_ipc));
+               }
        }
 
+       if (suspend_state == PM_SUSPEND_MEM && pm_ops->check_off_mode_enable())
+               pm_ops->prepare_rtc_resume();
+
        return ret;
 }
 
@@ -101,6 +246,18 @@ static int am33xx_pm_enter(suspend_state_t suspend_state)
 static int am33xx_pm_begin(suspend_state_t state)
 {
        int ret = -EINVAL;
+       struct nvmem_device *nvmem;
+
+       if (state == PM_SUSPEND_MEM && pm_ops->check_off_mode_enable()) {
+               nvmem = devm_nvmem_device_get(&omap_rtc->dev,
+                                             "omap_rtc_scratch0");
+               if (nvmem)
+                       nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4, 4,
+                                          (void *)&rtc_magic_val);
+               rtc_only_idle = 1;
+       } else {
+               rtc_only_idle = 0;
+       }
 
        switch (state) {
        case PM_SUSPEND_MEM:
@@ -116,7 +273,28 @@ static int am33xx_pm_begin(suspend_state_t state)
 
 static void am33xx_pm_end(void)
 {
+       u32 val = 0;
+       struct nvmem_device *nvmem;
+
+       nvmem = devm_nvmem_device_get(&omap_rtc->dev, "omap_rtc_scratch0");
        m3_ipc->ops->finish_low_power(m3_ipc);
+       if (rtc_only_idle) {
+               if (retrigger_irq)
+                       /*
+                        * 32 bits of Interrupt Set-Pending correspond to 32
+                        * 32 interrupts. Compute the bit offset of the
+                        * Interrupt and set that particular bit
+                        * Compute the register offset by dividing interrupt
+                        * number by 32 and mutiplying by 4
+                        */
+                       writel_relaxed(1 << (retrigger_irq & 31),
+                                      gic_dist_base + GIC_INT_SET_PENDING_BASE
+                                      + retrigger_irq / 32 * 4);
+                       nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4, 4,
+                                          (void *)&val);
+       }
+
+       rtc_only_idle = 0;
 }
 
 static int am33xx_pm_valid(suspend_state_t state)
@@ -219,51 +397,37 @@ mpu_put_node:
        return ret;
 }
 
-static int am33xx_push_sram_idle(void)
+static int am33xx_pm_rtc_setup(void)
 {
-       struct am33xx_pm_ro_sram_data ro_sram_data;
-       int ret;
-       u32 table_addr, ro_data_addr;
-       void *copy_addr;
-
-       ro_sram_data.amx3_pm_sram_data_virt = ocmcram_location_data;
-       ro_sram_data.amx3_pm_sram_data_phys =
-               gen_pool_virt_to_phys(sram_pool_data, ocmcram_location_data);
-       ro_sram_data.rtc_base_virt = pm_ops->get_rtc_base_addr();
+       struct device_node *np;
+       unsigned long val = 0;
+       struct nvmem_device *nvmem;
 
-       /* Save physical address to calculate resume offset during pm init */
-       am33xx_do_wfi_sram_phys = gen_pool_virt_to_phys(sram_pool,
-                                                       ocmcram_location);
+       np = of_find_node_by_name(NULL, "rtc");
 
-       am33xx_do_wfi_sram = sram_exec_copy(sram_pool, (void *)ocmcram_location,
-                                           pm_sram->do_wfi,
-                                           *pm_sram->do_wfi_sz);
-       if (!am33xx_do_wfi_sram) {
-               dev_err(pm33xx_dev,
-                       "PM: %s: am33xx_do_wfi copy to sram failed\n",
-                       __func__);
-               return -ENODEV;
-       }
-
-       table_addr =
-               sram_suspend_address((unsigned long)pm_sram->emif_sram_table);
-       ret = ti_emif_copy_pm_function_table(sram_pool, (void *)table_addr);
-       if (ret) {
-               dev_dbg(pm33xx_dev,
-                       "PM: %s: EMIF function copy failed\n", __func__);
-               return -EPROBE_DEFER;
-       }
+       if (of_device_is_available(np)) {
+               omap_rtc = rtc_class_open("rtc0");
+               if (!omap_rtc) {
+                       pr_warn("PM: rtc0 not available");
+                       return -EPROBE_DEFER;
+               }
 
-       ro_data_addr =
-               sram_suspend_address((unsigned long)pm_sram->ro_sram_data);
-       copy_addr = sram_exec_copy(sram_pool, (void *)ro_data_addr,
-                                  &ro_sram_data,
-                                  sizeof(ro_sram_data));
-       if (!copy_addr) {
-               dev_err(pm33xx_dev,
-                       "PM: %s: ro_sram_data copy to sram failed\n",
-                       __func__);
-               return -ENODEV;
+               nvmem = devm_nvmem_device_get(&omap_rtc->dev,
+                                             "omap_rtc_scratch0");
+               if (nvmem) {
+                       nvmem_device_read(nvmem, RTC_SCRATCH_MAGIC_REG * 4,
+                                         4, (void *)&rtc_magic_val);
+                       if ((rtc_magic_val & 0xffff) != RTC_REG_BOOT_MAGIC)
+                               pr_warn("PM: bootloader does not support rtc-only!\n");
+
+                       nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4,
+                                          4, (void *)&val);
+                       val = pm_sram->resume_address;
+                       nvmem_device_write(nvmem, RTC_SCRATCH_RESUME_REG * 4,
+                                          4, (void *)&val);
+               }
+       } else {
+               pr_warn("PM: no-rtc available, rtc-only mode disabled.\n");
        }
 
        return 0;
@@ -284,34 +448,42 @@ static int am33xx_pm_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       ret = am43xx_map_gic();
+       if (ret) {
+               pr_err("PM: Could not ioremap GIC base\n");
+               return ret;
+       }
+
        pm_sram = pm_ops->get_sram_addrs();
        if (!pm_sram) {
                dev_err(dev, "PM: Cannot get PM asm function addresses!!\n");
                return -ENODEV;
        }
 
+       m3_ipc = wkup_m3_ipc_get();
+       if (!m3_ipc) {
+               pr_err("PM: Cannot get wkup_m3_ipc handle\n");
+               return -EPROBE_DEFER;
+       }
+
        pm33xx_dev = dev;
 
        ret = am33xx_pm_alloc_sram();
        if (ret)
                return ret;
 
-       ret = am33xx_push_sram_idle();
+       ret = am33xx_pm_rtc_setup();
        if (ret)
                goto err_free_sram;
 
-       m3_ipc = wkup_m3_ipc_get();
-       if (!m3_ipc) {
-               dev_dbg(dev, "PM: Cannot get wkup_m3_ipc handle\n");
-               ret = -EPROBE_DEFER;
+       ret = am33xx_push_sram_idle();
+       if (ret)
                goto err_free_sram;
-       }
 
        am33xx_pm_set_ipc_ops();
 
 #ifdef CONFIG_SUSPEND
        suspend_set_ops(&am33xx_pm_ops);
-#endif /* CONFIG_SUSPEND */
 
        /*
         * For a system suspend we must flush the caches, we want
@@ -323,6 +495,7 @@ static int am33xx_pm_probe(struct platform_device *pdev)
        suspend_wfi_flags |= WFI_FLAG_SELF_REFRESH;
        suspend_wfi_flags |= WFI_FLAG_SAVE_EMIF;
        suspend_wfi_flags |= WFI_FLAG_WAKE_M3;
+#endif /* CONFIG_SUSPEND */
 
        ret = pm_ops->init();
        if (ret) {
index 354d256..600f57c 100644 (file)
@@ -23,6 +23,8 @@
 /* Flag stating if PM nodes mapped to the PM domain has been requested */
 #define ZYNQMP_PM_DOMAIN_REQUESTED     BIT(0)
 
+static const struct zynqmp_eemi_ops *eemi_ops;
+
 /**
  * struct zynqmp_pm_domain - Wrapper around struct generic_pm_domain
  * @gpd:               Generic power domain
@@ -71,9 +73,8 @@ static int zynqmp_gpd_power_on(struct generic_pm_domain *domain)
 {
        int ret;
        struct zynqmp_pm_domain *pd;
-       const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-       if (!eemi_ops || !eemi_ops->set_requirement)
+       if (!eemi_ops->set_requirement)
                return -ENXIO;
 
        pd = container_of(domain, struct zynqmp_pm_domain, gpd);
@@ -107,9 +108,8 @@ static int zynqmp_gpd_power_off(struct generic_pm_domain *domain)
        struct zynqmp_pm_domain *pd;
        u32 capabilities = 0;
        bool may_wakeup;
-       const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-       if (!eemi_ops || !eemi_ops->set_requirement)
+       if (!eemi_ops->set_requirement)
                return -ENXIO;
 
        pd = container_of(domain, struct zynqmp_pm_domain, gpd);
@@ -160,9 +160,8 @@ static int zynqmp_gpd_attach_dev(struct generic_pm_domain *domain,
 {
        int ret;
        struct zynqmp_pm_domain *pd;
-       const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-       if (!eemi_ops || !eemi_ops->request_node)
+       if (!eemi_ops->request_node)
                return -ENXIO;
 
        pd = container_of(domain, struct zynqmp_pm_domain, gpd);
@@ -197,9 +196,8 @@ static void zynqmp_gpd_detach_dev(struct generic_pm_domain *domain,
 {
        int ret;
        struct zynqmp_pm_domain *pd;
-       const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-       if (!eemi_ops || !eemi_ops->release_node)
+       if (!eemi_ops->release_node)
                return;
 
        pd = container_of(domain, struct zynqmp_pm_domain, gpd);
@@ -266,6 +264,10 @@ static int zynqmp_gpd_probe(struct platform_device *pdev)
        struct zynqmp_pm_domain *pd;
        struct device *dev = &pdev->dev;
 
+       eemi_ops = zynqmp_pm_get_eemi_ops();
+       if (IS_ERR(eemi_ops))
+               return PTR_ERR(eemi_ops);
+
        pd = devm_kcalloc(dev, ZYNQMP_NUM_DOMAINS, sizeof(*pd), GFP_KERNEL);
        if (!pd)
                return -ENOMEM;
index 771cb59..1b9d144 100644 (file)
@@ -31,6 +31,7 @@ static const char *const suspend_modes[] = {
 };
 
 static enum pm_suspend_mode suspend_mode = PM_SUSPEND_MODE_STD;
+static const struct zynqmp_eemi_ops *eemi_ops;
 
 enum pm_api_cb_id {
        PM_INIT_SUSPEND_CB = 30,
@@ -92,9 +93,8 @@ static ssize_t suspend_mode_store(struct device *dev,
                                  const char *buf, size_t count)
 {
        int md, ret = -EINVAL;
-       const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-       if (!eemi_ops || !eemi_ops->set_suspend_mode)
+       if (!eemi_ops->set_suspend_mode)
                return ret;
 
        for (md = PM_SUSPEND_MODE_FIRST; md < ARRAY_SIZE(suspend_modes); md++)
@@ -120,9 +120,11 @@ static int zynqmp_pm_probe(struct platform_device *pdev)
        int ret, irq;
        u32 pm_api_version;
 
-       const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+       eemi_ops = zynqmp_pm_get_eemi_ops();
+       if (IS_ERR(eemi_ops))
+               return PTR_ERR(eemi_ops);
 
-       if (!eemi_ops || !eemi_ops->get_api_version || !eemi_ops->init_finalize)
+       if (!eemi_ops->get_api_version || !eemi_ops->init_finalize)
                return -ENXIO;
 
        eemi_ops->init_finalize();
index 3912526..cdb613d 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/clk.h>
 #include <linux/dmaengine.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/pinctrl/consumer.h>
index 9f83e1b..9850a0e 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
+#include <linux/firmware/xlnx-zynqmp.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
 
 #define SPI_AUTOSUSPEND_TIMEOUT                3000
 enum mode_type {GQSPI_MODE_IO, GQSPI_MODE_DMA};
+static const struct zynqmp_eemi_ops *eemi_ops;
 
 /**
  * struct zynqmp_qspi - Defines qspi driver instance
@@ -1021,6 +1023,10 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
        struct resource *res;
        struct device *dev = &pdev->dev;
 
+       eemi_ops = zynqmp_pm_get_eemi_ops();
+       if (IS_ERR(eemi_ops))
+               return PTR_ERR(eemi_ops);
+
        master = spi_alloc_master(&pdev->dev, sizeof(*xqspi));
        if (!master)
                return -ENOMEM;
index 600928f..d35c4fb 100644 (file)
@@ -486,8 +486,8 @@ static int gasket_perform_mapping(struct gasket_page_table *pg_tbl,
                        ptes[i].dma_addr = pg_tbl->coherent_pages[0].paddr +
                                           off + i * PAGE_SIZE;
                } else {
-                       ret = get_user_pages_fast(page_addr - offset, 1, 1,
-                                                 &page);
+                       ret = get_user_pages_fast(page_addr - offset, 1,
+                                                 FOLL_WRITE, &page);
 
                        if (ret <= 0) {
                                dev_err(pg_tbl->device,
index 1ba4a51..64037b0 100644 (file)
@@ -1266,7 +1266,7 @@ static int prp_registered(struct v4l2_subdev *sd)
        if (ret)
                return ret;
 
-       ret = imx_media_capture_device_register(priv->vdev);
+       ret = imx_media_capture_device_register(priv->md, priv->vdev);
        if (ret)
                return ret;
 
index b7ce9d4..9430c83 100644 (file)
@@ -701,7 +701,8 @@ void imx_media_capture_device_error(struct imx_media_video_dev *vdev)
 }
 EXPORT_SYMBOL_GPL(imx_media_capture_device_error);
 
-int imx_media_capture_device_register(struct imx_media_video_dev *vdev)
+int imx_media_capture_device_register(struct imx_media_dev *md,
+                                     struct imx_media_video_dev *vdev)
 {
        struct capture_priv *priv = to_capture_priv(vdev);
        struct v4l2_subdev *sd = priv->src_sd;
@@ -710,8 +711,7 @@ int imx_media_capture_device_register(struct imx_media_video_dev *vdev)
        struct v4l2_subdev_format fmt_src;
        int ret;
 
-       /* get media device */
-       priv->md = dev_get_drvdata(sd->v4l2_dev->dev);
+       priv->md = md;
 
        vfd->v4l2_dev = sd->v4l2_dev;
 
index 28fe660..1d248ac 100644 (file)
@@ -1812,7 +1812,7 @@ static int csi_registered(struct v4l2_subdev *sd)
        if (ret)
                goto free_fim;
 
-       ret = imx_media_capture_device_register(priv->vdev);
+       ret = imx_media_capture_device_register(priv->md, priv->vdev);
        if (ret)
                goto free_fim;
 
index eb59ba0..6587aa4 100644 (file)
@@ -268,7 +268,8 @@ int imx_media_of_add_csi(struct imx_media_dev *imxmd,
 struct imx_media_video_dev *
 imx_media_capture_device_init(struct v4l2_subdev *src_sd, int pad);
 void imx_media_capture_device_remove(struct imx_media_video_dev *vdev);
-int imx_media_capture_device_register(struct imx_media_video_dev *vdev);
+int imx_media_capture_device_register(struct imx_media_dev *md,
+                                     struct imx_media_video_dev *vdev);
 void imx_media_capture_device_unregister(struct imx_media_video_dev *vdev);
 struct imx_media_buffer *
 imx_media_capture_device_next_buf(struct imx_media_video_dev *vdev);
index 18eb5d3..a708a03 100644 (file)
@@ -1126,7 +1126,7 @@ static int imx7_csi_registered(struct v4l2_subdev *sd)
        if (ret < 0)
                return ret;
 
-       ret = imx_media_capture_device_register(csi->vdev);
+       ret = imx_media_capture_device_register(csi->imxmd, csi->vdev);
        if (ret < 0)
                return ret;
 
index 58721c4..8bbc905 100644 (file)
@@ -352,7 +352,7 @@ static int rockchip_vpu_video_device_register(struct rockchip_vpu_dev *vpu)
        vpu->vfd_enc = vfd;
        video_set_drvdata(vfd, vpu);
 
-       ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
+       ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
        if (ret) {
                v4l2_err(&vpu->v4l2_dev, "Failed to register video device\n");
                goto err_free_dev;
@@ -463,6 +463,8 @@ static int rockchip_vpu_probe(struct platform_device *pdev)
 
        vpu->mdev.dev = vpu->dev;
        strscpy(vpu->mdev.model, DRIVER_NAME, sizeof(vpu->mdev.model));
+       strscpy(vpu->mdev.bus_info, "platform: " DRIVER_NAME,
+               sizeof(vpu->mdev.model));
        media_device_init(&vpu->mdev);
        vpu->v4l2_dev.mdev = &vpu->mdev;
 
@@ -480,15 +482,18 @@ static int rockchip_vpu_probe(struct platform_device *pdev)
        return 0;
 err_video_dev_unreg:
        if (vpu->vfd_enc) {
+               v4l2_m2m_unregister_media_controller(vpu->m2m_dev);
                video_unregister_device(vpu->vfd_enc);
                video_device_release(vpu->vfd_enc);
        }
 err_m2m_rel:
+       media_device_cleanup(&vpu->mdev);
        v4l2_m2m_release(vpu->m2m_dev);
 err_v4l2_unreg:
        v4l2_device_unregister(&vpu->v4l2_dev);
 err_clk_unprepare:
        clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks);
+       pm_runtime_dont_use_autosuspend(vpu->dev);
        pm_runtime_disable(vpu->dev);
        return ret;
 }
@@ -500,15 +505,16 @@ static int rockchip_vpu_remove(struct platform_device *pdev)
        v4l2_info(&vpu->v4l2_dev, "Removing %s\n", pdev->name);
 
        media_device_unregister(&vpu->mdev);
-       v4l2_m2m_unregister_media_controller(vpu->m2m_dev);
-       v4l2_m2m_release(vpu->m2m_dev);
-       media_device_cleanup(&vpu->mdev);
        if (vpu->vfd_enc) {
+               v4l2_m2m_unregister_media_controller(vpu->m2m_dev);
                video_unregister_device(vpu->vfd_enc);
                video_device_release(vpu->vfd_enc);
        }
+       media_device_cleanup(&vpu->mdev);
+       v4l2_m2m_release(vpu->m2m_dev);
        v4l2_device_unregister(&vpu->v4l2_dev);
        clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks);
+       pm_runtime_dont_use_autosuspend(vpu->dev);
        pm_runtime_disable(vpu->dev);
        return 0;
 }
index fb5e36a..dcbfc3c 100644 (file)
@@ -152,9 +152,10 @@ static int vidioc_querycap(struct file *file, void *priv,
                           struct v4l2_capability *cap)
 {
        struct rockchip_vpu_dev *vpu = video_drvdata(file);
+       struct video_device *vdev = video_devdata(file);
 
        strscpy(cap->driver, vpu->dev->driver->name, sizeof(cap->driver));
-       strscpy(cap->card, vpu->vfd_enc->name, sizeof(cap->card));
+       strscpy(cap->card, vdev->name, sizeof(cap->card));
        snprintf(cap->bus_info, sizeof(cap->bus_info), "platform: %s",
                 vpu->dev->driver->name);
        return 0;
index 255e266..f5c716b 100644 (file)
@@ -3,7 +3,6 @@ config FB_OLPC_DCON
        tristate "One Laptop Per Child Display CONtroller support"
        depends on OLPC && FB
        depends on I2C
-       depends on BACKLIGHT_LCD_SUPPORT
        depends on (GPIO_CS5535 || GPIO_CS5535=n)
        select BACKLIGHT_CLASS_DEVICE
        help
index 0842b6e..48963ea 100644 (file)
@@ -419,9 +419,35 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn,
        return true;
 }
 
+static struct tee_shm_pool *optee_config_dyn_shm(void)
+{
+       struct tee_shm_pool_mgr *priv_mgr;
+       struct tee_shm_pool_mgr *dmabuf_mgr;
+       void *rc;
+
+       rc = optee_shm_pool_alloc_pages();
+       if (IS_ERR(rc))
+               return rc;
+       priv_mgr = rc;
+
+       rc = optee_shm_pool_alloc_pages();
+       if (IS_ERR(rc)) {
+               tee_shm_pool_mgr_destroy(priv_mgr);
+               return rc;
+       }
+       dmabuf_mgr = rc;
+
+       rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
+       if (IS_ERR(rc)) {
+               tee_shm_pool_mgr_destroy(priv_mgr);
+               tee_shm_pool_mgr_destroy(dmabuf_mgr);
+       }
+
+       return rc;
+}
+
 static struct tee_shm_pool *
-optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm,
-                         u32 sec_caps)
+optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm)
 {
        union {
                struct arm_smccc_res smccc;
@@ -436,10 +462,11 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm,
        struct tee_shm_pool_mgr *priv_mgr;
        struct tee_shm_pool_mgr *dmabuf_mgr;
        void *rc;
+       const int sz = OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
 
        invoke_fn(OPTEE_SMC_GET_SHM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
        if (res.result.status != OPTEE_SMC_RETURN_OK) {
-               pr_info("shm service not available\n");
+               pr_err("static shm service not available\n");
                return ERR_PTR(-ENOENT);
        }
 
@@ -465,28 +492,15 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm,
        }
        vaddr = (unsigned long)va;
 
-       /*
-        * If OP-TEE can work with unregistered SHM, we will use own pool
-        * for private shm
-        */
-       if (sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) {
-               rc = optee_shm_pool_alloc_pages();
-               if (IS_ERR(rc))
-                       goto err_memunmap;
-               priv_mgr = rc;
-       } else {
-               const size_t sz = OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
-
-               rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, sz,
-                                                   3 /* 8 bytes aligned */);
-               if (IS_ERR(rc))
-                       goto err_memunmap;
-               priv_mgr = rc;
-
-               vaddr += sz;
-               paddr += sz;
-               size -= sz;
-       }
+       rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, sz,
+                                           3 /* 8 bytes aligned */);
+       if (IS_ERR(rc))
+               goto err_memunmap;
+       priv_mgr = rc;
+
+       vaddr += sz;
+       paddr += sz;
+       size -= sz;
 
        rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, size, PAGE_SHIFT);
        if (IS_ERR(rc))
@@ -552,7 +566,7 @@ static optee_invoke_fn *get_invoke_func(struct device_node *np)
 static struct optee *optee_probe(struct device_node *np)
 {
        optee_invoke_fn *invoke_fn;
-       struct tee_shm_pool *pool;
+       struct tee_shm_pool *pool = ERR_PTR(-EINVAL);
        struct optee *optee = NULL;
        void *memremaped_shm = NULL;
        struct tee_device *teedev;
@@ -581,13 +595,17 @@ static struct optee *optee_probe(struct device_node *np)
        }
 
        /*
-        * We have no other option for shared memory, if secure world
-        * doesn't have any reserved memory we can use we can't continue.
+        * Try to use dynamic shared memory if possible
         */
-       if (!(sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM))
-               return ERR_PTR(-EINVAL);
+       if (sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)
+               pool = optee_config_dyn_shm();
+
+       /*
+        * If dynamic shared memory is not available or failed - try static one
+        */
+       if (IS_ERR(pool) && (sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM))
+               pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm);
 
-       pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm, sec_caps);
        if (IS_ERR(pool))
                return (void *)pool;
 
index 0b9ab1d..49fd731 100644 (file)
@@ -273,7 +273,7 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
                goto err;
        }
 
-       rc = get_user_pages_fast(start, num_pages, 1, shm->pages);
+       rc = get_user_pages_fast(start, num_pages, FOLL_WRITE, shm->pages);
        if (rc > 0)
                shm->num_pages = rc;
        if (rc != num_pages) {
index 653aa27..15bdd25 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 menuconfig THERMAL
-       tristate "Generic Thermal sysfs driver"
+       bool "Generic Thermal sysfs driver"
        help
          Generic Thermal Sysfs driver offers a generic mechanism for
          thermal management. Usually it's made up of one or more thermal
@@ -11,7 +11,7 @@ menuconfig THERMAL
          Each thermal zone contains its own temperature, trip points,
          cooling devices.
          All platforms with ACPI thermal support can use this driver.
-         If you want this support, you should say Y or M here.
+         If you want this support, you should say Y here.
 
 if THERMAL
 
@@ -24,7 +24,6 @@ config THERMAL_STATISTICS
 
 config THERMAL_EMERGENCY_POWEROFF_DELAY_MS
        int "Emergency poweroff delay in milli-seconds"
-       depends on THERMAL
        default 0
        help
          Thermal subsystem will issue a graceful shutdown when
@@ -149,10 +148,9 @@ config THERMAL_GOV_POWER_ALLOCATOR
          allocating and limiting power to devices.
 
 config CPU_THERMAL
-       bool "generic cpu cooling support"
+       bool "Generic cpu cooling support"
        depends on CPU_FREQ
        depends on THERMAL_OF
-       depends on THERMAL=y
        help
          This implements the generic cpu cooling mechanism through frequency
          reduction. An ACPI version of this already exists
@@ -200,6 +198,17 @@ config THERMAL_EMULATION
          because userland can easily disable the thermal policy by simply
          flooding this sysfs node with low temperature values.
 
+config THERMAL_MMIO
+       tristate "Generic Thermal MMIO driver"
+       depends on OF || COMPILE_TEST
+       depends on HAS_IOMEM
+       help
+         This option enables the generic thermal MMIO driver that will use
+         memory-mapped reads to get the temperature.  Any HW/System that
+         allows temperature reading by a single memory-mapped reading, be it
+         register or shared memory, is a potential candidate to work with this
+         driver.
+
 config HISI_THERMAL
        tristate "Hisilicon thermal driver"
        depends on ARCH_HISI || COMPILE_TEST
index 486d682..74a37c7 100644 (file)
@@ -29,6 +29,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
 
 # platform thermal drivers
 obj-y                          += broadcom/
+obj-$(CONFIG_THERMAL_MMIO)             += thermal_mmio.o
 obj-$(CONFIG_SPEAR_THERMAL)    += spear_thermal.o
 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
 obj-$(CONFIG_RCAR_THERMAL)     += rcar_thermal.o
index 2284cbe..475ce29 100644 (file)
@@ -3,7 +3,6 @@
  * Copyright (C) 2018 Broadcom
  */
 
-#include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
@@ -100,18 +99,11 @@ static const struct of_device_id sr_thermal_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, sr_thermal_of_match);
 
-static const struct acpi_device_id sr_thermal_acpi_ids[] = {
-       { .id = "BRCM0500" },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(acpi, sr_thermal_acpi_ids);
-
 static struct platform_driver sr_thermal_driver = {
        .probe          = sr_thermal_probe,
        .driver = {
                .name = "sr-thermal",
                .of_match_table = sr_thermal_of_match,
-               .acpi_match_table = ACPI_PTR(sr_thermal_acpi_ids),
        },
 };
 module_platform_driver(sr_thermal_driver);
index f7c1f49..4c5db59 100644 (file)
@@ -1,26 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  *  linux/drivers/thermal/cpu_cooling.c
  *
  *  Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com)
- *  Copyright (C) 2012  Amit Daniel <amit.kachhap@linaro.org>
  *
- *  Copyright (C) 2014  Viresh Kumar <viresh.kumar@linaro.org>
+ *  Copyright (C) 2012-2018 Linaro Limited.
  *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
+ *  Authors:   Amit Daniel <amit.kachhap@linaro.org>
+ *             Viresh Kumar <viresh.kumar@linaro.org>
  *
- *  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/module.h>
 #include <linux/thermal.h>
@@ -99,7 +87,6 @@ struct cpufreq_cooling_device {
        unsigned int clipped_freq;
        unsigned int max_level;
        struct freq_table *freq_table;  /* In descending order */
-       struct thermal_cooling_device *cdev;
        struct cpufreq_policy *policy;
        struct list_head node;
        struct time_in_idle *idle_time;
@@ -207,8 +194,7 @@ static int update_freq_table(struct cpufreq_cooling_device *cpufreq_cdev,
 
        dev = get_cpu_device(cpu);
        if (unlikely(!dev)) {
-               dev_warn(&cpufreq_cdev->cdev->device,
-                        "No cpu device for cpu %d\n", cpu);
+               pr_warn("No cpu device for cpu %d\n", cpu);
                return -ENODEV;
        }
 
@@ -458,7 +444,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
                        load = 0;
 
                total_load += load;
-               if (trace_thermal_power_cpu_limit_enabled() && load_cpu)
+               if (load_cpu)
                        load_cpu[i] = load;
 
                i++;
@@ -541,7 +527,6 @@ static int cpufreq_power2state(struct thermal_cooling_device *cdev,
        struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
        struct cpufreq_policy *policy = cpufreq_cdev->policy;
 
-       power = power > 0 ? power : 0;
        last_load = cpufreq_cdev->last_load ?: 1;
        normalised_power = (power * 100) / last_load;
        target_freq = cpu_power_to_freq(cpufreq_cdev, normalised_power);
@@ -692,7 +677,6 @@ __cpufreq_cooling_register(struct device_node *np,
                goto remove_ida;
 
        cpufreq_cdev->clipped_freq = cpufreq_cdev->freq_table[0].frequency;
-       cpufreq_cdev->cdev = cdev;
 
        mutex_lock(&cooling_list_lock);
        /* Register the notifier for first cpufreq cooling device */
@@ -810,7 +794,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
                cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block,
                                            CPUFREQ_POLICY_NOTIFIER);
 
-       thermal_cooling_device_unregister(cpufreq_cdev->cdev);
+       thermal_cooling_device_unregister(cdev);
        ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id);
        kfree(cpufreq_cdev->idle_time);
        kfree(cpufreq_cdev->freq_table);
index 2e013ee..2c727a8 100644 (file)
@@ -1,6 +1,5 @@
 config INTEL_POWERCLAMP
        tristate "Intel PowerClamp idle injection driver"
-       depends on THERMAL
        depends on X86
        depends on CPU_SUP_INTEL
        help
index 0c19fcd..79a7df2 100644 (file)
@@ -220,6 +220,7 @@ static int int3403_add(struct platform_device *pdev)
 {
        struct int3403_priv *priv;
        int result = 0;
+       unsigned long long tmp;
        acpi_status status;
 
        priv = devm_kzalloc(&pdev->dev, sizeof(struct int3403_priv),
@@ -234,19 +235,18 @@ static int int3403_add(struct platform_device *pdev)
                goto err;
        }
 
-       status = acpi_evaluate_integer(priv->adev->handle, "PTYP",
-                                      NULL, &priv->type);
-       if (ACPI_FAILURE(status)) {
-               unsigned long long tmp;
 
-               status = acpi_evaluate_integer(priv->adev->handle, "_TMP",
-                                              NULL, &tmp);
+       status = acpi_evaluate_integer(priv->adev->handle, "_TMP",
+                                      NULL, &tmp);
+       if (ACPI_FAILURE(status)) {
+               status = acpi_evaluate_integer(priv->adev->handle, "PTYP",
+                                      NULL, &priv->type);
                if (ACPI_FAILURE(status)) {
                        result = -EINVAL;
                        goto err;
-               } else {
-                       priv->type = INT3403_TYPE_SENSOR;
                }
+       } else {
+               priv->type = INT3403_TYPE_SENSOR;
        }
 
        platform_set_drvdata(pdev, priv);
index 8e1cf4d..2e6071a 100644 (file)
@@ -81,22 +81,13 @@ static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \
                                        struct device_attribute *attr, \
                                        char *buf) \
 { \
-       struct pci_dev *pci_dev; \
-       struct platform_device *pdev; \
-       struct proc_thermal_device *proc_dev; \
+       struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); \
        \
        if (proc_thermal_emum_mode == PROC_THERMAL_NONE) { \
                dev_warn(dev, "Attempted to get power limit before device was initialized!\n"); \
                return 0; \
        } \
        \
-       if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) { \
-               pdev = to_platform_device(dev); \
-               proc_dev = platform_get_drvdata(pdev); \
-       } else { \
-               pci_dev = to_pci_dev(dev); \
-               proc_dev = pci_get_drvdata(pci_dev); \
-       } \
        return sprintf(buf, "%lu\n",\
        (unsigned long)proc_dev->power_limits[index].suffix * 1000); \
 }
@@ -274,7 +265,7 @@ static void proc_thermal_notify(acpi_handle handle, u32 event, void *data)
                                THERMAL_DEVICE_POWER_CAPABILITY_CHANGED);
                break;
        default:
-               dev_err(proc_priv->dev, "Unsupported event [0x%x]\n", event);
+               dev_dbg(proc_priv->dev, "Unsupported event [0x%x]\n", event);
                break;
        }
 }
index 2df059c..dc5093b 100644 (file)
@@ -5,6 +5,9 @@
  *  Copyright (C) 2013 Texas Instruments
  *  Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/thermal.h>
 #include <linux/slab.h>
 #include <linux/types.h>
index cdb455f..3ce20fe 100644 (file)
@@ -1,6 +1,5 @@
 config QCOM_TSENS
        tristate "Qualcomm TSENS Temperature Alarm"
-       depends on THERMAL
        depends on QCOM_QFPROM
        depends on ARCH_QCOM || COMPILE_TEST
        help
index 717a086..fc6fe50 100644 (file)
@@ -1,3 +1,5 @@
 obj-$(CONFIG_QCOM_TSENS)       += qcom_tsens.o
-qcom_tsens-y                   += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-v2.o
+
+qcom_tsens-y                   += tsens.o tsens-common.o tsens-v0_1.o \
+                                  tsens-8960.o tsens-v2.o tsens-v1.o
 obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM)     += qcom-spmi-temp-alarm.o
diff --git a/drivers/thermal/qcom/tsens-8916.c b/drivers/thermal/qcom/tsens-8916.c
deleted file mode 100644 (file)
index c6dd620..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
- */
-
-#include <linux/platform_device.h>
-#include "tsens.h"
-
-/* eeprom layout data for 8916 */
-#define BASE0_MASK     0x0000007f
-#define BASE1_MASK     0xfe000000
-#define BASE0_SHIFT    0
-#define BASE1_SHIFT    25
-
-#define S0_P1_MASK     0x00000f80
-#define S1_P1_MASK     0x003e0000
-#define S2_P1_MASK     0xf8000000
-#define S3_P1_MASK     0x000003e0
-#define S4_P1_MASK     0x000f8000
-
-#define S0_P2_MASK     0x0001f000
-#define S1_P2_MASK     0x07c00000
-#define S2_P2_MASK     0x0000001f
-#define S3_P2_MASK     0x00007c00
-#define S4_P2_MASK     0x01f00000
-
-#define S0_P1_SHIFT    7
-#define S1_P1_SHIFT    17
-#define S2_P1_SHIFT    27
-#define S3_P1_SHIFT    5
-#define S4_P1_SHIFT    15
-
-#define S0_P2_SHIFT    12
-#define S1_P2_SHIFT    22
-#define S2_P2_SHIFT    0
-#define S3_P2_SHIFT    10
-#define S4_P2_SHIFT    20
-
-#define CAL_SEL_MASK   0xe0000000
-#define CAL_SEL_SHIFT  29
-
-static int calibrate_8916(struct tsens_device *tmdev)
-{
-       int base0 = 0, base1 = 0, i;
-       u32 p1[5], p2[5];
-       int mode = 0;
-       u32 *qfprom_cdata, *qfprom_csel;
-
-       qfprom_cdata = (u32 *)qfprom_read(tmdev->dev, "calib");
-       if (IS_ERR(qfprom_cdata))
-               return PTR_ERR(qfprom_cdata);
-
-       qfprom_csel = (u32 *)qfprom_read(tmdev->dev, "calib_sel");
-       if (IS_ERR(qfprom_csel))
-               return PTR_ERR(qfprom_csel);
-
-       mode = (qfprom_csel[0] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
-       dev_dbg(tmdev->dev, "calibration mode is %d\n", mode);
-
-       switch (mode) {
-       case TWO_PT_CALIB:
-               base1 = (qfprom_cdata[1] & BASE1_MASK) >> BASE1_SHIFT;
-               p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
-               p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
-               p2[2] = (qfprom_cdata[1] & S2_P2_MASK) >> S2_P2_SHIFT;
-               p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
-               p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
-               for (i = 0; i < tmdev->num_sensors; i++)
-                       p2[i] = ((base1 + p2[i]) << 3);
-               /* Fall through */
-       case ONE_PT_CALIB2:
-               base0 = (qfprom_cdata[0] & BASE0_MASK);
-               p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
-               p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
-               p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
-               p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
-               p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
-               for (i = 0; i < tmdev->num_sensors; i++)
-                       p1[i] = (((base0) + p1[i]) << 3);
-               break;
-       default:
-               for (i = 0; i < tmdev->num_sensors; i++) {
-                       p1[i] = 500;
-                       p2[i] = 780;
-               }
-               break;
-       }
-
-       compute_intercept_slope(tmdev, p1, p2, mode);
-
-       return 0;
-}
-
-static const struct tsens_ops ops_8916 = {
-       .init           = init_common,
-       .calibrate      = calibrate_8916,
-       .get_temp       = get_temp_common,
-};
-
-const struct tsens_data data_8916 = {
-       .num_sensors    = 5,
-       .ops            = &ops_8916,
-       .reg_offsets    = { [SROT_CTRL_OFFSET] = 0x0 },
-       .hw_ids         = (unsigned int []){0, 1, 2, 4, 5 },
-};
index 0f0adb3..8d9b721 100644 (file)
 #define TRDY_MASK              BIT(7)
 #define TIMEOUT_US             100
 
-static int suspend_8960(struct tsens_device *tmdev)
+static int suspend_8960(struct tsens_priv *priv)
 {
        int ret;
        unsigned int mask;
-       struct regmap *map = tmdev->tm_map;
+       struct regmap *map = priv->tm_map;
 
-       ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold);
+       ret = regmap_read(map, THRESHOLD_ADDR, &priv->ctx.threshold);
        if (ret)
                return ret;
 
-       ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control);
+       ret = regmap_read(map, CNTL_ADDR, &priv->ctx.control);
        if (ret)
                return ret;
 
-       if (tmdev->num_sensors > 1)
+       if (priv->num_sensors > 1)
                mask = SLP_CLK_ENA | EN;
        else
                mask = SLP_CLK_ENA_8660 | EN;
@@ -82,10 +82,10 @@ static int suspend_8960(struct tsens_device *tmdev)
        return 0;
 }
 
-static int resume_8960(struct tsens_device *tmdev)
+static int resume_8960(struct tsens_priv *priv)
 {
        int ret;
-       struct regmap *map = tmdev->tm_map;
+       struct regmap *map = priv->tm_map;
 
        ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
        if (ret)
@@ -95,80 +95,80 @@ static int resume_8960(struct tsens_device *tmdev)
         * Separate CONFIG restore is not needed only for 8660 as
         * config is part of CTRL Addr and its restored as such
         */
-       if (tmdev->num_sensors > 1) {
+       if (priv->num_sensors > 1) {
                ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
                if (ret)
                        return ret;
        }
 
-       ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold);
+       ret = regmap_write(map, THRESHOLD_ADDR, priv->ctx.threshold);
        if (ret)
                return ret;
 
-       ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control);
+       ret = regmap_write(map, CNTL_ADDR, priv->ctx.control);
        if (ret)
                return ret;
 
        return 0;
 }
 
-static int enable_8960(struct tsens_device *tmdev, int id)
+static int enable_8960(struct tsens_priv *priv, int id)
 {
        int ret;
        u32 reg, mask;
 
-       ret = regmap_read(tmdev->tm_map, CNTL_ADDR, &reg);
+       ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg);
        if (ret)
                return ret;
 
        mask = BIT(id + SENSOR0_SHIFT);
-       ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg | SW_RST);
+       ret = regmap_write(priv->tm_map, CNTL_ADDR, reg | SW_RST);
        if (ret)
                return ret;
 
-       if (tmdev->num_sensors > 1)
+       if (priv->num_sensors > 1)
                reg |= mask | SLP_CLK_ENA | EN;
        else
                reg |= mask | SLP_CLK_ENA_8660 | EN;
 
-       ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg);
+       ret = regmap_write(priv->tm_map, CNTL_ADDR, reg);
        if (ret)
                return ret;
 
        return 0;
 }
 
-static void disable_8960(struct tsens_device *tmdev)
+static void disable_8960(struct tsens_priv *priv)
 {
        int ret;
        u32 reg_cntl;
        u32 mask;
 
-       mask = GENMASK(tmdev->num_sensors - 1, 0);
+       mask = GENMASK(priv->num_sensors - 1, 0);
        mask <<= SENSOR0_SHIFT;
        mask |= EN;
 
-       ret = regmap_read(tmdev->tm_map, CNTL_ADDR, &reg_cntl);
+       ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg_cntl);
        if (ret)
                return;
 
        reg_cntl &= ~mask;
 
-       if (tmdev->num_sensors > 1)
+       if (priv->num_sensors > 1)
                reg_cntl &= ~SLP_CLK_ENA;
        else
                reg_cntl &= ~SLP_CLK_ENA_8660;
 
-       regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl);
+       regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
 }
 
-static int init_8960(struct tsens_device *tmdev)
+static int init_8960(struct tsens_priv *priv)
 {
        int ret, i;
        u32 reg_cntl;
 
-       tmdev->tm_map = dev_get_regmap(tmdev->dev, NULL);
-       if (!tmdev->tm_map)
+       priv->tm_map = dev_get_regmap(priv->dev, NULL);
+       if (!priv->tm_map)
                return -ENODEV;
 
        /*
@@ -177,21 +177,21 @@ static int init_8960(struct tsens_device *tmdev)
         * but the control registers stay in the same place, i.e
         * directly after the first 5 status registers.
         */
-       for (i = 0; i < tmdev->num_sensors; i++) {
+       for (i = 0; i < priv->num_sensors; i++) {
                if (i >= 5)
-                       tmdev->sensor[i].status = S0_STATUS_ADDR + 40;
-               tmdev->sensor[i].status += i * 4;
+                       priv->sensor[i].status = S0_STATUS_ADDR + 40;
+               priv->sensor[i].status += i * 4;
        }
 
        reg_cntl = SW_RST;
-       ret = regmap_update_bits(tmdev->tm_map, CNTL_ADDR, SW_RST, reg_cntl);
+       ret = regmap_update_bits(priv->tm_map, CNTL_ADDR, SW_RST, reg_cntl);
        if (ret)
                return ret;
 
-       if (tmdev->num_sensors > 1) {
+       if (priv->num_sensors > 1) {
                reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18);
                reg_cntl &= ~SW_RST;
-               ret = regmap_update_bits(tmdev->tm_map, CONFIG_ADDR,
+               ret = regmap_update_bits(priv->tm_map, CONFIG_ADDR,
                                         CONFIG_MASK, CONFIG);
        } else {
                reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16);
@@ -199,30 +199,30 @@ static int init_8960(struct tsens_device *tmdev)
                reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660;
        }
 
-       reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT;
-       ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl);
+       reg_cntl |= GENMASK(priv->num_sensors - 1, 0) << SENSOR0_SHIFT;
+       ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
        if (ret)
                return ret;
 
        reg_cntl |= EN;
-       ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl);
+       ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl);
        if (ret)
                return ret;
 
        return 0;
 }
 
-static int calibrate_8960(struct tsens_device *tmdev)
+static int calibrate_8960(struct tsens_priv *priv)
 {
        int i;
        char *data;
 
-       ssize_t num_read = tmdev->num_sensors;
-       struct tsens_sensor *s = tmdev->sensor;
+       ssize_t num_read = priv->num_sensors;
+       struct tsens_sensor *s = priv->sensor;
 
-       data = qfprom_read(tmdev->dev, "calib");
+       data = qfprom_read(priv->dev, "calib");
        if (IS_ERR(data))
-               data = qfprom_read(tmdev->dev, "calib_backup");
+               data = qfprom_read(priv->dev, "calib_backup");
        if (IS_ERR(data))
                return PTR_ERR(data);
 
@@ -243,21 +243,21 @@ static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s)
        return adc_code * slope + offset;
 }
 
-static int get_temp_8960(struct tsens_device *tmdev, int id, int *temp)
+static int get_temp_8960(struct tsens_priv *priv, int id, int *temp)
 {
        int ret;
        u32 code, trdy;
-       const struct tsens_sensor *s = &tmdev->sensor[id];
+       const struct tsens_sensor *s = &priv->sensor[id];
        unsigned long timeout;
 
        timeout = jiffies + usecs_to_jiffies(TIMEOUT_US);
        do {
-               ret = regmap_read(tmdev->tm_map, INT_STATUS_ADDR, &trdy);
+               ret = regmap_read(priv->tm_map, INT_STATUS_ADDR, &trdy);
                if (ret)
                        return ret;
                if (!(trdy & TRDY_MASK))
                        continue;
-               ret = regmap_read(tmdev->tm_map, s->status, &code);
+               ret = regmap_read(priv->tm_map, s->status, &code);
                if (ret)
                        return ret;
                *temp = code_to_mdegC(code, s);
@@ -277,7 +277,7 @@ static const struct tsens_ops ops_8960 = {
        .resume         = resume_8960,
 };
 
-const struct tsens_data data_8960 = {
+const struct tsens_plat_data data_8960 = {
        .num_sensors    = 11,
        .ops            = &ops_8960,
 };
diff --git a/drivers/thermal/qcom/tsens-8974.c b/drivers/thermal/qcom/tsens-8974.c
deleted file mode 100644 (file)
index 3d3fda3..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
- */
-
-#include <linux/platform_device.h>
-#include "tsens.h"
-
-/* eeprom layout data for 8974 */
-#define BASE1_MASK             0xff
-#define S0_P1_MASK             0x3f00
-#define S1_P1_MASK             0xfc000
-#define S2_P1_MASK             0x3f00000
-#define S3_P1_MASK             0xfc000000
-#define S4_P1_MASK             0x3f
-#define S5_P1_MASK             0xfc0
-#define S6_P1_MASK             0x3f000
-#define S7_P1_MASK             0xfc0000
-#define S8_P1_MASK             0x3f000000
-#define S8_P1_MASK_BKP         0x3f
-#define S9_P1_MASK             0x3f
-#define S9_P1_MASK_BKP         0xfc0
-#define S10_P1_MASK            0xfc0
-#define S10_P1_MASK_BKP                0x3f000
-#define CAL_SEL_0_1            0xc0000000
-#define CAL_SEL_2              0x40000000
-#define CAL_SEL_SHIFT          30
-#define CAL_SEL_SHIFT_2                28
-
-#define S0_P1_SHIFT            8
-#define S1_P1_SHIFT            14
-#define S2_P1_SHIFT            20
-#define S3_P1_SHIFT            26
-#define S5_P1_SHIFT            6
-#define S6_P1_SHIFT            12
-#define S7_P1_SHIFT            18
-#define S8_P1_SHIFT            24
-#define S9_P1_BKP_SHIFT                6
-#define S10_P1_SHIFT           6
-#define S10_P1_BKP_SHIFT       12
-
-#define BASE2_SHIFT            12
-#define BASE2_BKP_SHIFT                18
-#define S0_P2_SHIFT            20
-#define S0_P2_BKP_SHIFT                26
-#define S1_P2_SHIFT            26
-#define S2_P2_BKP_SHIFT                6
-#define S3_P2_SHIFT            6
-#define S3_P2_BKP_SHIFT                12
-#define S4_P2_SHIFT            12
-#define S4_P2_BKP_SHIFT                18
-#define S5_P2_SHIFT            18
-#define S5_P2_BKP_SHIFT                24
-#define S6_P2_SHIFT            24
-#define S7_P2_BKP_SHIFT                6
-#define S8_P2_SHIFT            6
-#define S8_P2_BKP_SHIFT                12
-#define S9_P2_SHIFT            12
-#define S9_P2_BKP_SHIFT                18
-#define S10_P2_SHIFT           18
-#define S10_P2_BKP_SHIFT       24
-
-#define BASE2_MASK             0xff000
-#define BASE2_BKP_MASK         0xfc0000
-#define S0_P2_MASK             0x3f00000
-#define S0_P2_BKP_MASK         0xfc000000
-#define S1_P2_MASK             0xfc000000
-#define S1_P2_BKP_MASK         0x3f
-#define S2_P2_MASK             0x3f
-#define S2_P2_BKP_MASK         0xfc0
-#define S3_P2_MASK             0xfc0
-#define S3_P2_BKP_MASK         0x3f000
-#define S4_P2_MASK             0x3f000
-#define S4_P2_BKP_MASK         0xfc0000
-#define S5_P2_MASK             0xfc0000
-#define S5_P2_BKP_MASK         0x3f000000
-#define S6_P2_MASK             0x3f000000
-#define S6_P2_BKP_MASK         0x3f
-#define S7_P2_MASK             0x3f
-#define S7_P2_BKP_MASK         0xfc0
-#define S8_P2_MASK             0xfc0
-#define S8_P2_BKP_MASK         0x3f000
-#define S9_P2_MASK             0x3f000
-#define S9_P2_BKP_MASK         0xfc0000
-#define S10_P2_MASK            0xfc0000
-#define S10_P2_BKP_MASK                0x3f000000
-
-#define BKP_SEL                        0x3
-#define BKP_REDUN_SEL          0xe0000000
-#define BKP_REDUN_SHIFT                29
-
-#define BIT_APPEND             0x3
-
-static int calibrate_8974(struct tsens_device *tmdev)
-{
-       int base1 = 0, base2 = 0, i;
-       u32 p1[11], p2[11];
-       int mode = 0;
-       u32 *calib, *bkp;
-       u32 calib_redun_sel;
-
-       calib = (u32 *)qfprom_read(tmdev->dev, "calib");
-       if (IS_ERR(calib))
-               return PTR_ERR(calib);
-
-       bkp = (u32 *)qfprom_read(tmdev->dev, "calib_backup");
-       if (IS_ERR(bkp))
-               return PTR_ERR(bkp);
-
-       calib_redun_sel =  bkp[1] & BKP_REDUN_SEL;
-       calib_redun_sel >>= BKP_REDUN_SHIFT;
-
-       if (calib_redun_sel == BKP_SEL) {
-               mode = (calib[4] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
-               mode |= (calib[5] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
-
-               switch (mode) {
-               case TWO_PT_CALIB:
-                       base2 = (bkp[2] & BASE2_BKP_MASK) >> BASE2_BKP_SHIFT;
-                       p2[0] = (bkp[2] & S0_P2_BKP_MASK) >> S0_P2_BKP_SHIFT;
-                       p2[1] = (bkp[3] & S1_P2_BKP_MASK);
-                       p2[2] = (bkp[3] & S2_P2_BKP_MASK) >> S2_P2_BKP_SHIFT;
-                       p2[3] = (bkp[3] & S3_P2_BKP_MASK) >> S3_P2_BKP_SHIFT;
-                       p2[4] = (bkp[3] & S4_P2_BKP_MASK) >> S4_P2_BKP_SHIFT;
-                       p2[5] = (calib[4] & S5_P2_BKP_MASK) >> S5_P2_BKP_SHIFT;
-                       p2[6] = (calib[5] & S6_P2_BKP_MASK);
-                       p2[7] = (calib[5] & S7_P2_BKP_MASK) >> S7_P2_BKP_SHIFT;
-                       p2[8] = (calib[5] & S8_P2_BKP_MASK) >> S8_P2_BKP_SHIFT;
-                       p2[9] = (calib[5] & S9_P2_BKP_MASK) >> S9_P2_BKP_SHIFT;
-                       p2[10] = (calib[5] & S10_P2_BKP_MASK) >> S10_P2_BKP_SHIFT;
-                       /* Fall through */
-               case ONE_PT_CALIB:
-               case ONE_PT_CALIB2:
-                       base1 = bkp[0] & BASE1_MASK;
-                       p1[0] = (bkp[0] & S0_P1_MASK) >> S0_P1_SHIFT;
-                       p1[1] = (bkp[0] & S1_P1_MASK) >> S1_P1_SHIFT;
-                       p1[2] = (bkp[0] & S2_P1_MASK) >> S2_P1_SHIFT;
-                       p1[3] = (bkp[0] & S3_P1_MASK) >> S3_P1_SHIFT;
-                       p1[4] = (bkp[1] & S4_P1_MASK);
-                       p1[5] = (bkp[1] & S5_P1_MASK) >> S5_P1_SHIFT;
-                       p1[6] = (bkp[1] & S6_P1_MASK) >> S6_P1_SHIFT;
-                       p1[7] = (bkp[1] & S7_P1_MASK) >> S7_P1_SHIFT;
-                       p1[8] = (bkp[2] & S8_P1_MASK_BKP) >> S8_P1_SHIFT;
-                       p1[9] = (bkp[2] & S9_P1_MASK_BKP) >> S9_P1_BKP_SHIFT;
-                       p1[10] = (bkp[2] & S10_P1_MASK_BKP) >> S10_P1_BKP_SHIFT;
-                       break;
-               }
-       } else {
-               mode = (calib[1] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
-               mode |= (calib[3] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
-
-               switch (mode) {
-               case TWO_PT_CALIB:
-                       base2 = (calib[2] & BASE2_MASK) >> BASE2_SHIFT;
-                       p2[0] = (calib[2] & S0_P2_MASK) >> S0_P2_SHIFT;
-                       p2[1] = (calib[2] & S1_P2_MASK) >> S1_P2_SHIFT;
-                       p2[2] = (calib[3] & S2_P2_MASK);
-                       p2[3] = (calib[3] & S3_P2_MASK) >> S3_P2_SHIFT;
-                       p2[4] = (calib[3] & S4_P2_MASK) >> S4_P2_SHIFT;
-                       p2[5] = (calib[3] & S5_P2_MASK) >> S5_P2_SHIFT;
-                       p2[6] = (calib[3] & S6_P2_MASK) >> S6_P2_SHIFT;
-                       p2[7] = (calib[4] & S7_P2_MASK);
-                       p2[8] = (calib[4] & S8_P2_MASK) >> S8_P2_SHIFT;
-                       p2[9] = (calib[4] & S9_P2_MASK) >> S9_P2_SHIFT;
-                       p2[10] = (calib[4] & S10_P2_MASK) >> S10_P2_SHIFT;
-                       /* Fall through */
-               case ONE_PT_CALIB:
-               case ONE_PT_CALIB2:
-                       base1 = calib[0] & BASE1_MASK;
-                       p1[0] = (calib[0] & S0_P1_MASK) >> S0_P1_SHIFT;
-                       p1[1] = (calib[0] & S1_P1_MASK) >> S1_P1_SHIFT;
-                       p1[2] = (calib[0] & S2_P1_MASK) >> S2_P1_SHIFT;
-                       p1[3] = (calib[0] & S3_P1_MASK) >> S3_P1_SHIFT;
-                       p1[4] = (calib[1] & S4_P1_MASK);
-                       p1[5] = (calib[1] & S5_P1_MASK) >> S5_P1_SHIFT;
-                       p1[6] = (calib[1] & S6_P1_MASK) >> S6_P1_SHIFT;
-                       p1[7] = (calib[1] & S7_P1_MASK) >> S7_P1_SHIFT;
-                       p1[8] = (calib[1] & S8_P1_MASK) >> S8_P1_SHIFT;
-                       p1[9] = (calib[2] & S9_P1_MASK);
-                       p1[10] = (calib[2] & S10_P1_MASK) >> S10_P1_SHIFT;
-                       break;
-               }
-       }
-
-       switch (mode) {
-       case ONE_PT_CALIB:
-               for (i = 0; i < tmdev->num_sensors; i++)
-                       p1[i] += (base1 << 2) | BIT_APPEND;
-               break;
-       case TWO_PT_CALIB:
-               for (i = 0; i < tmdev->num_sensors; i++) {
-                       p2[i] += base2;
-                       p2[i] <<= 2;
-                       p2[i] |= BIT_APPEND;
-               }
-               /* Fall through */
-       case ONE_PT_CALIB2:
-               for (i = 0; i < tmdev->num_sensors; i++) {
-                       p1[i] += base1;
-                       p1[i] <<= 2;
-                       p1[i] |= BIT_APPEND;
-               }
-               break;
-       default:
-               for (i = 0; i < tmdev->num_sensors; i++)
-                       p2[i] = 780;
-               p1[0] = 502;
-               p1[1] = 509;
-               p1[2] = 503;
-               p1[3] = 509;
-               p1[4] = 505;
-               p1[5] = 509;
-               p1[6] = 507;
-               p1[7] = 510;
-               p1[8] = 508;
-               p1[9] = 509;
-               p1[10] = 508;
-               break;
-       }
-
-       compute_intercept_slope(tmdev, p1, p2, mode);
-
-       return 0;
-}
-
-static const struct tsens_ops ops_8974 = {
-       .init           = init_common,
-       .calibrate      = calibrate_8974,
-       .get_temp       = get_temp_common,
-};
-
-const struct tsens_data data_8974 = {
-       .num_sensors    = 11,
-       .ops            = &ops_8974,
-       .reg_offsets    = { [SROT_CTRL_OFFSET] = 0x0 },
-};
index f80c73f..928e8e8 100644 (file)
 #include <linux/regmap.h>
 #include "tsens.h"
 
-/* SROT */
-#define TSENS_EN               BIT(0)
-
-/* TM */
-#define STATUS_OFFSET          0x30
-#define SN_ADDR_OFFSET         0x4
-#define SN_ST_TEMP_MASK                0x3ff
-#define CAL_DEGC_PT1           30
-#define CAL_DEGC_PT2           120
-#define SLOPE_FACTOR           1000
-#define SLOPE_DEFAULT          3200
-
 char *qfprom_read(struct device *dev, const char *cname)
 {
        struct nvmem_cell *cell;
@@ -46,18 +34,18 @@ char *qfprom_read(struct device *dev, const char *cname)
  * and offset values are derived from tz->tzp->slope and tz->tzp->offset
  * resp.
  */
-void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
+void compute_intercept_slope(struct tsens_priv *priv, u32 *p1,
                             u32 *p2, u32 mode)
 {
        int i;
        int num, den;
 
-       for (i = 0; i < tmdev->num_sensors; i++) {
-               dev_dbg(tmdev->dev,
+       for (i = 0; i < priv->num_sensors; i++) {
+               dev_dbg(priv->dev,
                        "sensor%d - data_point1:%#x data_point2:%#x\n",
                        i, p1[i], p2[i]);
 
-               tmdev->sensor[i].slope = SLOPE_DEFAULT;
+               priv->sensor[i].slope = SLOPE_DEFAULT;
                if (mode == TWO_PT_CALIB) {
                        /*
                         * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
@@ -66,16 +54,30 @@ void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
                        num = p2[i] - p1[i];
                        num *= SLOPE_FACTOR;
                        den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
-                       tmdev->sensor[i].slope = num / den;
+                       priv->sensor[i].slope = num / den;
                }
 
-               tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
+               priv->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
                                (CAL_DEGC_PT1 *
-                               tmdev->sensor[i].slope);
-               dev_dbg(tmdev->dev, "offset:%d\n", tmdev->sensor[i].offset);
+                               priv->sensor[i].slope);
+               dev_dbg(priv->dev, "offset:%d\n", priv->sensor[i].offset);
        }
 }
 
+bool is_sensor_enabled(struct tsens_priv *priv, u32 hw_id)
+{
+       u32 val;
+       int ret;
+
+       if ((hw_id > (priv->num_sensors - 1)) || (hw_id < 0))
+               return -EINVAL;
+       ret = regmap_field_read(priv->rf[SENSOR_EN], &val);
+       if (ret)
+               return ret;
+
+       return val & (1 << hw_id);
+}
+
 static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
 {
        int degc, num, den;
@@ -95,18 +97,54 @@ static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
        return degc;
 }
 
-int get_temp_common(struct tsens_device *tmdev, int id, int *temp)
+int get_temp_tsens_valid(struct tsens_priv *priv, int i, int *temp)
 {
-       struct tsens_sensor *s = &tmdev->sensor[id];
-       u32 code;
-       unsigned int status_reg;
+       struct tsens_sensor *s = &priv->sensor[i];
+       u32 temp_idx = LAST_TEMP_0 + s->hw_id;
+       u32 valid_idx = VALID_0 + s->hw_id;
+       u32 last_temp = 0, valid, mask;
+       int ret;
+
+       ret = regmap_field_read(priv->rf[valid_idx], &valid);
+       if (ret)
+               return ret;
+       while (!valid) {
+               /* Valid bit is 0 for 6 AHB clock cycles.
+                * At 19.2MHz, 1 AHB clock is ~60ns.
+                * We should enter this loop very, very rarely.
+                */
+               ndelay(400);
+               ret = regmap_field_read(priv->rf[valid_idx], &valid);
+               if (ret)
+                       return ret;
+       }
+
+       /* Valid bit is set, OK to read the temperature */
+       ret = regmap_field_read(priv->rf[temp_idx], &last_temp);
+       if (ret)
+               return ret;
+
+       if (priv->feat->adc) {
+               /* Convert temperature from ADC code to milliCelsius */
+               *temp = code_to_degc(last_temp, s) * 1000;
+       } else {
+               mask = GENMASK(priv->fields[LAST_TEMP_0].msb,
+                              priv->fields[LAST_TEMP_0].lsb);
+               /* Convert temperature from deciCelsius to milliCelsius */
+               *temp = sign_extend32(last_temp, fls(mask) - 1) * 100;
+       }
+
+       return 0;
+}
+
+int get_temp_common(struct tsens_priv *priv, int i, int *temp)
+{
+       struct tsens_sensor *s = &priv->sensor[i];
        int last_temp = 0, ret;
 
-       status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * SN_ADDR_OFFSET;
-       ret = regmap_read(tmdev->tm_map, status_reg, &code);
+       ret = regmap_field_read(priv->rf[LAST_TEMP_0 + s->hw_id], &last_temp);
        if (ret)
                return ret;
-       last_temp = code & SN_ST_TEMP_MASK;
 
        *temp = code_to_degc(last_temp, s) * 1000;
 
@@ -127,21 +165,21 @@ static const struct regmap_config tsens_srot_config = {
        .reg_stride     = 4,
 };
 
-int __init init_common(struct tsens_device *tmdev)
+int __init init_common(struct tsens_priv *priv)
 {
        void __iomem *tm_base, *srot_base;
+       struct device *dev = priv->dev;
        struct resource *res;
-       u32 code;
-       int ret;
-       struct platform_device *op = of_find_device_by_node(tmdev->dev->of_node);
-       u16 ctrl_offset = tmdev->reg_offsets[SROT_CTRL_OFFSET];
+       u32 enabled;
+       int ret, i, j;
+       struct platform_device *op = of_find_device_by_node(priv->dev->of_node);
 
        if (!op)
                return -EINVAL;
 
        if (op->num_resources > 1) {
                /* DT with separate SROT and TM address space */
-               tmdev->tm_offset = 0;
+               priv->tm_offset = 0;
                res = platform_get_resource(op, IORESOURCE_MEM, 1);
                srot_base = devm_ioremap_resource(&op->dev, res);
                if (IS_ERR(srot_base)) {
@@ -149,16 +187,15 @@ int __init init_common(struct tsens_device *tmdev)
                        goto err_put_device;
                }
 
-               tmdev->srot_map = devm_regmap_init_mmio(tmdev->dev, srot_base,
+               priv->srot_map = devm_regmap_init_mmio(dev, srot_base,
                                                        &tsens_srot_config);
-               if (IS_ERR(tmdev->srot_map)) {
-                       ret = PTR_ERR(tmdev->srot_map);
+               if (IS_ERR(priv->srot_map)) {
+                       ret = PTR_ERR(priv->srot_map);
                        goto err_put_device;
                }
-
        } else {
                /* old DTs where SROT and TM were in a contiguous 2K block */
-               tmdev->tm_offset = 0x1000;
+               priv->tm_offset = 0x1000;
        }
 
        res = platform_get_resource(op, IORESOURCE_MEM, 0);
@@ -168,19 +205,47 @@ int __init init_common(struct tsens_device *tmdev)
                goto err_put_device;
        }
 
-       tmdev->tm_map = devm_regmap_init_mmio(tmdev->dev, tm_base, &tsens_config);
-       if (IS_ERR(tmdev->tm_map)) {
-               ret = PTR_ERR(tmdev->tm_map);
+       priv->tm_map = devm_regmap_init_mmio(dev, tm_base, &tsens_config);
+       if (IS_ERR(priv->tm_map)) {
+               ret = PTR_ERR(priv->tm_map);
                goto err_put_device;
        }
 
-       if (tmdev->srot_map) {
-               ret = regmap_read(tmdev->srot_map, ctrl_offset, &code);
-               if (ret)
+       priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
+                                                    priv->fields[TSENS_EN]);
+       if (IS_ERR(priv->rf[TSENS_EN])) {
+               ret = PTR_ERR(priv->rf[TSENS_EN]);
+               goto err_put_device;
+       }
+       ret = regmap_field_read(priv->rf[TSENS_EN], &enabled);
+       if (ret)
+               goto err_put_device;
+       if (!enabled) {
+               dev_err(dev, "tsens device is not enabled\n");
+               ret = -ENODEV;
+               goto err_put_device;
+       }
+
+       priv->rf[SENSOR_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
+                                                     priv->fields[SENSOR_EN]);
+       if (IS_ERR(priv->rf[SENSOR_EN])) {
+               ret = PTR_ERR(priv->rf[SENSOR_EN]);
+               goto err_put_device;
+       }
+       /* now alloc regmap_fields in tm_map */
+       for (i = 0, j = LAST_TEMP_0; i < priv->feat->max_sensors; i++, j++) {
+               priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map,
+                                                     priv->fields[j]);
+               if (IS_ERR(priv->rf[j])) {
+                       ret = PTR_ERR(priv->rf[j]);
                        goto err_put_device;
-               if (!(code & TSENS_EN)) {
-                       dev_err(tmdev->dev, "tsens device is not enabled\n");
-                       ret = -ENODEV;
+               }
+       }
+       for (i = 0, j = VALID_0; i < priv->feat->max_sensors; i++, j++) {
+               priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map,
+                                                     priv->fields[j]);
+               if (IS_ERR(priv->rf[j])) {
+                       ret = PTR_ERR(priv->rf[j]);
                        goto err_put_device;
                }
        }
diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c
new file mode 100644 (file)
index 0000000..a319283
--- /dev/null
@@ -0,0 +1,382 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/platform_device.h>
+#include "tsens.h"
+
+/* ----- SROT ------ */
+#define SROT_CTRL_OFF 0x0000
+
+/* ----- TM ------ */
+#define TM_INT_EN_OFF                          0x0000
+#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF      0x0004
+#define TM_Sn_STATUS_OFF                       0x0030
+#define TM_TRDY_OFF                            0x005c
+
+/* eeprom layout data for 8916 */
+#define MSM8916_BASE0_MASK     0x0000007f
+#define MSM8916_BASE1_MASK     0xfe000000
+#define MSM8916_BASE0_SHIFT    0
+#define MSM8916_BASE1_SHIFT    25
+
+#define MSM8916_S0_P1_MASK     0x00000f80
+#define MSM8916_S1_P1_MASK     0x003e0000
+#define MSM8916_S2_P1_MASK     0xf8000000
+#define MSM8916_S3_P1_MASK     0x000003e0
+#define MSM8916_S4_P1_MASK     0x000f8000
+
+#define MSM8916_S0_P2_MASK     0x0001f000
+#define MSM8916_S1_P2_MASK     0x07c00000
+#define MSM8916_S2_P2_MASK     0x0000001f
+#define MSM8916_S3_P2_MASK     0x00007c00
+#define MSM8916_S4_P2_MASK     0x01f00000
+
+#define MSM8916_S0_P1_SHIFT    7
+#define MSM8916_S1_P1_SHIFT    17
+#define MSM8916_S2_P1_SHIFT    27
+#define MSM8916_S3_P1_SHIFT    5
+#define MSM8916_S4_P1_SHIFT    15
+
+#define MSM8916_S0_P2_SHIFT    12
+#define MSM8916_S1_P2_SHIFT    22
+#define MSM8916_S2_P2_SHIFT    0
+#define MSM8916_S3_P2_SHIFT    10
+#define MSM8916_S4_P2_SHIFT    20
+
+#define MSM8916_CAL_SEL_MASK   0xe0000000
+#define MSM8916_CAL_SEL_SHIFT  29
+
+/* eeprom layout data for 8974 */
+#define BASE1_MASK             0xff
+#define S0_P1_MASK             0x3f00
+#define S1_P1_MASK             0xfc000
+#define S2_P1_MASK             0x3f00000
+#define S3_P1_MASK             0xfc000000
+#define S4_P1_MASK             0x3f
+#define S5_P1_MASK             0xfc0
+#define S6_P1_MASK             0x3f000
+#define S7_P1_MASK             0xfc0000
+#define S8_P1_MASK             0x3f000000
+#define S8_P1_MASK_BKP         0x3f
+#define S9_P1_MASK             0x3f
+#define S9_P1_MASK_BKP         0xfc0
+#define S10_P1_MASK            0xfc0
+#define S10_P1_MASK_BKP                0x3f000
+#define CAL_SEL_0_1            0xc0000000
+#define CAL_SEL_2              0x40000000
+#define CAL_SEL_SHIFT          30
+#define CAL_SEL_SHIFT_2                28
+
+#define S0_P1_SHIFT            8
+#define S1_P1_SHIFT            14
+#define S2_P1_SHIFT            20
+#define S3_P1_SHIFT            26
+#define S5_P1_SHIFT            6
+#define S6_P1_SHIFT            12
+#define S7_P1_SHIFT            18
+#define S8_P1_SHIFT            24
+#define S9_P1_BKP_SHIFT                6
+#define S10_P1_SHIFT           6
+#define S10_P1_BKP_SHIFT       12
+
+#define BASE2_SHIFT            12
+#define BASE2_BKP_SHIFT                18
+#define S0_P2_SHIFT            20
+#define S0_P2_BKP_SHIFT                26
+#define S1_P2_SHIFT            26
+#define S2_P2_BKP_SHIFT                6
+#define S3_P2_SHIFT            6
+#define S3_P2_BKP_SHIFT                12
+#define S4_P2_SHIFT            12
+#define S4_P2_BKP_SHIFT                18
+#define S5_P2_SHIFT            18
+#define S5_P2_BKP_SHIFT                24
+#define S6_P2_SHIFT            24
+#define S7_P2_BKP_SHIFT                6
+#define S8_P2_SHIFT            6
+#define S8_P2_BKP_SHIFT                12
+#define S9_P2_SHIFT            12
+#define S9_P2_BKP_SHIFT                18
+#define S10_P2_SHIFT           18
+#define S10_P2_BKP_SHIFT       24
+
+#define BASE2_MASK             0xff000
+#define BASE2_BKP_MASK         0xfc0000
+#define S0_P2_MASK             0x3f00000
+#define S0_P2_BKP_MASK         0xfc000000
+#define S1_P2_MASK             0xfc000000
+#define S1_P2_BKP_MASK         0x3f
+#define S2_P2_MASK             0x3f
+#define S2_P2_BKP_MASK         0xfc0
+#define S3_P2_MASK             0xfc0
+#define S3_P2_BKP_MASK         0x3f000
+#define S4_P2_MASK             0x3f000
+#define S4_P2_BKP_MASK         0xfc0000
+#define S5_P2_MASK             0xfc0000
+#define S5_P2_BKP_MASK         0x3f000000
+#define S6_P2_MASK             0x3f000000
+#define S6_P2_BKP_MASK         0x3f
+#define S7_P2_MASK             0x3f
+#define S7_P2_BKP_MASK         0xfc0
+#define S8_P2_MASK             0xfc0
+#define S8_P2_BKP_MASK         0x3f000
+#define S9_P2_MASK             0x3f000
+#define S9_P2_BKP_MASK         0xfc0000
+#define S10_P2_MASK            0xfc0000
+#define S10_P2_BKP_MASK                0x3f000000
+
+#define BKP_SEL                        0x3
+#define BKP_REDUN_SEL          0xe0000000
+#define BKP_REDUN_SHIFT                29
+
+#define BIT_APPEND             0x3
+
+static int calibrate_8916(struct tsens_priv *priv)
+{
+       int base0 = 0, base1 = 0, i;
+       u32 p1[5], p2[5];
+       int mode = 0;
+       u32 *qfprom_cdata, *qfprom_csel;
+
+       qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
+       if (IS_ERR(qfprom_cdata))
+               return PTR_ERR(qfprom_cdata);
+
+       qfprom_csel = (u32 *)qfprom_read(priv->dev, "calib_sel");
+       if (IS_ERR(qfprom_csel))
+               return PTR_ERR(qfprom_csel);
+
+       mode = (qfprom_csel[0] & MSM8916_CAL_SEL_MASK) >> MSM8916_CAL_SEL_SHIFT;
+       dev_dbg(priv->dev, "calibration mode is %d\n", mode);
+
+       switch (mode) {
+       case TWO_PT_CALIB:
+               base1 = (qfprom_cdata[1] & MSM8916_BASE1_MASK) >> MSM8916_BASE1_SHIFT;
+               p2[0] = (qfprom_cdata[0] & MSM8916_S0_P2_MASK) >> MSM8916_S0_P2_SHIFT;
+               p2[1] = (qfprom_cdata[0] & MSM8916_S1_P2_MASK) >> MSM8916_S1_P2_SHIFT;
+               p2[2] = (qfprom_cdata[1] & MSM8916_S2_P2_MASK) >> MSM8916_S2_P2_SHIFT;
+               p2[3] = (qfprom_cdata[1] & MSM8916_S3_P2_MASK) >> MSM8916_S3_P2_SHIFT;
+               p2[4] = (qfprom_cdata[1] & MSM8916_S4_P2_MASK) >> MSM8916_S4_P2_SHIFT;
+               for (i = 0; i < priv->num_sensors; i++)
+                       p2[i] = ((base1 + p2[i]) << 3);
+               /* Fall through */
+       case ONE_PT_CALIB2:
+               base0 = (qfprom_cdata[0] & MSM8916_BASE0_MASK);
+               p1[0] = (qfprom_cdata[0] & MSM8916_S0_P1_MASK) >> MSM8916_S0_P1_SHIFT;
+               p1[1] = (qfprom_cdata[0] & MSM8916_S1_P1_MASK) >> MSM8916_S1_P1_SHIFT;
+               p1[2] = (qfprom_cdata[0] & MSM8916_S2_P1_MASK) >> MSM8916_S2_P1_SHIFT;
+               p1[3] = (qfprom_cdata[1] & MSM8916_S3_P1_MASK) >> MSM8916_S3_P1_SHIFT;
+               p1[4] = (qfprom_cdata[1] & MSM8916_S4_P1_MASK) >> MSM8916_S4_P1_SHIFT;
+               for (i = 0; i < priv->num_sensors; i++)
+                       p1[i] = (((base0) + p1[i]) << 3);
+               break;
+       default:
+               for (i = 0; i < priv->num_sensors; i++) {
+                       p1[i] = 500;
+                       p2[i] = 780;
+               }
+               break;
+       }
+
+       compute_intercept_slope(priv, p1, p2, mode);
+
+       return 0;
+}
+
+static int calibrate_8974(struct tsens_priv *priv)
+{
+       int base1 = 0, base2 = 0, i;
+       u32 p1[11], p2[11];
+       int mode = 0;
+       u32 *calib, *bkp;
+       u32 calib_redun_sel;
+
+       calib = (u32 *)qfprom_read(priv->dev, "calib");
+       if (IS_ERR(calib))
+               return PTR_ERR(calib);
+
+       bkp = (u32 *)qfprom_read(priv->dev, "calib_backup");
+       if (IS_ERR(bkp))
+               return PTR_ERR(bkp);
+
+       calib_redun_sel =  bkp[1] & BKP_REDUN_SEL;
+       calib_redun_sel >>= BKP_REDUN_SHIFT;
+
+       if (calib_redun_sel == BKP_SEL) {
+               mode = (calib[4] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
+               mode |= (calib[5] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
+
+               switch (mode) {
+               case TWO_PT_CALIB:
+                       base2 = (bkp[2] & BASE2_BKP_MASK) >> BASE2_BKP_SHIFT;
+                       p2[0] = (bkp[2] & S0_P2_BKP_MASK) >> S0_P2_BKP_SHIFT;
+                       p2[1] = (bkp[3] & S1_P2_BKP_MASK);
+                       p2[2] = (bkp[3] & S2_P2_BKP_MASK) >> S2_P2_BKP_SHIFT;
+                       p2[3] = (bkp[3] & S3_P2_BKP_MASK) >> S3_P2_BKP_SHIFT;
+                       p2[4] = (bkp[3] & S4_P2_BKP_MASK) >> S4_P2_BKP_SHIFT;
+                       p2[5] = (calib[4] & S5_P2_BKP_MASK) >> S5_P2_BKP_SHIFT;
+                       p2[6] = (calib[5] & S6_P2_BKP_MASK);
+                       p2[7] = (calib[5] & S7_P2_BKP_MASK) >> S7_P2_BKP_SHIFT;
+                       p2[8] = (calib[5] & S8_P2_BKP_MASK) >> S8_P2_BKP_SHIFT;
+                       p2[9] = (calib[5] & S9_P2_BKP_MASK) >> S9_P2_BKP_SHIFT;
+                       p2[10] = (calib[5] & S10_P2_BKP_MASK) >> S10_P2_BKP_SHIFT;
+                       /* Fall through */
+               case ONE_PT_CALIB:
+               case ONE_PT_CALIB2:
+                       base1 = bkp[0] & BASE1_MASK;
+                       p1[0] = (bkp[0] & S0_P1_MASK) >> S0_P1_SHIFT;
+                       p1[1] = (bkp[0] & S1_P1_MASK) >> S1_P1_SHIFT;
+                       p1[2] = (bkp[0] & S2_P1_MASK) >> S2_P1_SHIFT;
+                       p1[3] = (bkp[0] & S3_P1_MASK) >> S3_P1_SHIFT;
+                       p1[4] = (bkp[1] & S4_P1_MASK);
+                       p1[5] = (bkp[1] & S5_P1_MASK) >> S5_P1_SHIFT;
+                       p1[6] = (bkp[1] & S6_P1_MASK) >> S6_P1_SHIFT;
+                       p1[7] = (bkp[1] & S7_P1_MASK) >> S7_P1_SHIFT;
+                       p1[8] = (bkp[2] & S8_P1_MASK_BKP) >> S8_P1_SHIFT;
+                       p1[9] = (bkp[2] & S9_P1_MASK_BKP) >> S9_P1_BKP_SHIFT;
+                       p1[10] = (bkp[2] & S10_P1_MASK_BKP) >> S10_P1_BKP_SHIFT;
+                       break;
+               }
+       } else {
+               mode = (calib[1] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
+               mode |= (calib[3] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
+
+               switch (mode) {
+               case TWO_PT_CALIB:
+                       base2 = (calib[2] & BASE2_MASK) >> BASE2_SHIFT;
+                       p2[0] = (calib[2] & S0_P2_MASK) >> S0_P2_SHIFT;
+                       p2[1] = (calib[2] & S1_P2_MASK) >> S1_P2_SHIFT;
+                       p2[2] = (calib[3] & S2_P2_MASK);
+                       p2[3] = (calib[3] & S3_P2_MASK) >> S3_P2_SHIFT;
+                       p2[4] = (calib[3] & S4_P2_MASK) >> S4_P2_SHIFT;
+                       p2[5] = (calib[3] & S5_P2_MASK) >> S5_P2_SHIFT;
+                       p2[6] = (calib[3] & S6_P2_MASK) >> S6_P2_SHIFT;
+                       p2[7] = (calib[4] & S7_P2_MASK);
+                       p2[8] = (calib[4] & S8_P2_MASK) >> S8_P2_SHIFT;
+                       p2[9] = (calib[4] & S9_P2_MASK) >> S9_P2_SHIFT;
+                       p2[10] = (calib[4] & S10_P2_MASK) >> S10_P2_SHIFT;
+                       /* Fall through */
+               case ONE_PT_CALIB:
+               case ONE_PT_CALIB2:
+                       base1 = calib[0] & BASE1_MASK;
+                       p1[0] = (calib[0] & S0_P1_MASK) >> S0_P1_SHIFT;
+                       p1[1] = (calib[0] & S1_P1_MASK) >> S1_P1_SHIFT;
+                       p1[2] = (calib[0] & S2_P1_MASK) >> S2_P1_SHIFT;
+                       p1[3] = (calib[0] & S3_P1_MASK) >> S3_P1_SHIFT;
+                       p1[4] = (calib[1] & S4_P1_MASK);
+                       p1[5] = (calib[1] & S5_P1_MASK) >> S5_P1_SHIFT;
+                       p1[6] = (calib[1] & S6_P1_MASK) >> S6_P1_SHIFT;
+                       p1[7] = (calib[1] & S7_P1_MASK) >> S7_P1_SHIFT;
+                       p1[8] = (calib[1] & S8_P1_MASK) >> S8_P1_SHIFT;
+                       p1[9] = (calib[2] & S9_P1_MASK);
+                       p1[10] = (calib[2] & S10_P1_MASK) >> S10_P1_SHIFT;
+                       break;
+               }
+       }
+
+       switch (mode) {
+       case ONE_PT_CALIB:
+               for (i = 0; i < priv->num_sensors; i++)
+                       p1[i] += (base1 << 2) | BIT_APPEND;
+               break;
+       case TWO_PT_CALIB:
+               for (i = 0; i < priv->num_sensors; i++) {
+                       p2[i] += base2;
+                       p2[i] <<= 2;
+                       p2[i] |= BIT_APPEND;
+               }
+               /* Fall through */
+       case ONE_PT_CALIB2:
+               for (i = 0; i < priv->num_sensors; i++) {
+                       p1[i] += base1;
+                       p1[i] <<= 2;
+                       p1[i] |= BIT_APPEND;
+               }
+               break;
+       default:
+               for (i = 0; i < priv->num_sensors; i++)
+                       p2[i] = 780;
+               p1[0] = 502;
+               p1[1] = 509;
+               p1[2] = 503;
+               p1[3] = 509;
+               p1[4] = 505;
+               p1[5] = 509;
+               p1[6] = 507;
+               p1[7] = 510;
+               p1[8] = 508;
+               p1[9] = 509;
+               p1[10] = 508;
+               break;
+       }
+
+       compute_intercept_slope(priv, p1, p2, mode);
+
+       return 0;
+}
+
+/* v0.1: 8916, 8974 */
+
+static const struct tsens_features tsens_v0_1_feat = {
+       .ver_major      = VER_0_1,
+       .crit_int       = 0,
+       .adc            = 1,
+       .srot_split     = 1,
+       .max_sensors    = 11,
+};
+
+static const struct reg_field tsens_v0_1_regfields[MAX_REGFIELDS] = {
+       /* ----- SROT ------ */
+       /* No VERSION information */
+
+       /* CTRL_OFFSET */
+       [TSENS_EN]     = REG_FIELD(SROT_CTRL_OFF, 0,  0),
+       [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1,  1),
+       [SENSOR_EN]    = REG_FIELD(SROT_CTRL_OFF, 3, 13),
+
+       /* ----- TM ------ */
+       /* INTERRUPT ENABLE */
+       [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0),
+
+       /* Sn_STATUS */
+       REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP,    TM_Sn_STATUS_OFF,  0,  9),
+       /* No VALID field on v0.1 */
+       REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS,   TM_Sn_STATUS_OFF, 10, 10),
+       REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11),
+       REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12),
+       /* No CRITICAL field on v0.1 */
+       REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS,   TM_Sn_STATUS_OFF, 13, 13),
+
+       /* TRDY: 1=ready, 0=in progress */
+       [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
+};
+
+static const struct tsens_ops ops_8916 = {
+       .init           = init_common,
+       .calibrate      = calibrate_8916,
+       .get_temp       = get_temp_common,
+};
+
+const struct tsens_plat_data data_8916 = {
+       .num_sensors    = 5,
+       .ops            = &ops_8916,
+       .hw_ids         = (unsigned int []){0, 1, 2, 4, 5 },
+
+       .feat           = &tsens_v0_1_feat,
+       .fields = tsens_v0_1_regfields,
+};
+
+static const struct tsens_ops ops_8974 = {
+       .init           = init_common,
+       .calibrate      = calibrate_8974,
+       .get_temp       = get_temp_common,
+};
+
+const struct tsens_plat_data data_8974 = {
+       .num_sensors    = 11,
+       .ops            = &ops_8974,
+       .feat           = &tsens_v0_1_feat,
+       .fields = tsens_v0_1_regfields,
+};
diff --git a/drivers/thermal/qcom/tsens-v1.c b/drivers/thermal/qcom/tsens-v1.c
new file mode 100644 (file)
index 0000000..10b595d
--- /dev/null
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <linux/delay.h>
+#include "tsens.h"
+
+/* ----- SROT ------ */
+#define SROT_HW_VER_OFF        0x0000
+#define SROT_CTRL_OFF          0x0004
+
+/* ----- TM ------ */
+#define TM_INT_EN_OFF                          0x0000
+#define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF      0x0004
+#define TM_Sn_STATUS_OFF                       0x0044
+#define TM_TRDY_OFF                            0x0084
+
+/* eeprom layout data for qcs404/405 (v1) */
+#define BASE0_MASK     0x000007f8
+#define BASE1_MASK     0x0007f800
+#define BASE0_SHIFT    3
+#define BASE1_SHIFT    11
+
+#define S0_P1_MASK     0x0000003f
+#define S1_P1_MASK     0x0003f000
+#define S2_P1_MASK     0x3f000000
+#define S3_P1_MASK     0x000003f0
+#define S4_P1_MASK     0x003f0000
+#define S5_P1_MASK     0x0000003f
+#define S6_P1_MASK     0x0003f000
+#define S7_P1_MASK     0x3f000000
+#define S8_P1_MASK     0x000003f0
+#define S9_P1_MASK     0x003f0000
+
+#define S0_P2_MASK     0x00000fc0
+#define S1_P2_MASK     0x00fc0000
+#define S2_P2_MASK_1_0 0xc0000000
+#define S2_P2_MASK_5_2 0x0000000f
+#define S3_P2_MASK     0x0000fc00
+#define S4_P2_MASK     0x0fc00000
+#define S5_P2_MASK     0x00000fc0
+#define S6_P2_MASK     0x00fc0000
+#define S7_P2_MASK_1_0 0xc0000000
+#define S7_P2_MASK_5_2 0x0000000f
+#define S8_P2_MASK     0x0000fc00
+#define S9_P2_MASK     0x0fc00000
+
+#define S0_P1_SHIFT    0
+#define S0_P2_SHIFT    6
+#define S1_P1_SHIFT    12
+#define S1_P2_SHIFT    18
+#define S2_P1_SHIFT    24
+#define S2_P2_SHIFT_1_0        30
+
+#define S2_P2_SHIFT_5_2        0
+#define S3_P1_SHIFT    4
+#define S3_P2_SHIFT    10
+#define S4_P1_SHIFT    16
+#define S4_P2_SHIFT    22
+
+#define S5_P1_SHIFT    0
+#define S5_P2_SHIFT    6
+#define S6_P1_SHIFT    12
+#define S6_P2_SHIFT    18
+#define S7_P1_SHIFT    24
+#define S7_P2_SHIFT_1_0        30
+
+#define S7_P2_SHIFT_5_2        0
+#define S8_P1_SHIFT    4
+#define S8_P2_SHIFT    10
+#define S9_P1_SHIFT    16
+#define S9_P2_SHIFT    22
+
+#define CAL_SEL_MASK   7
+#define CAL_SEL_SHIFT  0
+
+static int calibrate_v1(struct tsens_priv *priv)
+{
+       u32 base0 = 0, base1 = 0;
+       u32 p1[10], p2[10];
+       u32 mode = 0, lsb = 0, msb = 0;
+       u32 *qfprom_cdata;
+       int i;
+
+       qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib");
+       if (IS_ERR(qfprom_cdata))
+               return PTR_ERR(qfprom_cdata);
+
+       mode = (qfprom_cdata[4] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
+       dev_dbg(priv->dev, "calibration mode is %d\n", mode);
+
+       switch (mode) {
+       case TWO_PT_CALIB:
+               base1 = (qfprom_cdata[4] & BASE1_MASK) >> BASE1_SHIFT;
+               p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
+               p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
+               /* This value is split over two registers, 2 bits and 4 bits */
+               lsb   = (qfprom_cdata[0] & S2_P2_MASK_1_0) >> S2_P2_SHIFT_1_0;
+               msb   = (qfprom_cdata[1] & S2_P2_MASK_5_2) >> S2_P2_SHIFT_5_2;
+               p2[2] = msb << 2 | lsb;
+               p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
+               p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
+               p2[5] = (qfprom_cdata[2] & S5_P2_MASK) >> S5_P2_SHIFT;
+               p2[6] = (qfprom_cdata[2] & S6_P2_MASK) >> S6_P2_SHIFT;
+               /* This value is split over two registers, 2 bits and 4 bits */
+               lsb   = (qfprom_cdata[2] & S7_P2_MASK_1_0) >> S7_P2_SHIFT_1_0;
+               msb   = (qfprom_cdata[3] & S7_P2_MASK_5_2) >> S7_P2_SHIFT_5_2;
+               p2[7] = msb << 2 | lsb;
+               p2[8] = (qfprom_cdata[3] & S8_P2_MASK) >> S8_P2_SHIFT;
+               p2[9] = (qfprom_cdata[3] & S9_P2_MASK) >> S9_P2_SHIFT;
+               for (i = 0; i < priv->num_sensors; i++)
+                       p2[i] = ((base1 + p2[i]) << 2);
+               /* Fall through */
+       case ONE_PT_CALIB2:
+               base0 = (qfprom_cdata[4] & BASE0_MASK) >> BASE0_SHIFT;
+               p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
+               p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
+               p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
+               p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
+               p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
+               p1[5] = (qfprom_cdata[2] & S5_P1_MASK) >> S5_P1_SHIFT;
+               p1[6] = (qfprom_cdata[2] & S6_P1_MASK) >> S6_P1_SHIFT;
+               p1[7] = (qfprom_cdata[2] & S7_P1_MASK) >> S7_P1_SHIFT;
+               p1[8] = (qfprom_cdata[3] & S8_P1_MASK) >> S8_P1_SHIFT;
+               p1[9] = (qfprom_cdata[3] & S9_P1_MASK) >> S9_P1_SHIFT;
+               for (i = 0; i < priv->num_sensors; i++)
+                       p1[i] = (((base0) + p1[i]) << 2);
+               break;
+       default:
+               for (i = 0; i < priv->num_sensors; i++) {
+                       p1[i] = 500;
+                       p2[i] = 780;
+               }
+               break;
+       }
+
+       compute_intercept_slope(priv, p1, p2, mode);
+
+       return 0;
+}
+
+/* v1.x: qcs404,405 */
+
+static const struct tsens_features tsens_v1_feat = {
+       .ver_major      = VER_1_X,
+       .crit_int       = 0,
+       .adc            = 1,
+       .srot_split     = 1,
+       .max_sensors    = 11,
+};
+
+static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = {
+       /* ----- SROT ------ */
+       /* VERSION */
+       [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31),
+       [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27),
+       [VER_STEP]  = REG_FIELD(SROT_HW_VER_OFF,  0, 15),
+       /* CTRL_OFFSET */
+       [TSENS_EN]     = REG_FIELD(SROT_CTRL_OFF, 0,  0),
+       [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1,  1),
+       [SENSOR_EN]    = REG_FIELD(SROT_CTRL_OFF, 3, 13),
+
+       /* ----- TM ------ */
+       /* INTERRUPT ENABLE */
+       [INT_EN]     = REG_FIELD(TM_INT_EN_OFF, 0, 0),
+
+       /* Sn_STATUS */
+       REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP,    TM_Sn_STATUS_OFF,  0,  9),
+       REG_FIELD_FOR_EACH_SENSOR11(VALID,        TM_Sn_STATUS_OFF, 14, 14),
+       REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS,   TM_Sn_STATUS_OFF, 10, 10),
+       REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11),
+       REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12),
+       /* No CRITICAL field on v1.x */
+       REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS,   TM_Sn_STATUS_OFF, 13, 13),
+
+       /* TRDY: 1=ready, 0=in progress */
+       [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
+};
+
+static const struct tsens_ops ops_generic_v1 = {
+       .init           = init_common,
+       .calibrate      = calibrate_v1,
+       .get_temp       = get_temp_tsens_valid,
+};
+
+const struct tsens_plat_data data_tsens_v1 = {
+       .ops            = &ops_generic_v1,
+       .feat           = &tsens_v1_feat,
+       .fields = tsens_v1_regfields,
+};
index 381a212..1099069 100644 (file)
@@ -4,76 +4,81 @@
  * Copyright (c) 2018, Linaro Limited
  */
 
-#include <linux/regmap.h>
 #include <linux/bitops.h>
+#include <linux/regmap.h>
 #include "tsens.h"
 
-#define STATUS_OFFSET          0xa0
-#define LAST_TEMP_MASK         0xfff
-#define STATUS_VALID_BIT       BIT(21)
+/* ----- SROT ------ */
+#define SROT_HW_VER_OFF        0x0000
+#define SROT_CTRL_OFF          0x0004
+
+/* ----- TM ------ */
+#define TM_INT_EN_OFF                  0x0004
+#define TM_UPPER_LOWER_INT_STATUS_OFF  0x0008
+#define TM_UPPER_LOWER_INT_CLEAR_OFF   0x000c
+#define TM_UPPER_LOWER_INT_MASK_OFF    0x0010
+#define TM_CRITICAL_INT_STATUS_OFF     0x0014
+#define TM_CRITICAL_INT_CLEAR_OFF      0x0018
+#define TM_CRITICAL_INT_MASK_OFF       0x001c
+#define TM_Sn_UPPER_LOWER_THRESHOLD_OFF 0x0020
+#define TM_Sn_CRITICAL_THRESHOLD_OFF   0x0060
+#define TM_Sn_STATUS_OFF               0x00a0
+#define TM_TRDY_OFF                    0x00e4
 
-static int get_temp_tsens_v2(struct tsens_device *tmdev, int id, int *temp)
-{
-       struct tsens_sensor *s = &tmdev->sensor[id];
-       u32 code;
-       unsigned int status_reg;
-       u32 last_temp = 0, last_temp2 = 0, last_temp3 = 0;
-       int ret;
+/* v2.x: 8996, 8998, sdm845 */
 
-       status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * 4;
-       ret = regmap_read(tmdev->tm_map, status_reg, &code);
-       if (ret)
-               return ret;
-       last_temp = code & LAST_TEMP_MASK;
-       if (code & STATUS_VALID_BIT)
-               goto done;
+static const struct tsens_features tsens_v2_feat = {
+       .ver_major      = VER_2_X,
+       .crit_int       = 1,
+       .adc            = 0,
+       .srot_split     = 1,
+       .max_sensors    = 16,
+};
 
-       /* Try a second time */
-       ret = regmap_read(tmdev->tm_map, status_reg, &code);
-       if (ret)
-               return ret;
-       if (code & STATUS_VALID_BIT) {
-               last_temp = code & LAST_TEMP_MASK;
-               goto done;
-       } else {
-               last_temp2 = code & LAST_TEMP_MASK;
-       }
+static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
+       /* ----- SROT ------ */
+       /* VERSION */
+       [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31),
+       [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27),
+       [VER_STEP]  = REG_FIELD(SROT_HW_VER_OFF,  0, 15),
+       /* CTRL_OFF */
+       [TSENS_EN]     = REG_FIELD(SROT_CTRL_OFF,    0,  0),
+       [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF,    1,  1),
+       [SENSOR_EN]    = REG_FIELD(SROT_CTRL_OFF,    3, 18),
 
-       /* Try a third/last time */
-       ret = regmap_read(tmdev->tm_map, status_reg, &code);
-       if (ret)
-               return ret;
-       if (code & STATUS_VALID_BIT) {
-               last_temp = code & LAST_TEMP_MASK;
-               goto done;
-       } else {
-               last_temp3 = code & LAST_TEMP_MASK;
-       }
+       /* ----- TM ------ */
+       /* INTERRUPT ENABLE */
+       /* v2 has separate enables for UPPER/LOWER/CRITICAL interrupts */
+       [INT_EN]  = REG_FIELD(TM_INT_EN_OFF, 0, 2),
 
-       if (last_temp == last_temp2)
-               last_temp = last_temp2;
-       else if (last_temp2 == last_temp3)
-               last_temp = last_temp3;
-done:
-       /* Convert temperature from deciCelsius to milliCelsius */
-       *temp = sign_extend32(last_temp, fls(LAST_TEMP_MASK) - 1) * 100;
+       /* Sn_STATUS */
+       REG_FIELD_FOR_EACH_SENSOR16(LAST_TEMP,       TM_Sn_STATUS_OFF,  0,  11),
+       REG_FIELD_FOR_EACH_SENSOR16(VALID,           TM_Sn_STATUS_OFF, 21,  21),
+       REG_FIELD_FOR_EACH_SENSOR16(MIN_STATUS,      TM_Sn_STATUS_OFF, 16,  16),
+       REG_FIELD_FOR_EACH_SENSOR16(LOWER_STATUS,    TM_Sn_STATUS_OFF, 17,  17),
+       REG_FIELD_FOR_EACH_SENSOR16(UPPER_STATUS,    TM_Sn_STATUS_OFF, 18,  18),
+       REG_FIELD_FOR_EACH_SENSOR16(CRITICAL_STATUS, TM_Sn_STATUS_OFF, 19,  19),
+       REG_FIELD_FOR_EACH_SENSOR16(MAX_STATUS,      TM_Sn_STATUS_OFF, 20,  20),
 
-       return 0;
-}
+       /* TRDY: 1=ready, 0=in progress */
+       [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
+};
 
 static const struct tsens_ops ops_generic_v2 = {
        .init           = init_common,
-       .get_temp       = get_temp_tsens_v2,
+       .get_temp       = get_temp_tsens_valid,
 };
 
-const struct tsens_data data_tsens_v2 = {
-       .ops            = &ops_generic_v2,
-       .reg_offsets    = { [SROT_CTRL_OFFSET] = 0x4 },
+const struct tsens_plat_data data_tsens_v2 = {
+       .ops            = &ops_generic_v2,
+       .feat           = &tsens_v2_feat,
+       .fields = tsens_v2_regfields,
 };
 
 /* Kept around for backward compatibility with old msm8996.dtsi */
-const struct tsens_data data_8996 = {
+const struct tsens_plat_data data_8996 = {
        .num_sensors    = 13,
        .ops            = &ops_generic_v2,
-       .reg_offsets    = { [SROT_CTRL_OFFSET] = 0x4 },
+       .feat           = &tsens_v2_feat,
+       .fields = tsens_v2_regfields,
 };
index f1ec9bb..36b0b52 100644 (file)
 static int tsens_get_temp(void *data, int *temp)
 {
        const struct tsens_sensor *s = data;
-       struct tsens_device *tmdev = s->tmdev;
+       struct tsens_priv *priv = s->priv;
 
-       return tmdev->ops->get_temp(tmdev, s->id, temp);
+       return priv->ops->get_temp(priv, s->id, temp);
 }
 
-static int tsens_get_trend(void *p, int trip, enum thermal_trend *trend)
+static int tsens_get_trend(void *data, int trip, enum thermal_trend *trend)
 {
-       const struct tsens_sensor *s = p;
-       struct tsens_device *tmdev = s->tmdev;
+       const struct tsens_sensor *s = data;
+       struct tsens_priv *priv = s->priv;
 
-       if (tmdev->ops->get_trend)
-               return  tmdev->ops->get_trend(tmdev, s->id, trend);
+       if (priv->ops->get_trend)
+               return priv->ops->get_trend(priv, s->id, trend);
 
        return -ENOTSUPP;
 }
 
 static int  __maybe_unused tsens_suspend(struct device *dev)
 {
-       struct tsens_device *tmdev = dev_get_drvdata(dev);
+       struct tsens_priv *priv = dev_get_drvdata(dev);
 
-       if (tmdev->ops && tmdev->ops->suspend)
-               return tmdev->ops->suspend(tmdev);
+       if (priv->ops && priv->ops->suspend)
+               return priv->ops->suspend(priv);
 
        return 0;
 }
 
 static int __maybe_unused tsens_resume(struct device *dev)
 {
-       struct tsens_device *tmdev = dev_get_drvdata(dev);
+       struct tsens_priv *priv = dev_get_drvdata(dev);
 
-       if (tmdev->ops && tmdev->ops->resume)
-               return tmdev->ops->resume(tmdev);
+       if (priv->ops && priv->ops->resume)
+               return priv->ops->resume(priv);
 
        return 0;
 }
@@ -63,6 +63,9 @@ static const struct of_device_id tsens_table[] = {
        }, {
                .compatible = "qcom,msm8996-tsens",
                .data = &data_8996,
+       }, {
+               .compatible = "qcom,tsens-v1",
+               .data = &data_tsens_v1,
        }, {
                .compatible = "qcom,tsens-v2",
                .data = &data_tsens_v2,
@@ -76,22 +79,27 @@ static const struct thermal_zone_of_device_ops tsens_of_ops = {
        .get_trend = tsens_get_trend,
 };
 
-static int tsens_register(struct tsens_device *tmdev)
+static int tsens_register(struct tsens_priv *priv)
 {
        int i;
        struct thermal_zone_device *tzd;
 
-       for (i = 0;  i < tmdev->num_sensors; i++) {
-               tmdev->sensor[i].tmdev = tmdev;
-               tmdev->sensor[i].id = i;
-               tzd = devm_thermal_zone_of_sensor_register(tmdev->dev, i,
-                                                          &tmdev->sensor[i],
+       for (i = 0;  i < priv->num_sensors; i++) {
+               if (!is_sensor_enabled(priv, priv->sensor[i].hw_id)) {
+                       dev_err(priv->dev, "sensor %d: disabled\n",
+                               priv->sensor[i].hw_id);
+                       continue;
+               }
+               priv->sensor[i].priv = priv;
+               priv->sensor[i].id = i;
+               tzd = devm_thermal_zone_of_sensor_register(priv->dev, i,
+                                                          &priv->sensor[i],
                                                           &tsens_of_ops);
                if (IS_ERR(tzd))
                        continue;
-               tmdev->sensor[i].tzd = tzd;
-               if (tmdev->ops->enable)
-                       tmdev->ops->enable(tmdev, i);
+               priv->sensor[i].tzd = tzd;
+               if (priv->ops->enable)
+                       priv->ops->enable(priv, i);
        }
        return 0;
 }
@@ -101,8 +109,8 @@ static int tsens_probe(struct platform_device *pdev)
        int ret, i;
        struct device *dev;
        struct device_node *np;
-       struct tsens_device *tmdev;
-       const struct tsens_data *data;
+       struct tsens_priv *priv;
+       const struct tsens_plat_data *data;
        const struct of_device_id *id;
        u32 num_sensors;
 
@@ -129,55 +137,55 @@ static int tsens_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       tmdev = devm_kzalloc(dev,
-                            struct_size(tmdev, sensor, num_sensors),
+       priv = devm_kzalloc(dev,
+                            struct_size(priv, sensor, num_sensors),
                             GFP_KERNEL);
-       if (!tmdev)
+       if (!priv)
                return -ENOMEM;
 
-       tmdev->dev = dev;
-       tmdev->num_sensors = num_sensors;
-       tmdev->ops = data->ops;
-       for (i = 0;  i < tmdev->num_sensors; i++) {
+       priv->dev = dev;
+       priv->num_sensors = num_sensors;
+       priv->ops = data->ops;
+       for (i = 0;  i < priv->num_sensors; i++) {
                if (data->hw_ids)
-                       tmdev->sensor[i].hw_id = data->hw_ids[i];
+                       priv->sensor[i].hw_id = data->hw_ids[i];
                else
-                       tmdev->sensor[i].hw_id = i;
-       }
-       for (i = 0; i < REG_ARRAY_SIZE; i++) {
-               tmdev->reg_offsets[i] = data->reg_offsets[i];
+                       priv->sensor[i].hw_id = i;
        }
+       priv->feat = data->feat;
+       priv->fields = data->fields;
 
-       if (!tmdev->ops || !tmdev->ops->init || !tmdev->ops->get_temp)
+       if (!priv->ops || !priv->ops->init || !priv->ops->get_temp)
                return -EINVAL;
 
-       ret = tmdev->ops->init(tmdev);
+       ret = priv->ops->init(priv);
        if (ret < 0) {
                dev_err(dev, "tsens init failed\n");
                return ret;
        }
 
-       if (tmdev->ops->calibrate) {
-               ret = tmdev->ops->calibrate(tmdev);
+       if (priv->ops->calibrate) {
+               ret = priv->ops->calibrate(priv);
                if (ret < 0) {
-                       dev_err(dev, "tsens calibration failed\n");
+                       if (ret != -EPROBE_DEFER)
+                               dev_err(dev, "tsens calibration failed\n");
                        return ret;
                }
        }
 
-       ret = tsens_register(tmdev);
+       ret = tsens_register(priv);
 
-       platform_set_drvdata(pdev, tmdev);
+       platform_set_drvdata(pdev, priv);
 
        return ret;
 }
 
 static int tsens_remove(struct platform_device *pdev)
 {
-       struct tsens_device *tmdev = platform_get_drvdata(pdev);
+       struct tsens_priv *priv = platform_get_drvdata(pdev);
 
-       if (tmdev->ops->disable)
-               tmdev->ops->disable(tmdev);
+       if (priv->ops->disable)
+               priv->ops->disable(priv);
 
        return 0;
 }
index 7b7feee..eefe384 100644 (file)
@@ -9,17 +9,39 @@
 #define ONE_PT_CALIB           0x1
 #define ONE_PT_CALIB2          0x2
 #define TWO_PT_CALIB           0x3
+#define CAL_DEGC_PT1           30
+#define CAL_DEGC_PT2           120
+#define SLOPE_FACTOR           1000
+#define SLOPE_DEFAULT          3200
+
 
 #include <linux/thermal.h>
+#include <linux/regmap.h>
+
+struct tsens_priv;
 
-struct tsens_device;
+enum tsens_ver {
+       VER_0_1 = 0,
+       VER_1_X,
+       VER_2_X,
+};
 
+/**
+ * struct tsens_sensor - data for each sensor connected to the tsens device
+ * @priv: tsens device instance that this sensor is connected to
+ * @tzd: pointer to the thermal zone that this sensor is in
+ * @offset: offset of temperature adjustment curve
+ * @id: Sensor ID
+ * @hw_id: HW ID can be used in case of platform-specific IDs
+ * @slope: slope of temperature adjustment curve
+ * @status: 8960-specific variable to track 8960 and 8660 status register offset
+ */
 struct tsens_sensor {
-       struct tsens_device             *tmdev;
+       struct tsens_priv               *priv;
        struct thermal_zone_device      *tzd;
        int                             offset;
-       int                             id;
-       int                             hw_id;
+       unsigned int                    id;
+       unsigned int                    hw_id;
        int                             slope;
        u32                             status;
 };
@@ -37,63 +59,274 @@ struct tsens_sensor {
  */
 struct tsens_ops {
        /* mandatory callbacks */
-       int (*init)(struct tsens_device *);
-       int (*calibrate)(struct tsens_device *);
-       int (*get_temp)(struct tsens_device *, int, int *);
+       int (*init)(struct tsens_priv *priv);
+       int (*calibrate)(struct tsens_priv *priv);
+       int (*get_temp)(struct tsens_priv *priv, int i, int *temp);
        /* optional callbacks */
-       int (*enable)(struct tsens_device *, int);
-       void (*disable)(struct tsens_device *);
-       int (*suspend)(struct tsens_device *);
-       int (*resume)(struct tsens_device *);
-       int (*get_trend)(struct tsens_device *, int, enum thermal_trend *);
+       int (*enable)(struct tsens_priv *priv, int i);
+       void (*disable)(struct tsens_priv *priv);
+       int (*suspend)(struct tsens_priv *priv);
+       int (*resume)(struct tsens_priv *priv);
+       int (*get_trend)(struct tsens_priv *priv, int i, enum thermal_trend *trend);
 };
 
-enum reg_list {
-       SROT_CTRL_OFFSET,
+#define REG_FIELD_FOR_EACH_SENSOR11(_name, _offset, _startbit, _stopbit) \
+       [_name##_##0]  = REG_FIELD(_offset,      _startbit, _stopbit),  \
+       [_name##_##1]  = REG_FIELD(_offset +  4, _startbit, _stopbit), \
+       [_name##_##2]  = REG_FIELD(_offset +  8, _startbit, _stopbit), \
+       [_name##_##3]  = REG_FIELD(_offset + 12, _startbit, _stopbit), \
+       [_name##_##4]  = REG_FIELD(_offset + 16, _startbit, _stopbit), \
+       [_name##_##5]  = REG_FIELD(_offset + 20, _startbit, _stopbit), \
+       [_name##_##6]  = REG_FIELD(_offset + 24, _startbit, _stopbit), \
+       [_name##_##7]  = REG_FIELD(_offset + 28, _startbit, _stopbit), \
+       [_name##_##8]  = REG_FIELD(_offset + 32, _startbit, _stopbit), \
+       [_name##_##9]  = REG_FIELD(_offset + 36, _startbit, _stopbit), \
+       [_name##_##10] = REG_FIELD(_offset + 40, _startbit, _stopbit)
 
-       REG_ARRAY_SIZE,
+#define REG_FIELD_FOR_EACH_SENSOR16(_name, _offset, _startbit, _stopbit) \
+       [_name##_##0]  = REG_FIELD(_offset,      _startbit, _stopbit),  \
+       [_name##_##1]  = REG_FIELD(_offset +  4, _startbit, _stopbit), \
+       [_name##_##2]  = REG_FIELD(_offset +  8, _startbit, _stopbit), \
+       [_name##_##3]  = REG_FIELD(_offset + 12, _startbit, _stopbit), \
+       [_name##_##4]  = REG_FIELD(_offset + 16, _startbit, _stopbit), \
+       [_name##_##5]  = REG_FIELD(_offset + 20, _startbit, _stopbit), \
+       [_name##_##6]  = REG_FIELD(_offset + 24, _startbit, _stopbit), \
+       [_name##_##7]  = REG_FIELD(_offset + 28, _startbit, _stopbit), \
+       [_name##_##8]  = REG_FIELD(_offset + 32, _startbit, _stopbit), \
+       [_name##_##9]  = REG_FIELD(_offset + 36, _startbit, _stopbit), \
+       [_name##_##10] = REG_FIELD(_offset + 40, _startbit, _stopbit), \
+       [_name##_##11] = REG_FIELD(_offset + 44, _startbit, _stopbit), \
+       [_name##_##12] = REG_FIELD(_offset + 48, _startbit, _stopbit), \
+       [_name##_##13] = REG_FIELD(_offset + 52, _startbit, _stopbit), \
+       [_name##_##14] = REG_FIELD(_offset + 56, _startbit, _stopbit), \
+       [_name##_##15] = REG_FIELD(_offset + 60, _startbit, _stopbit)
+
+/* reg_field IDs to use as an index into an array */
+enum regfield_ids {
+       /* ----- SROT ------ */
+       /* HW_VER */
+       VER_MAJOR = 0,
+       VER_MINOR,
+       VER_STEP,
+       /* CTRL_OFFSET */
+       TSENS_EN =  3,
+       TSENS_SW_RST,
+       SENSOR_EN,
+       CODE_OR_TEMP,
+
+       /* ----- TM ------ */
+       /* STATUS */
+       LAST_TEMP_0 = 7,        /* Last temperature reading */
+       LAST_TEMP_1,
+       LAST_TEMP_2,
+       LAST_TEMP_3,
+       LAST_TEMP_4,
+       LAST_TEMP_5,
+       LAST_TEMP_6,
+       LAST_TEMP_7,
+       LAST_TEMP_8,
+       LAST_TEMP_9,
+       LAST_TEMP_10,
+       LAST_TEMP_11,
+       LAST_TEMP_12,
+       LAST_TEMP_13,
+       LAST_TEMP_14,
+       LAST_TEMP_15,
+       VALID_0 = 23,           /* VALID reading or not */
+       VALID_1,
+       VALID_2,
+       VALID_3,
+       VALID_4,
+       VALID_5,
+       VALID_6,
+       VALID_7,
+       VALID_8,
+       VALID_9,
+       VALID_10,
+       VALID_11,
+       VALID_12,
+       VALID_13,
+       VALID_14,
+       VALID_15,
+       MIN_STATUS_0,           /* MIN threshold violated */
+       MIN_STATUS_1,
+       MIN_STATUS_2,
+       MIN_STATUS_3,
+       MIN_STATUS_4,
+       MIN_STATUS_5,
+       MIN_STATUS_6,
+       MIN_STATUS_7,
+       MIN_STATUS_8,
+       MIN_STATUS_9,
+       MIN_STATUS_10,
+       MIN_STATUS_11,
+       MIN_STATUS_12,
+       MIN_STATUS_13,
+       MIN_STATUS_14,
+       MIN_STATUS_15,
+       MAX_STATUS_0,           /* MAX threshold violated */
+       MAX_STATUS_1,
+       MAX_STATUS_2,
+       MAX_STATUS_3,
+       MAX_STATUS_4,
+       MAX_STATUS_5,
+       MAX_STATUS_6,
+       MAX_STATUS_7,
+       MAX_STATUS_8,
+       MAX_STATUS_9,
+       MAX_STATUS_10,
+       MAX_STATUS_11,
+       MAX_STATUS_12,
+       MAX_STATUS_13,
+       MAX_STATUS_14,
+       MAX_STATUS_15,
+       LOWER_STATUS_0, /* LOWER threshold violated */
+       LOWER_STATUS_1,
+       LOWER_STATUS_2,
+       LOWER_STATUS_3,
+       LOWER_STATUS_4,
+       LOWER_STATUS_5,
+       LOWER_STATUS_6,
+       LOWER_STATUS_7,
+       LOWER_STATUS_8,
+       LOWER_STATUS_9,
+       LOWER_STATUS_10,
+       LOWER_STATUS_11,
+       LOWER_STATUS_12,
+       LOWER_STATUS_13,
+       LOWER_STATUS_14,
+       LOWER_STATUS_15,
+       UPPER_STATUS_0, /* UPPER threshold violated */
+       UPPER_STATUS_1,
+       UPPER_STATUS_2,
+       UPPER_STATUS_3,
+       UPPER_STATUS_4,
+       UPPER_STATUS_5,
+       UPPER_STATUS_6,
+       UPPER_STATUS_7,
+       UPPER_STATUS_8,
+       UPPER_STATUS_9,
+       UPPER_STATUS_10,
+       UPPER_STATUS_11,
+       UPPER_STATUS_12,
+       UPPER_STATUS_13,
+       UPPER_STATUS_14,
+       UPPER_STATUS_15,
+       CRITICAL_STATUS_0,      /* CRITICAL threshold violated */
+       CRITICAL_STATUS_1,
+       CRITICAL_STATUS_2,
+       CRITICAL_STATUS_3,
+       CRITICAL_STATUS_4,
+       CRITICAL_STATUS_5,
+       CRITICAL_STATUS_6,
+       CRITICAL_STATUS_7,
+       CRITICAL_STATUS_8,
+       CRITICAL_STATUS_9,
+       CRITICAL_STATUS_10,
+       CRITICAL_STATUS_11,
+       CRITICAL_STATUS_12,
+       CRITICAL_STATUS_13,
+       CRITICAL_STATUS_14,
+       CRITICAL_STATUS_15,
+       /* TRDY */
+       TRDY,
+       /* INTERRUPT ENABLE */
+       INT_EN, /* Pre-V1, V1.x */
+       LOW_INT_EN,     /* V2.x */
+       UP_INT_EN,      /* V2.x */
+       CRIT_INT_EN,    /* V2.x */
+
+       /* Keep last */
+       MAX_REGFIELDS
 };
 
 /**
- * struct tsens_data - tsens instance specific data
- * @num_sensors: Max number of sensors supported by platform
+ * struct tsens_features - Features supported by the IP
+ * @ver_major: Major number of IP version
+ * @crit_int: does the IP support critical interrupts?
+ * @adc:      do the sensors only output adc code (instead of temperature)?
+ * @srot_split: does the IP neatly splits the register space into SROT and TM,
+ *              with SROT only being available to secure boot firmware?
+ * @max_sensors: maximum sensors supported by this version of the IP
+ */
+struct tsens_features {
+       unsigned int ver_major;
+       unsigned int crit_int:1;
+       unsigned int adc:1;
+       unsigned int srot_split:1;
+       unsigned int max_sensors;
+};
+
+/**
+ * struct tsens_plat_data - tsens compile-time platform data
+ * @num_sensors: Number of sensors supported by platform
  * @ops: operations the tsens instance supports
  * @hw_ids: Subset of sensors ids supported by platform, if not the first n
- * @reg_offsets: Register offsets for commonly used registers
+ * @feat: features of the IP
+ * @fields: bitfield locations
  */
-struct tsens_data {
+struct tsens_plat_data {
        const u32               num_sensors;
        const struct tsens_ops  *ops;
-       const u16               reg_offsets[REG_ARRAY_SIZE];
        unsigned int            *hw_ids;
+       const struct tsens_features     *feat;
+       const struct reg_field          *fields;
 };
 
-/* Registers to be saved/restored across a context loss */
+/**
+ * struct tsens_context - Registers to be saved/restored across a context loss
+ */
 struct tsens_context {
        int     threshold;
        int     control;
 };
 
-struct tsens_device {
+/**
+ * struct tsens_priv - private data for each instance of the tsens IP
+ * @dev: pointer to struct device
+ * @num_sensors: number of sensors enabled on this device
+ * @tm_map: pointer to TM register address space
+ * @srot_map: pointer to SROT register address space
+ * @tm_offset: deal with old device trees that don't address TM and SROT
+ *             address space separately
+ * @rf: array of regmap_fields used to store value of the field
+ * @ctx: registers to be saved and restored during suspend/resume
+ * @feat: features of the IP
+ * @fields: bitfield locations
+ * @ops: pointer to list of callbacks supported by this device
+ * @sensor: list of sensors attached to this device
+ */
+struct tsens_priv {
        struct device                   *dev;
        u32                             num_sensors;
        struct regmap                   *tm_map;
        struct regmap                   *srot_map;
        u32                             tm_offset;
-       u16                             reg_offsets[REG_ARRAY_SIZE];
+       struct regmap_field             *rf[MAX_REGFIELDS];
        struct tsens_context            ctx;
+       const struct tsens_features     *feat;
+       const struct reg_field          *fields;
        const struct tsens_ops          *ops;
        struct tsens_sensor             sensor[0];
 };
 
-char *qfprom_read(struct device *, const char *);
-void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
-int init_common(struct tsens_device *);
-int get_temp_common(struct tsens_device *, int, int *);
+char *qfprom_read(struct device *dev, const char *cname);
+void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mode);
+int init_common(struct tsens_priv *priv);
+int get_temp_tsens_valid(struct tsens_priv *priv, int i, int *temp);
+int get_temp_common(struct tsens_priv *priv, int i, int *temp);
+bool is_sensor_enabled(struct tsens_priv *priv, u32 hw_id);
+
+/* TSENS target */
+extern const struct tsens_plat_data data_8960;
+
+/* TSENS v0.1 targets */
+extern const struct tsens_plat_data data_8916, data_8974;
 
 /* TSENS v1 targets */
-extern const struct tsens_data data_8916, data_8974, data_8960;
+extern const struct tsens_plat_data data_tsens_v1;
+
 /* TSENS v2 targets */
-extern const struct tsens_data data_8996, data_tsens_v2;
+extern const struct tsens_plat_data data_8996, data_tsens_v2;
 
 #endif /* __QCOM_TSENS_H__ */
index 3b5f5b3..7b36493 100644 (file)
@@ -193,11 +193,6 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
        struct qoriq_tmu_data *data;
        struct device_node *np = pdev->dev.of_node;
 
-       if (!np) {
-               dev_err(&pdev->dev, "Device OF-Node is NULL");
-               return -ENODEV;
-       }
-
        data = devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data),
                            GFP_KERNEL);
        if (!data)
index 88fa41c..83f3062 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
-#include <linux/spinlock.h>
 #include <linux/sys_soc.h>
 #include <linux/thermal.h>
 
@@ -82,7 +81,6 @@ struct rcar_gen3_thermal_tsc {
 struct rcar_gen3_thermal_priv {
        struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM];
        unsigned int num_tscs;
-       spinlock_t lock; /* Protect interrupts on and off */
        void (*thermal_init)(struct rcar_gen3_thermal_tsc *tsc);
 };
 
@@ -232,38 +230,16 @@ static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data)
 {
        struct rcar_gen3_thermal_priv *priv = data;
        u32 status;
-       int i, ret = IRQ_HANDLED;
+       int i;
 
-       spin_lock(&priv->lock);
        for (i = 0; i < priv->num_tscs; i++) {
                status = rcar_gen3_thermal_read(priv->tscs[i], REG_GEN3_IRQSTR);
                rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQSTR, 0);
                if (status)
-                       ret = IRQ_WAKE_THREAD;
+                       thermal_zone_device_update(priv->tscs[i]->zone,
+                                                  THERMAL_EVENT_UNSPECIFIED);
        }
 
-       if (ret == IRQ_WAKE_THREAD)
-               rcar_thermal_irq_set(priv, false);
-
-       spin_unlock(&priv->lock);
-
-       return ret;
-}
-
-static irqreturn_t rcar_gen3_thermal_irq_thread(int irq, void *data)
-{
-       struct rcar_gen3_thermal_priv *priv = data;
-       unsigned long flags;
-       int i;
-
-       for (i = 0; i < priv->num_tscs; i++)
-               thermal_zone_device_update(priv->tscs[i]->zone,
-                                          THERMAL_EVENT_UNSPECIFIED);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       rcar_thermal_irq_set(priv, true);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
        return IRQ_HANDLED;
 }
 
@@ -307,7 +283,7 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
 
        usleep_range(1000, 2000);
 
-       rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F);
+       rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0);
        rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0);
        rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, IRQ_TEMPD1 | IRQ_TEMP2);
 
@@ -331,6 +307,9 @@ MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids);
 static int rcar_gen3_thermal_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
+       struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev);
+
+       rcar_thermal_irq_set(priv, false);
 
        pm_runtime_put(dev);
        pm_runtime_disable(dev);
@@ -371,8 +350,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
        if (soc_device_match(r8a7795es1))
                priv->thermal_init = rcar_gen3_thermal_init_r8a7795es1;
 
-       spin_lock_init(&priv->lock);
-
        platform_set_drvdata(pdev, priv);
 
        /*
@@ -390,9 +367,9 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
                if (!irqname)
                        return -ENOMEM;
 
-               ret = devm_request_threaded_irq(dev, irq, rcar_gen3_thermal_irq,
-                                               rcar_gen3_thermal_irq_thread,
-                                               IRQF_SHARED, irqname, priv);
+               ret = devm_request_threaded_irq(dev, irq, NULL,
+                                               rcar_gen3_thermal_irq,
+                                               IRQF_ONESHOT, irqname, priv);
                if (ret)
                        return ret;
        }
@@ -433,10 +410,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
                }
                tsc->zone = zone;
 
-               ret = of_thermal_get_ntrips(tsc->zone);
-               if (ret < 0)
-                       goto error_unregister;
-
                tsc->zone->tzp->no_hwmon = false;
                ret = thermal_add_hwmon_sysfs(tsc->zone);
                if (ret)
@@ -448,6 +421,10 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
                        goto error_unregister;
                }
 
+               ret = of_thermal_get_ntrips(tsc->zone);
+               if (ret < 0)
+                       goto error_unregister;
+
                dev_info(dev, "TSC%d: Loaded %d trip points\n", i, ret);
        }
 
index 97462e9..d0873de 100644 (file)
@@ -52,6 +52,7 @@ struct rcar_thermal_chip {
        unsigned int irq_per_ch : 1;
        unsigned int needs_suspend_resume : 1;
        unsigned int nirqs;
+       unsigned int ctemp_bands;
 };
 
 static const struct rcar_thermal_chip rcar_thermal = {
@@ -60,6 +61,7 @@ static const struct rcar_thermal_chip rcar_thermal = {
        .irq_per_ch = 0,
        .needs_suspend_resume = 0,
        .nirqs = 1,
+       .ctemp_bands = 1,
 };
 
 static const struct rcar_thermal_chip rcar_gen2_thermal = {
@@ -68,6 +70,7 @@ static const struct rcar_thermal_chip rcar_gen2_thermal = {
        .irq_per_ch = 0,
        .needs_suspend_resume = 0,
        .nirqs = 1,
+       .ctemp_bands = 1,
 };
 
 static const struct rcar_thermal_chip rcar_gen3_thermal = {
@@ -80,6 +83,7 @@ static const struct rcar_thermal_chip rcar_gen3_thermal = {
         * interrupts to detect a temperature change, rise or fall.
         */
        .nirqs = 2,
+       .ctemp_bands = 2,
 };
 
 struct rcar_thermal_priv {
@@ -263,7 +267,12 @@ static int rcar_thermal_get_current_temp(struct rcar_thermal_priv *priv,
                return ret;
 
        mutex_lock(&priv->lock);
-       tmp =  MCELSIUS((priv->ctemp * 5) - 65);
+       if (priv->chip->ctemp_bands == 1)
+               tmp = MCELSIUS((priv->ctemp * 5) - 65);
+       else if (priv->ctemp < 24)
+               tmp = MCELSIUS(((priv->ctemp * 55) - 720) / 10);
+       else
+               tmp = MCELSIUS((priv->ctemp * 5) - 60);
        mutex_unlock(&priv->lock);
 
        if ((tmp < MCELSIUS(-45)) || (tmp > MCELSIUS(125))) {
index 9c7643d..bda1ca1 100644 (file)
@@ -172,6 +172,9 @@ struct rockchip_thermal_data {
        int tshut_temp;
        enum tshut_mode tshut_mode;
        enum tshut_polarity tshut_polarity;
+       struct pinctrl *pinctrl;
+       struct pinctrl_state *gpio_state;
+       struct pinctrl_state *otp_state;
 };
 
 /**
@@ -222,11 +225,15 @@ struct rockchip_thermal_data {
 #define GRF_TSADC_TESTBIT_L                    0x0e648
 #define GRF_TSADC_TESTBIT_H                    0x0e64c
 
+#define PX30_GRF_SOC_CON2                      0x0408
+
 #define GRF_SARADC_TESTBIT_ON                  (0x10001 << 2)
 #define GRF_TSADC_TESTBIT_H_ON                 (0x10001 << 2)
 #define GRF_TSADC_VCM_EN_L                     (0x10001 << 7)
 #define GRF_TSADC_VCM_EN_H                     (0x10001 << 7)
 
+#define GRF_CON_TSADC_CH_INV                   (0x10001 << 1)
+
 /**
  * struct tsadc_table - code to temperature conversion table
  * @code: the value of adc channel
@@ -689,6 +696,13 @@ static void rk_tsadcv3_initialize(struct regmap *grf, void __iomem *regs,
                               regs + TSADCV2_AUTO_CON);
 }
 
+static void rk_tsadcv4_initialize(struct regmap *grf, void __iomem *regs,
+                                 enum tshut_polarity tshut_polarity)
+{
+       rk_tsadcv2_initialize(grf, regs, tshut_polarity);
+       regmap_write(grf, PX30_GRF_SOC_CON2, GRF_CON_TSADC_CH_INV);
+}
+
 static void rk_tsadcv2_irq_ack(void __iomem *regs)
 {
        u32 val;
@@ -818,6 +832,30 @@ static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs,
        writel_relaxed(val, regs + TSADCV2_INT_EN);
 }
 
+static const struct rockchip_tsadc_chip px30_tsadc_data = {
+       .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
+       .chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */
+       .chn_num = 2, /* 2 channels for tsadc */
+
+       .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */
+       .tshut_temp = 95000,
+
+       .initialize = rk_tsadcv4_initialize,
+       .irq_ack = rk_tsadcv3_irq_ack,
+       .control = rk_tsadcv3_control,
+       .get_temp = rk_tsadcv2_get_temp,
+       .set_alarm_temp = rk_tsadcv2_alarm_temp,
+       .set_tshut_temp = rk_tsadcv2_tshut_temp,
+       .set_tshut_mode = rk_tsadcv2_tshut_mode,
+
+       .table = {
+               .id = rk3328_code_table,
+               .length = ARRAY_SIZE(rk3328_code_table),
+               .data_mask = TSADCV2_DATA_MASK,
+               .mode = ADC_INCREMENT,
+       },
+};
+
 static const struct rockchip_tsadc_chip rv1108_tsadc_data = {
        .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
        .chn_num = 1, /* one channel for tsadc */
@@ -990,6 +1028,9 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
 };
 
 static const struct of_device_id of_rockchip_thermal_match[] = {
+       {       .compatible = "rockchip,px30-tsadc",
+               .data = (void *)&px30_tsadc_data,
+       },
        {
                .compatible = "rockchip,rv1108-tsadc",
                .data = (void *)&rv1108_tsadc_data,
@@ -1242,6 +1283,8 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
                return error;
        }
 
+       thermal->chip->control(thermal->regs, false);
+
        error = clk_prepare_enable(thermal->clk);
        if (error) {
                dev_err(&pdev->dev, "failed to enable converter clock: %d\n",
@@ -1267,6 +1310,30 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
        thermal->chip->initialize(thermal->grf, thermal->regs,
                                  thermal->tshut_polarity);
 
+       if (thermal->tshut_mode == TSHUT_MODE_GPIO) {
+               thermal->pinctrl = devm_pinctrl_get(&pdev->dev);
+               if (IS_ERR(thermal->pinctrl)) {
+                       dev_err(&pdev->dev, "failed to find thermal pinctrl\n");
+                       return PTR_ERR(thermal->pinctrl);
+               }
+
+               thermal->gpio_state = pinctrl_lookup_state(thermal->pinctrl,
+                                                          "gpio");
+               if (IS_ERR_OR_NULL(thermal->gpio_state)) {
+                       dev_err(&pdev->dev, "failed to find thermal gpio state\n");
+                       return -EINVAL;
+               }
+
+               thermal->otp_state = pinctrl_lookup_state(thermal->pinctrl,
+                                                         "otpout");
+               if (IS_ERR_OR_NULL(thermal->otp_state)) {
+                       dev_err(&pdev->dev, "failed to find thermal otpout state\n");
+                       return -EINVAL;
+               }
+
+               pinctrl_select_state(thermal->pinctrl, thermal->otp_state);
+       }
+
        for (i = 0; i < thermal->chip->chn_num; i++) {
                error = rockchip_thermal_register_sensor(pdev, thermal,
                                                &thermal->sensors[i],
@@ -1337,8 +1404,8 @@ static int __maybe_unused rockchip_thermal_suspend(struct device *dev)
 
        clk_disable(thermal->pclk);
        clk_disable(thermal->clk);
-
-       pinctrl_pm_select_sleep_state(dev);
+       if (thermal->tshut_mode == TSHUT_MODE_GPIO)
+               pinctrl_select_state(thermal->pinctrl, thermal->gpio_state);
 
        return 0;
 }
@@ -1383,7 +1450,8 @@ static int __maybe_unused rockchip_thermal_resume(struct device *dev)
        for (i = 0; i < thermal->chip->chn_num; i++)
                rockchip_thermal_toggle_sensor(&thermal->sensors[i], true);
 
-       pinctrl_pm_select_default_state(dev);
+       if (thermal->tshut_mode == TSHUT_MODE_GPIO)
+               pinctrl_select_state(thermal->pinctrl, thermal->otp_state);
 
        return 0;
 }
index b80f9a9..d8b1a45 100644 (file)
@@ -3,9 +3,9 @@
 #
 
 config ST_THERMAL
-       tristate "Thermal sensors on STMicroelectronics STi series of SoCs"
-       help
-         Support for thermal sensors on STMicroelectronics STi series of SoCs.
+       tristate "Thermal sensors on STMicroelectronics STi series of SoCs"
+       help
+         Support for thermal sensors on STMicroelectronics STi series of SoCs.
 
 config ST_THERMAL_SYSCFG
        select ST_THERMAL
@@ -16,11 +16,11 @@ config ST_THERMAL_MEMMAP
        tristate "STi series memory mapped access based thermal sensors"
 
 config STM32_THERMAL
-       tristate "Thermal framework support on STMicroelectronics STM32 series of SoCs"
-       depends on MACH_STM32MP157
-       default y
-       help
-       Support for thermal framework on STMicroelectronics STM32 series of
-       SoCs. This thermal driver allows to access to general thermal framework
-       functionalities and to acces to SoC sensor functionalities. This
-       configuration is fully dependent of MACH_STM32MP157.
+       tristate "Thermal framework support on STMicroelectronics STM32 series of SoCs"
+       depends on MACH_STM32MP157
+       default y
+       help
+         Support for thermal framework on STMicroelectronics STM32 series of
+         SoCs. This thermal driver allows to access to general thermal framework
+         functionalities and to acces to SoC sensor functionalities. This
+         configuration is fully dependent of MACH_STM32MP157.
index bbd73c5..cf9ddc5 100644 (file)
@@ -570,8 +570,7 @@ thermal_unprepare:
 static int stm_thermal_suspend(struct device *dev)
 {
        int ret;
-       struct platform_device *pdev = to_platform_device(dev);
-       struct stm_thermal_sensor *sensor = platform_get_drvdata(pdev);
+       struct stm_thermal_sensor *sensor = dev_get_drvdata(dev);
 
        ret = stm_thermal_sensor_off(sensor);
        if (ret)
@@ -585,8 +584,7 @@ static int stm_thermal_suspend(struct device *dev)
 static int stm_thermal_resume(struct device *dev)
 {
        int ret;
-       struct platform_device *pdev = to_platform_device(dev);
-       struct stm_thermal_sensor *sensor = platform_get_drvdata(pdev);
+       struct stm_thermal_sensor *sensor = dev_get_drvdata(dev);
 
        ret = stm_thermal_prepare(sensor);
        if (ret)
index f8740f7..fc0b33b 100644 (file)
@@ -14,7 +14,7 @@ config TEGRA_BPMP_THERMAL
        tristate "Tegra BPMP thermal sensing"
        depends on TEGRA_BPMP || COMPILE_TEST
        help
-        Enable this option for support for sensing system temperature of NVIDIA
-        Tegra systems-on-chip with the BPMP coprocessor (Tegra186).
+         Enable this option for support for sensing system temperature of NVIDIA
+         Tegra systems-on-chip with the BPMP coprocessor (Tegra186).
 
 endmenu
index 70043a2..fcf70a3 100644 (file)
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014 - 2018, NVIDIA CORPORATION.  All rights reserved.
  *
  * Author:
  *     Mikko Perttunen <mperttunen@nvidia.com>
@@ -22,6 +23,8 @@
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #define THERMCTL_LVL0_UP_STATS                 0x10
 #define THERMCTL_LVL0_DN_STATS                 0x14
 
+#define THERMCTL_INTR_STATUS                   0x84
+
+#define TH_INTR_MD0_MASK                       BIT(25)
+#define TH_INTR_MU0_MASK                       BIT(24)
+#define TH_INTR_GD0_MASK                       BIT(17)
+#define TH_INTR_GU0_MASK                       BIT(16)
+#define TH_INTR_CD0_MASK                       BIT(9)
+#define TH_INTR_CU0_MASK                       BIT(8)
+#define TH_INTR_PD0_MASK                       BIT(1)
+#define TH_INTR_PU0_MASK                       BIT(0)
+#define TH_INTR_IGNORE_MASK                    0xFCFCFCFC
+
 #define THERMCTL_STATS_CTL                     0x94
 #define STATS_CTL_CLR_DN                       0x8
 #define STATS_CTL_EN_DN                                0x4
 #define STATS_CTL_CLR_UP                       0x2
 #define STATS_CTL_EN_UP                                0x1
 
+#define OC1_CFG                                        0x310
+#define OC1_CFG_LONG_LATENCY_MASK              BIT(6)
+#define OC1_CFG_HW_RESTORE_MASK                        BIT(5)
+#define OC1_CFG_PWR_GOOD_MASK_MASK             BIT(4)
+#define OC1_CFG_THROTTLE_MODE_MASK             (0x3 << 2)
+#define OC1_CFG_ALARM_POLARITY_MASK            BIT(1)
+#define OC1_CFG_EN_THROTTLE_MASK               BIT(0)
+
+#define OC1_CNT_THRESHOLD                      0x314
+#define OC1_THROTTLE_PERIOD                    0x318
+#define OC1_ALARM_COUNT                                0x31c
+#define OC1_FILTER                             0x320
+#define OC1_STATS                              0x3a8
+
+#define OC_INTR_STATUS                         0x39c
+#define OC_INTR_ENABLE                         0x3a0
+#define OC_INTR_DISABLE                                0x3a4
+#define OC_STATS_CTL                           0x3c4
+#define OC_STATS_CTL_CLR_ALL                   0x2
+#define OC_STATS_CTL_EN_ALL                    0x1
+
+#define OC_INTR_OC1_MASK                       BIT(0)
+#define OC_INTR_OC2_MASK                       BIT(1)
+#define OC_INTR_OC3_MASK                       BIT(2)
+#define OC_INTR_OC4_MASK                       BIT(3)
+#define OC_INTR_OC5_MASK                       BIT(4)
+
 #define THROT_GLOBAL_CFG                       0x400
 #define THROT_GLOBAL_ENB_MASK                  BIT(0)
 
 /* get dividend from the depth */
 #define THROT_DEPTH_DIVIDEND(depth)    ((256 * (100 - (depth)) / 100) - 1)
 
+/* gk20a nv_therm interface N:3 Mapping. Levels defined in tegra124-sochterm.h
+ * level       vector
+ * NONE                3'b000
+ * LOW         3'b001
+ * MED         3'b011
+ * HIGH                3'b111
+ */
+#define THROT_LEVEL_TO_DEPTH(level)    ((0x1 << (level)) - 1)
+
 /* get THROT_PSKIP_xxx offset per LIGHT/HEAVY throt and CPU/GPU dev */
 #define THROT_OFFSET                   0x30
 #define THROT_PSKIP_CTRL(throt, dev)   (THROT_PSKIP_CTRL_LITE_CPU + \
 #define THROT_DELAY_CTRL(throt)                (THROT_DELAY_LITE + \
                                        (THROT_OFFSET * throt))
 
+#define ALARM_OFFSET                   0x14
+#define ALARM_CFG(throt)               (OC1_CFG + \
+                                       (ALARM_OFFSET * (throt - THROTTLE_OC1)))
+
+#define ALARM_CNT_THRESHOLD(throt)     (OC1_CNT_THRESHOLD + \
+                                       (ALARM_OFFSET * (throt - THROTTLE_OC1)))
+
+#define ALARM_THROTTLE_PERIOD(throt)   (OC1_THROTTLE_PERIOD + \
+                                       (ALARM_OFFSET * (throt - THROTTLE_OC1)))
+
+#define ALARM_ALARM_COUNT(throt)       (OC1_ALARM_COUNT + \
+                                       (ALARM_OFFSET * (throt - THROTTLE_OC1)))
+
+#define ALARM_FILTER(throt)            (OC1_FILTER + \
+                                       (ALARM_OFFSET * (throt - THROTTLE_OC1)))
+
+#define ALARM_STATS(throt)             (OC1_STATS + \
+                                       (4 * (throt - THROTTLE_OC1)))
+
 /* get CCROC_THROT_PSKIP_xxx offset per HIGH/MED/LOW vect*/
 #define CCROC_THROT_OFFSET                     0x0c
 #define CCROC_THROT_PSKIP_CTRL_CPU_REG(vect)    (CCROC_THROT_PSKIP_CTRL_CPU + \
 #define THERMCTL_LVL_REGS_SIZE         0x20
 #define THERMCTL_LVL_REG(rg, lv)       ((rg) + ((lv) * THERMCTL_LVL_REGS_SIZE))
 
+#define OC_THROTTLE_MODE_DISABLED      0
+#define OC_THROTTLE_MODE_BRIEF         2
+
 static const int min_low_temp = -127000;
 static const int max_high_temp = 127000;
 
 enum soctherm_throttle_id {
        THROTTLE_LIGHT = 0,
        THROTTLE_HEAVY,
+       THROTTLE_OC1,
+       THROTTLE_OC2,
+       THROTTLE_OC3,
+       THROTTLE_OC4,
+       THROTTLE_OC5, /* OC5 is reserved */
        THROTTLE_SIZE,
 };
 
+enum soctherm_oc_irq_id {
+       TEGRA_SOC_OC_IRQ_1,
+       TEGRA_SOC_OC_IRQ_2,
+       TEGRA_SOC_OC_IRQ_3,
+       TEGRA_SOC_OC_IRQ_4,
+       TEGRA_SOC_OC_IRQ_5,
+       TEGRA_SOC_OC_IRQ_MAX,
+};
+
 enum soctherm_throttle_dev_id {
        THROTTLE_DEV_CPU = 0,
        THROTTLE_DEV_GPU,
@@ -202,6 +289,11 @@ enum soctherm_throttle_dev_id {
 static const char *const throt_names[] = {
        [THROTTLE_LIGHT] = "light",
        [THROTTLE_HEAVY] = "heavy",
+       [THROTTLE_OC1]   = "oc1",
+       [THROTTLE_OC2]   = "oc2",
+       [THROTTLE_OC3]   = "oc3",
+       [THROTTLE_OC4]   = "oc4",
+       [THROTTLE_OC5]   = "oc5",
 };
 
 struct tegra_soctherm;
@@ -213,12 +305,23 @@ struct tegra_thermctl_zone {
        const struct tegra_tsensor_group *sg;
 };
 
+struct soctherm_oc_cfg {
+       u32 active_low;
+       u32 throt_period;
+       u32 alarm_cnt_thresh;
+       u32 alarm_filter;
+       u32 mode;
+       bool intr_en;
+};
+
 struct soctherm_throt_cfg {
        const char *name;
        unsigned int id;
        u8 priority;
        u8 cpu_throt_level;
        u32 cpu_throt_depth;
+       u32 gpu_throt_level;
+       struct soctherm_oc_cfg oc_cfg;
        struct thermal_cooling_device *cdev;
        bool init;
 };
@@ -231,6 +334,9 @@ struct tegra_soctherm {
        void __iomem *clk_regs;
        void __iomem *ccroc_regs;
 
+       int thermal_irq;
+       int edp_irq;
+
        u32 *calib;
        struct thermal_zone_device **thermctl_tzs;
        struct tegra_soctherm_soc *soc;
@@ -238,8 +344,19 @@ struct tegra_soctherm {
        struct soctherm_throt_cfg throt_cfgs[THROTTLE_SIZE];
 
        struct dentry *debugfs_dir;
+
+       struct mutex thermctl_lock;
 };
 
+struct soctherm_oc_irq_chip_data {
+       struct mutex            irq_lock; /* serialize OC IRQs */
+       struct irq_chip         irq_chip;
+       struct irq_domain       *domain;
+       int                     irq_enable;
+};
+
+static struct soctherm_oc_irq_chip_data soc_irq_cdata;
+
 /**
  * ccroc_writel() - writes a value to a CCROC register
  * @ts: pointer to a struct tegra_soctherm
@@ -446,6 +563,24 @@ find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name)
        return NULL;
 }
 
+static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id)
+{
+       int i, temp = min_low_temp;
+       struct tsensor_group_thermtrips *tt = ts->soc->thermtrips;
+
+       if (id >= TEGRA124_SOCTHERM_SENSOR_NUM)
+               return temp;
+
+       if (tt) {
+               for (i = 0; i < ts->soc->num_ttgs; i++) {
+                       if (tt[i].id == id)
+                               return tt[i].temp;
+               }
+       }
+
+       return temp;
+}
+
 static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp)
 {
        struct tegra_thermctl_zone *zone = data;
@@ -464,7 +599,16 @@ static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp)
                return ret;
 
        if (type == THERMAL_TRIP_CRITICAL) {
-               return thermtrip_program(dev, sg, temp);
+               /*
+                * If thermtrips property is set in DT,
+                * doesn't need to program critical type trip to HW,
+                * if not, program critical trip to HW.
+                */
+               if (min_low_temp == tsensor_group_thermtrip_get(ts, sg->id))
+                       return thermtrip_program(dev, sg, temp);
+               else
+                       return 0;
+
        } else if (type == THERMAL_TRIP_HOT) {
                int i;
 
@@ -519,10 +663,60 @@ static int tegra_thermctl_get_trend(void *data, int trip,
        return 0;
 }
 
+static void thermal_irq_enable(struct tegra_thermctl_zone *zn)
+{
+       u32 r;
+
+       /* multiple zones could be handling and setting trips at once */
+       mutex_lock(&zn->ts->thermctl_lock);
+       r = readl(zn->ts->regs + THERMCTL_INTR_ENABLE);
+       r = REG_SET_MASK(r, zn->sg->thermctl_isr_mask, TH_INTR_UP_DN_EN);
+       writel(r, zn->ts->regs + THERMCTL_INTR_ENABLE);
+       mutex_unlock(&zn->ts->thermctl_lock);
+}
+
+static void thermal_irq_disable(struct tegra_thermctl_zone *zn)
+{
+       u32 r;
+
+       /* multiple zones could be handling and setting trips at once */
+       mutex_lock(&zn->ts->thermctl_lock);
+       r = readl(zn->ts->regs + THERMCTL_INTR_DISABLE);
+       r = REG_SET_MASK(r, zn->sg->thermctl_isr_mask, 0);
+       writel(r, zn->ts->regs + THERMCTL_INTR_DISABLE);
+       mutex_unlock(&zn->ts->thermctl_lock);
+}
+
+static int tegra_thermctl_set_trips(void *data, int lo, int hi)
+{
+       struct tegra_thermctl_zone *zone = data;
+       u32 r;
+
+       thermal_irq_disable(zone);
+
+       r = readl(zone->ts->regs + zone->sg->thermctl_lvl0_offset);
+       r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 0);
+       writel(r, zone->ts->regs + zone->sg->thermctl_lvl0_offset);
+
+       lo = enforce_temp_range(zone->dev, lo) / zone->ts->soc->thresh_grain;
+       hi = enforce_temp_range(zone->dev, hi) / zone->ts->soc->thresh_grain;
+       dev_dbg(zone->dev, "%s hi:%d, lo:%d\n", __func__, hi, lo);
+
+       r = REG_SET_MASK(r, zone->sg->thermctl_lvl0_up_thresh_mask, hi);
+       r = REG_SET_MASK(r, zone->sg->thermctl_lvl0_dn_thresh_mask, lo);
+       r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 1);
+       writel(r, zone->ts->regs + zone->sg->thermctl_lvl0_offset);
+
+       thermal_irq_enable(zone);
+
+       return 0;
+}
+
 static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = {
        .get_temp = tegra_thermctl_get_temp,
        .set_trip_temp = tegra_thermctl_set_trip_temp,
        .get_trend = tegra_thermctl_get_trend,
+       .set_trips = tegra_thermctl_set_trips,
 };
 
 static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp)
@@ -555,7 +749,8 @@ static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp)
  * @dev: struct device * of the SOC_THERM instance
  *
  * Configure the SOC_THERM HW trip points, setting "THERMTRIP"
- * "THROTTLE" trip points , using "critical" or "hot" type trip_temp
+ * "THROTTLE" trip points , using "thermtrips", "critical" or "hot"
+ * type trip_temp
  * from thermal zone.
  * After they have been configured, THERMTRIP or THROTTLE will take
  * action when the configured SoC thermal sensor group reaches a
@@ -577,28 +772,23 @@ static int tegra_soctherm_set_hwtrips(struct device *dev,
 {
        struct tegra_soctherm *ts = dev_get_drvdata(dev);
        struct soctherm_throt_cfg *stc;
-       int i, trip, temperature;
-       int ret;
+       int i, trip, temperature, ret;
 
-       ret = tz->ops->get_crit_temp(tz, &temperature);
-       if (ret) {
-               dev_warn(dev, "thermtrip: %s: missing critical temperature\n",
-                        sg->name);
-               goto set_throttle;
-       }
+       /* Get thermtrips. If missing, try to get critical trips. */
+       temperature = tsensor_group_thermtrip_get(ts, sg->id);
+       if (min_low_temp == temperature)
+               if (tz->ops->get_crit_temp(tz, &temperature))
+                       temperature = max_high_temp;
 
        ret = thermtrip_program(dev, sg, temperature);
        if (ret) {
-               dev_err(dev, "thermtrip: %s: error during enable\n",
-                       sg->name);
+               dev_err(dev, "thermtrip: %s: error during enable\n", sg->name);
                return ret;
        }
 
-       dev_info(dev,
-                "thermtrip: will shut down when %s reaches %d mC\n",
+       dev_info(dev, "thermtrip: will shut down when %s reaches %d mC\n",
                 sg->name, temperature);
 
-set_throttle:
        ret = get_hot_temp(tz, &trip, &temperature);
        if (ret) {
                dev_info(dev, "throttrip: %s: missing hot temperature\n",
@@ -606,7 +796,7 @@ set_throttle:
                return 0;
        }
 
-       for (i = 0; i < THROTTLE_SIZE; i++) {
+       for (i = 0; i < THROTTLE_OC1; i++) {
                struct thermal_cooling_device *cdev;
 
                if (!ts->throt_cfgs[i].init)
@@ -638,6 +828,461 @@ set_throttle:
        return 0;
 }
 
+static irqreturn_t soctherm_thermal_isr(int irq, void *dev_id)
+{
+       struct tegra_soctherm *ts = dev_id;
+       u32 r;
+
+       /* Case for no lock:
+        * Although interrupts are enabled in set_trips, there is still no need
+        * to lock here because the interrupts are disabled before programming
+        * new trip points. Hence there cant be a interrupt on the same sensor.
+        * An interrupt can however occur on a sensor while trips are being
+        * programmed on a different one. This beign a LEVEL interrupt won't
+        * cause a new interrupt but this is taken care of by the re-reading of
+        * the STATUS register in the thread function.
+        */
+       r = readl(ts->regs + THERMCTL_INTR_STATUS);
+       writel(r, ts->regs + THERMCTL_INTR_DISABLE);
+
+       return IRQ_WAKE_THREAD;
+}
+
+/**
+ * soctherm_thermal_isr_thread() - Handles a thermal interrupt request
+ * @irq:       The interrupt number being requested; not used
+ * @dev_id:    Opaque pointer to tegra_soctherm;
+ *
+ * Clears the interrupt status register if there are expected
+ * interrupt bits set.
+ * The interrupt(s) are then handled by updating the corresponding
+ * thermal zones.
+ *
+ * An error is logged if any unexpected interrupt bits are set.
+ *
+ * Disabled interrupts are re-enabled.
+ *
+ * Return: %IRQ_HANDLED. Interrupt was handled and no further processing
+ * is needed.
+ */
+static irqreturn_t soctherm_thermal_isr_thread(int irq, void *dev_id)
+{
+       struct tegra_soctherm *ts = dev_id;
+       struct thermal_zone_device *tz;
+       u32 st, ex = 0, cp = 0, gp = 0, pl = 0, me = 0;
+
+       st = readl(ts->regs + THERMCTL_INTR_STATUS);
+
+       /* deliberately clear expected interrupts handled in SW */
+       cp |= st & TH_INTR_CD0_MASK;
+       cp |= st & TH_INTR_CU0_MASK;
+
+       gp |= st & TH_INTR_GD0_MASK;
+       gp |= st & TH_INTR_GU0_MASK;
+
+       pl |= st & TH_INTR_PD0_MASK;
+       pl |= st & TH_INTR_PU0_MASK;
+
+       me |= st & TH_INTR_MD0_MASK;
+       me |= st & TH_INTR_MU0_MASK;
+
+       ex |= cp | gp | pl | me;
+       if (ex) {
+               writel(ex, ts->regs + THERMCTL_INTR_STATUS);
+               st &= ~ex;
+
+               if (cp) {
+                       tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_CPU];
+                       thermal_zone_device_update(tz,
+                                                  THERMAL_EVENT_UNSPECIFIED);
+               }
+
+               if (gp) {
+                       tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_GPU];
+                       thermal_zone_device_update(tz,
+                                                  THERMAL_EVENT_UNSPECIFIED);
+               }
+
+               if (pl) {
+                       tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_PLLX];
+                       thermal_zone_device_update(tz,
+                                                  THERMAL_EVENT_UNSPECIFIED);
+               }
+
+               if (me) {
+                       tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_MEM];
+                       thermal_zone_device_update(tz,
+                                                  THERMAL_EVENT_UNSPECIFIED);
+               }
+       }
+
+       /* deliberately ignore expected interrupts NOT handled in SW */
+       ex |= TH_INTR_IGNORE_MASK;
+       st &= ~ex;
+
+       if (st) {
+               /* Whine about any other unexpected INTR bits still set */
+               pr_err("soctherm: Ignored unexpected INTRs 0x%08x\n", st);
+               writel(st, ts->regs + THERMCTL_INTR_STATUS);
+       }
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * soctherm_oc_intr_enable() - Enables the soctherm over-current interrupt
+ * @alarm:             The soctherm throttle id
+ * @enable:            Flag indicating enable the soctherm over-current
+ *                     interrupt or disable it
+ *
+ * Enables a specific over-current pins @alarm to raise an interrupt if the flag
+ * is set and the alarm corresponds to OC1, OC2, OC3, or OC4.
+ */
+static void soctherm_oc_intr_enable(struct tegra_soctherm *ts,
+                                   enum soctherm_throttle_id alarm,
+                                   bool enable)
+{
+       u32 r;
+
+       if (!enable)
+               return;
+
+       r = readl(ts->regs + OC_INTR_ENABLE);
+       switch (alarm) {
+       case THROTTLE_OC1:
+               r = REG_SET_MASK(r, OC_INTR_OC1_MASK, 1);
+               break;
+       case THROTTLE_OC2:
+               r = REG_SET_MASK(r, OC_INTR_OC2_MASK, 1);
+               break;
+       case THROTTLE_OC3:
+               r = REG_SET_MASK(r, OC_INTR_OC3_MASK, 1);
+               break;
+       case THROTTLE_OC4:
+               r = REG_SET_MASK(r, OC_INTR_OC4_MASK, 1);
+               break;
+       default:
+               r = 0;
+               break;
+       }
+       writel(r, ts->regs + OC_INTR_ENABLE);
+}
+
+/**
+ * soctherm_handle_alarm() - Handles soctherm alarms
+ * @alarm:             The soctherm throttle id
+ *
+ * "Handles" over-current alarms (OC1, OC2, OC3, and OC4) by printing
+ * a warning or informative message.
+ *
+ * Return: -EINVAL for @alarm = THROTTLE_OC3, otherwise 0 (success).
+ */
+static int soctherm_handle_alarm(enum soctherm_throttle_id alarm)
+{
+       int rv = -EINVAL;
+
+       switch (alarm) {
+       case THROTTLE_OC1:
+               pr_debug("soctherm: Successfully handled OC1 alarm\n");
+               rv = 0;
+               break;
+
+       case THROTTLE_OC2:
+               pr_debug("soctherm: Successfully handled OC2 alarm\n");
+               rv = 0;
+               break;
+
+       case THROTTLE_OC3:
+               pr_debug("soctherm: Successfully handled OC3 alarm\n");
+               rv = 0;
+               break;
+
+       case THROTTLE_OC4:
+               pr_debug("soctherm: Successfully handled OC4 alarm\n");
+               rv = 0;
+               break;
+
+       default:
+               break;
+       }
+
+       if (rv)
+               pr_err("soctherm: ERROR in handling %s alarm\n",
+                      throt_names[alarm]);
+
+       return rv;
+}
+
+/**
+ * soctherm_edp_isr_thread() - log an over-current interrupt request
+ * @irq:       OC irq number. Currently not being used. See description
+ * @arg:       a void pointer for callback, currently not being used
+ *
+ * Over-current events are handled in hardware. This function is called to log
+ * and handle any OC events that happened. Additionally, it checks every
+ * over-current interrupt registers for registers are set but
+ * was not expected (i.e. any discrepancy in interrupt status) by the function,
+ * the discrepancy will logged.
+ *
+ * Return: %IRQ_HANDLED
+ */
+static irqreturn_t soctherm_edp_isr_thread(int irq, void *arg)
+{
+       struct tegra_soctherm *ts = arg;
+       u32 st, ex, oc1, oc2, oc3, oc4;
+
+       st = readl(ts->regs + OC_INTR_STATUS);
+
+       /* deliberately clear expected interrupts handled in SW */
+       oc1 = st & OC_INTR_OC1_MASK;
+       oc2 = st & OC_INTR_OC2_MASK;
+       oc3 = st & OC_INTR_OC3_MASK;
+       oc4 = st & OC_INTR_OC4_MASK;
+       ex = oc1 | oc2 | oc3 | oc4;
+
+       pr_err("soctherm: OC ALARM 0x%08x\n", ex);
+       if (ex) {
+               writel(st, ts->regs + OC_INTR_STATUS);
+               st &= ~ex;
+
+               if (oc1 && !soctherm_handle_alarm(THROTTLE_OC1))
+                       soctherm_oc_intr_enable(ts, THROTTLE_OC1, true);
+
+               if (oc2 && !soctherm_handle_alarm(THROTTLE_OC2))
+                       soctherm_oc_intr_enable(ts, THROTTLE_OC2, true);
+
+               if (oc3 && !soctherm_handle_alarm(THROTTLE_OC3))
+                       soctherm_oc_intr_enable(ts, THROTTLE_OC3, true);
+
+               if (oc4 && !soctherm_handle_alarm(THROTTLE_OC4))
+                       soctherm_oc_intr_enable(ts, THROTTLE_OC4, true);
+
+               if (oc1 && soc_irq_cdata.irq_enable & BIT(0))
+                       handle_nested_irq(
+                               irq_find_mapping(soc_irq_cdata.domain, 0));
+
+               if (oc2 && soc_irq_cdata.irq_enable & BIT(1))
+                       handle_nested_irq(
+                               irq_find_mapping(soc_irq_cdata.domain, 1));
+
+               if (oc3 && soc_irq_cdata.irq_enable & BIT(2))
+                       handle_nested_irq(
+                               irq_find_mapping(soc_irq_cdata.domain, 2));
+
+               if (oc4 && soc_irq_cdata.irq_enable & BIT(3))
+                       handle_nested_irq(
+                               irq_find_mapping(soc_irq_cdata.domain, 3));
+       }
+
+       if (st) {
+               pr_err("soctherm: Ignored unexpected OC ALARM 0x%08x\n", st);
+               writel(st, ts->regs + OC_INTR_STATUS);
+       }
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * soctherm_edp_isr() - Disables any active interrupts
+ * @irq:       The interrupt request number
+ * @arg:       Opaque pointer to an argument
+ *
+ * Writes to the OC_INTR_DISABLE register the over current interrupt status,
+ * masking any asserted interrupts. Doing this prevents the same interrupts
+ * from triggering this isr repeatedly. The thread woken by this isr will
+ * handle asserted interrupts and subsequently unmask/re-enable them.
+ *
+ * The OC_INTR_DISABLE register indicates which OC interrupts
+ * have been disabled.
+ *
+ * Return: %IRQ_WAKE_THREAD, handler requests to wake the handler thread
+ */
+static irqreturn_t soctherm_edp_isr(int irq, void *arg)
+{
+       struct tegra_soctherm *ts = arg;
+       u32 r;
+
+       if (!ts)
+               return IRQ_NONE;
+
+       r = readl(ts->regs + OC_INTR_STATUS);
+       writel(r, ts->regs + OC_INTR_DISABLE);
+
+       return IRQ_WAKE_THREAD;
+}
+
+/**
+ * soctherm_oc_irq_lock() - locks the over-current interrupt request
+ * @data:      Interrupt request data
+ *
+ * Looks up the chip data from @data and locks the mutex associated with
+ * a particular over-current interrupt request.
+ */
+static void soctherm_oc_irq_lock(struct irq_data *data)
+{
+       struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);
+
+       mutex_lock(&d->irq_lock);
+}
+
+/**
+ * soctherm_oc_irq_sync_unlock() - Unlocks the OC interrupt request
+ * @data:              Interrupt request data
+ *
+ * Looks up the interrupt request data @data and unlocks the mutex associated
+ * with a particular over-current interrupt request.
+ */
+static void soctherm_oc_irq_sync_unlock(struct irq_data *data)
+{
+       struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);
+
+       mutex_unlock(&d->irq_lock);
+}
+
+/**
+ * soctherm_oc_irq_enable() - Enables the SOC_THERM over-current interrupt queue
+ * @data:       irq_data structure of the chip
+ *
+ * Sets the irq_enable bit of SOC_THERM allowing SOC_THERM
+ * to respond to over-current interrupts.
+ *
+ */
+static void soctherm_oc_irq_enable(struct irq_data *data)
+{
+       struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);
+
+       d->irq_enable |= BIT(data->hwirq);
+}
+
+/**
+ * soctherm_oc_irq_disable() - Disables overcurrent interrupt requests
+ * @irq_data:  The interrupt request information
+ *
+ * Clears the interrupt request enable bit of the overcurrent
+ * interrupt request chip data.
+ *
+ * Return: Nothing is returned (void)
+ */
+static void soctherm_oc_irq_disable(struct irq_data *data)
+{
+       struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data);
+
+       d->irq_enable &= ~BIT(data->hwirq);
+}
+
+static int soctherm_oc_irq_set_type(struct irq_data *data, unsigned int type)
+{
+       return 0;
+}
+
+/**
+ * soctherm_oc_irq_map() - SOC_THERM interrupt request domain mapper
+ * @h:         Interrupt request domain
+ * @virq:      Virtual interrupt request number
+ * @hw:                Hardware interrupt request number
+ *
+ * Mapping callback function for SOC_THERM's irq_domain. When a SOC_THERM
+ * interrupt request is called, the irq_domain takes the request's virtual
+ * request number (much like a virtual memory address) and maps it to a
+ * physical hardware request number.
+ *
+ * When a mapping doesn't already exist for a virtual request number, the
+ * irq_domain calls this function to associate the virtual request number with
+ * a hardware request number.
+ *
+ * Return: 0
+ */
+static int soctherm_oc_irq_map(struct irq_domain *h, unsigned int virq,
+               irq_hw_number_t hw)
+{
+       struct soctherm_oc_irq_chip_data *data = h->host_data;
+
+       irq_set_chip_data(virq, data);
+       irq_set_chip(virq, &data->irq_chip);
+       irq_set_nested_thread(virq, 1);
+       return 0;
+}
+
+/**
+ * soctherm_irq_domain_xlate_twocell() - xlate for soctherm interrupts
+ * @d:      Interrupt request domain
+ * @intspec:    Array of u32s from DTs "interrupt" property
+ * @intsize:    Number of values inside the intspec array
+ * @out_hwirq:  HW IRQ value associated with this interrupt
+ * @out_type:   The IRQ SENSE type for this interrupt.
+ *
+ * This Device Tree IRQ specifier translation function will translate a
+ * specific "interrupt" as defined by 2 DT values where the cell values map
+ * the hwirq number + 1 and linux irq flags. Since the output is the hwirq
+ * number, this function will subtract 1 from the value listed in DT.
+ *
+ * Return: 0
+ */
+static int soctherm_irq_domain_xlate_twocell(struct irq_domain *d,
+       struct device_node *ctrlr, const u32 *intspec, unsigned int intsize,
+       irq_hw_number_t *out_hwirq, unsigned int *out_type)
+{
+       if (WARN_ON(intsize < 2))
+               return -EINVAL;
+
+       /*
+        * The HW value is 1 index less than the DT IRQ values.
+        * i.e. OC4 goes to HW index 3.
+        */
+       *out_hwirq = intspec[0] - 1;
+       *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+       return 0;
+}
+
+static const struct irq_domain_ops soctherm_oc_domain_ops = {
+       .map    = soctherm_oc_irq_map,
+       .xlate  = soctherm_irq_domain_xlate_twocell,
+};
+
+/**
+ * soctherm_oc_int_init() - Initial enabling of the over
+ * current interrupts
+ * @np:        The devicetree node for soctherm
+ * @num_irqs:  The number of new interrupt requests
+ *
+ * Sets the over current interrupt request chip data
+ *
+ * Return: 0 on success or if overcurrent interrupts are not enabled,
+ * -ENOMEM (out of memory), or irq_base if the function failed to
+ * allocate the irqs
+ */
+static int soctherm_oc_int_init(struct device_node *np, int num_irqs)
+{
+       if (!num_irqs) {
+               pr_info("%s(): OC interrupts are not enabled\n", __func__);
+               return 0;
+       }
+
+       mutex_init(&soc_irq_cdata.irq_lock);
+       soc_irq_cdata.irq_enable = 0;
+
+       soc_irq_cdata.irq_chip.name = "soc_therm_oc";
+       soc_irq_cdata.irq_chip.irq_bus_lock = soctherm_oc_irq_lock;
+       soc_irq_cdata.irq_chip.irq_bus_sync_unlock =
+               soctherm_oc_irq_sync_unlock;
+       soc_irq_cdata.irq_chip.irq_disable = soctherm_oc_irq_disable;
+       soc_irq_cdata.irq_chip.irq_enable = soctherm_oc_irq_enable;
+       soc_irq_cdata.irq_chip.irq_set_type = soctherm_oc_irq_set_type;
+       soc_irq_cdata.irq_chip.irq_set_wake = NULL;
+
+       soc_irq_cdata.domain = irq_domain_add_linear(np, num_irqs,
+                                                    &soctherm_oc_domain_ops,
+                                                    &soc_irq_cdata);
+
+       if (!soc_irq_cdata.domain) {
+               pr_err("%s: Failed to create IRQ domain\n", __func__);
+               return -ENOMEM;
+       }
+
+       pr_debug("%s(): OC interrupts enabled successful\n", __func__);
+       return 0;
+}
+
 #ifdef CONFIG_DEBUG_FS
 static int regs_show(struct seq_file *s, void *data)
 {
@@ -929,6 +1574,120 @@ static const struct thermal_cooling_device_ops throt_cooling_ops = {
        .set_cur_state = throt_set_cdev_state,
 };
 
+static int soctherm_thermtrips_parse(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct tegra_soctherm *ts = dev_get_drvdata(dev);
+       struct tsensor_group_thermtrips *tt = ts->soc->thermtrips;
+       const int max_num_prop = ts->soc->num_ttgs * 2;
+       u32 *tlb;
+       int i, j, n, ret;
+
+       if (!tt)
+               return -ENOMEM;
+
+       n = of_property_count_u32_elems(dev->of_node, "nvidia,thermtrips");
+       if (n <= 0) {
+               dev_info(dev,
+                        "missing thermtrips, will use critical trips as shut down temp\n");
+               return n;
+       }
+
+       n = min(max_num_prop, n);
+
+       tlb = devm_kcalloc(&pdev->dev, max_num_prop, sizeof(u32), GFP_KERNEL);
+       if (!tlb)
+               return -ENOMEM;
+       ret = of_property_read_u32_array(dev->of_node, "nvidia,thermtrips",
+                                        tlb, n);
+       if (ret) {
+               dev_err(dev, "invalid num ele: thermtrips:%d\n", ret);
+               return ret;
+       }
+
+       i = 0;
+       for (j = 0; j < n; j = j + 2) {
+               if (tlb[j] >= TEGRA124_SOCTHERM_SENSOR_NUM)
+                       continue;
+
+               tt[i].id = tlb[j];
+               tt[i].temp = tlb[j + 1];
+               i++;
+       }
+
+       return 0;
+}
+
+static void soctherm_oc_cfg_parse(struct device *dev,
+                               struct device_node *np_oc,
+                               struct soctherm_throt_cfg *stc)
+{
+       u32 val;
+
+       if (of_property_read_bool(np_oc, "nvidia,polarity-active-low"))
+               stc->oc_cfg.active_low = 1;
+       else
+               stc->oc_cfg.active_low = 0;
+
+       if (!of_property_read_u32(np_oc, "nvidia,count-threshold", &val)) {
+               stc->oc_cfg.intr_en = 1;
+               stc->oc_cfg.alarm_cnt_thresh = val;
+       }
+
+       if (!of_property_read_u32(np_oc, "nvidia,throttle-period-us", &val))
+               stc->oc_cfg.throt_period = val;
+
+       if (!of_property_read_u32(np_oc, "nvidia,alarm-filter", &val))
+               stc->oc_cfg.alarm_filter = val;
+
+       /* BRIEF throttling by default, do not support STICKY */
+       stc->oc_cfg.mode = OC_THROTTLE_MODE_BRIEF;
+}
+
+static int soctherm_throt_cfg_parse(struct device *dev,
+                                   struct device_node *np,
+                                   struct soctherm_throt_cfg *stc)
+{
+       struct tegra_soctherm *ts = dev_get_drvdata(dev);
+       int ret;
+       u32 val;
+
+       ret = of_property_read_u32(np, "nvidia,priority", &val);
+       if (ret) {
+               dev_err(dev, "throttle-cfg: %s: invalid priority\n", stc->name);
+               return -EINVAL;
+       }
+       stc->priority = val;
+
+       ret = of_property_read_u32(np, ts->soc->use_ccroc ?
+                                  "nvidia,cpu-throt-level" :
+                                  "nvidia,cpu-throt-percent", &val);
+       if (!ret) {
+               if (ts->soc->use_ccroc &&
+                   val <= TEGRA_SOCTHERM_THROT_LEVEL_HIGH)
+                       stc->cpu_throt_level = val;
+               else if (!ts->soc->use_ccroc && val <= 100)
+                       stc->cpu_throt_depth = val;
+               else
+                       goto err;
+       } else {
+               goto err;
+       }
+
+       ret = of_property_read_u32(np, "nvidia,gpu-throt-level", &val);
+       if (!ret && val <= TEGRA_SOCTHERM_THROT_LEVEL_HIGH)
+               stc->gpu_throt_level = val;
+       else
+               goto err;
+
+       return 0;
+
+err:
+       dev_err(dev, "throttle-cfg: %s: no throt prop or invalid prop\n",
+               stc->name);
+       return -EINVAL;
+}
+
 /**
  * soctherm_init_hw_throt_cdev() - Parse the HW throttle configurations
  * and register them as cooling devices.
@@ -939,8 +1698,7 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
        struct tegra_soctherm *ts = dev_get_drvdata(dev);
        struct device_node *np_stc, *np_stcc;
        const char *name;
-       u32 val;
-       int i, r;
+       int i;
 
        for (i = 0; i < THROTTLE_SIZE; i++) {
                ts->throt_cfgs[i].name = throt_names[i];
@@ -958,6 +1716,7 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
        for_each_child_of_node(np_stc, np_stcc) {
                struct soctherm_throt_cfg *stc;
                struct thermal_cooling_device *tcd;
+               int err;
 
                name = np_stcc->name;
                stc = find_throttle_cfg_by_name(ts, name);
@@ -967,51 +1726,34 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
                        continue;
                }
 
-               r = of_property_read_u32(np_stcc, "nvidia,priority", &val);
-               if (r) {
-                       dev_info(dev,
-                                "throttle-cfg: %s: missing priority\n", name);
-                       continue;
+               if (stc->init) {
+                       dev_err(dev, "throttle-cfg: %s: redefined!\n", name);
+                       of_node_put(np_stcc);
+                       break;
                }
-               stc->priority = val;
-
-               if (ts->soc->use_ccroc) {
-                       r = of_property_read_u32(np_stcc,
-                                                "nvidia,cpu-throt-level",
-                                                &val);
-                       if (r) {
-                               dev_info(dev,
-                                        "throttle-cfg: %s: missing cpu-throt-level\n",
-                                        name);
-                               continue;
-                       }
-                       stc->cpu_throt_level = val;
+
+               err = soctherm_throt_cfg_parse(dev, np_stcc, stc);
+               if (err)
+                       continue;
+
+               if (stc->id >= THROTTLE_OC1) {
+                       soctherm_oc_cfg_parse(dev, np_stcc, stc);
+                       stc->init = true;
                } else {
-                       r = of_property_read_u32(np_stcc,
-                                                "nvidia,cpu-throt-percent",
-                                                &val);
-                       if (r) {
-                               dev_info(dev,
-                                        "throttle-cfg: %s: missing cpu-throt-percent\n",
-                                        name);
-                               continue;
-                       }
-                       stc->cpu_throt_depth = val;
-               }
 
-               tcd = thermal_of_cooling_device_register(np_stcc,
+                       tcd = thermal_of_cooling_device_register(np_stcc,
                                                         (char *)name, ts,
                                                         &throt_cooling_ops);
-               of_node_put(np_stcc);
-               if (IS_ERR_OR_NULL(tcd)) {
-                       dev_err(dev,
-                               "throttle-cfg: %s: failed to register cooling device\n",
-                               name);
-                       continue;
+                       if (IS_ERR_OR_NULL(tcd)) {
+                               dev_err(dev,
+                                       "throttle-cfg: %s: failed to register cooling device\n",
+                                       name);
+                               continue;
+                       }
+                       stc->cdev = tcd;
+                       stc->init = true;
                }
 
-               stc->cdev = tcd;
-               stc->init = true;
        }
 
        of_node_put(np_stc);
@@ -1140,6 +1882,50 @@ static void throttlectl_cpu_mn(struct tegra_soctherm *ts,
        writel(r, ts->regs + THROT_PSKIP_RAMP(throt, THROTTLE_DEV_CPU));
 }
 
+/**
+ * throttlectl_gpu_level_select() - selects throttling level for GPU
+ * @throt: the LIGHT/HEAVY of throttle event id
+ *
+ * This function programs soctherm's interface to GK20a NV_THERM to select
+ * pre-configured "Low", "Medium" or "Heavy" throttle levels.
+ *
+ * Return: boolean true if HW was programmed
+ */
+static void throttlectl_gpu_level_select(struct tegra_soctherm *ts,
+                                        enum soctherm_throttle_id throt)
+{
+       u32 r, level, throt_vect;
+
+       level = ts->throt_cfgs[throt].gpu_throt_level;
+       throt_vect = THROT_LEVEL_TO_DEPTH(level);
+       r = readl(ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_GPU));
+       r = REG_SET_MASK(r, THROT_PSKIP_CTRL_ENABLE_MASK, 1);
+       r = REG_SET_MASK(r, THROT_PSKIP_CTRL_VECT_GPU_MASK, throt_vect);
+       writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_GPU));
+}
+
+static int soctherm_oc_cfg_program(struct tegra_soctherm *ts,
+                                     enum soctherm_throttle_id throt)
+{
+       u32 r;
+       struct soctherm_oc_cfg *oc = &ts->throt_cfgs[throt].oc_cfg;
+
+       if (oc->mode == OC_THROTTLE_MODE_DISABLED)
+               return -EINVAL;
+
+       r = REG_SET_MASK(0, OC1_CFG_HW_RESTORE_MASK, 1);
+       r = REG_SET_MASK(r, OC1_CFG_THROTTLE_MODE_MASK, oc->mode);
+       r = REG_SET_MASK(r, OC1_CFG_ALARM_POLARITY_MASK, oc->active_low);
+       r = REG_SET_MASK(r, OC1_CFG_EN_THROTTLE_MASK, 1);
+       writel(r, ts->regs + ALARM_CFG(throt));
+       writel(oc->throt_period, ts->regs + ALARM_THROTTLE_PERIOD(throt));
+       writel(oc->alarm_cnt_thresh, ts->regs + ALARM_CNT_THRESHOLD(throt));
+       writel(oc->alarm_filter, ts->regs + ALARM_FILTER(throt));
+       soctherm_oc_intr_enable(ts, throt, oc->intr_en);
+
+       return 0;
+}
+
 /**
  * soctherm_throttle_program() - programs pulse skippers' configuration
  * @throt: the LIGHT/HEAVY of the throttle event id.
@@ -1156,12 +1942,17 @@ static void soctherm_throttle_program(struct tegra_soctherm *ts,
        if (!stc.init)
                return;
 
+       if ((throt >= THROTTLE_OC1) && (soctherm_oc_cfg_program(ts, throt)))
+               return;
+
        /* Setup PSKIP parameters */
        if (ts->soc->use_ccroc)
                throttlectl_cpu_level_select(ts, throt);
        else
                throttlectl_cpu_mn(ts, throt);
 
+       throttlectl_gpu_level_select(ts, throt);
+
        r = REG_SET_MASK(0, THROT_PRIORITY_LITE_PRIO_MASK, stc.priority);
        writel(r, ts->regs + THROT_PRIORITY_CTRL(throt));
 
@@ -1215,6 +2006,57 @@ static void tegra_soctherm_throttle(struct device *dev)
        writel(v, ts->regs + THERMCTL_STATS_CTL);
 }
 
+static int soctherm_interrupts_init(struct platform_device *pdev,
+                                   struct tegra_soctherm *tegra)
+{
+       struct device_node *np = pdev->dev.of_node;
+       int ret;
+
+       ret = soctherm_oc_int_init(np, TEGRA_SOC_OC_IRQ_MAX);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "soctherm_oc_int_init failed\n");
+               return ret;
+       }
+
+       tegra->thermal_irq = platform_get_irq(pdev, 0);
+       if (tegra->thermal_irq < 0) {
+               dev_dbg(&pdev->dev, "get 'thermal_irq' failed.\n");
+               return 0;
+       }
+
+       tegra->edp_irq = platform_get_irq(pdev, 1);
+       if (tegra->edp_irq < 0) {
+               dev_dbg(&pdev->dev, "get 'edp_irq' failed.\n");
+               return 0;
+       }
+
+       ret = devm_request_threaded_irq(&pdev->dev,
+                                       tegra->thermal_irq,
+                                       soctherm_thermal_isr,
+                                       soctherm_thermal_isr_thread,
+                                       IRQF_ONESHOT,
+                                       dev_name(&pdev->dev),
+                                       tegra);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "request_irq 'thermal_irq' failed.\n");
+               return ret;
+       }
+
+       ret = devm_request_threaded_irq(&pdev->dev,
+                                       tegra->edp_irq,
+                                       soctherm_edp_isr,
+                                       soctherm_edp_isr_thread,
+                                       IRQF_ONESHOT,
+                                       "soctherm_edp",
+                                       tegra);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "request_irq 'edp_irq' failed.\n");
+               return ret;
+       }
+
+       return 0;
+}
+
 static void soctherm_init(struct platform_device *pdev)
 {
        struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
@@ -1292,6 +2134,7 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
        if (!tegra)
                return -ENOMEM;
 
+       mutex_init(&tegra->thermctl_lock);
        dev_set_drvdata(&pdev->dev, tegra);
 
        tegra->soc = soc;
@@ -1370,6 +2213,8 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
        if (err)
                return err;
 
+       soctherm_thermtrips_parse(pdev);
+
        soctherm_init_hw_throt_cdev(pdev);
 
        soctherm_init(pdev);
@@ -1406,6 +2251,8 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
                        goto disable_clocks;
        }
 
+       err = soctherm_interrupts_init(pdev, tegra);
+
        soctherm_debug_init(pdev);
 
        return 0;
index e96ca73..70501e7 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
  *
 #define THERMCTL_THERMTRIP_CTL                 0x80
 /* BITs are defined in device file */
 
+#define THERMCTL_INTR_ENABLE                   0x88
+#define THERMCTL_INTR_DISABLE                  0x8c
+#define TH_INTR_UP_DN_EN                       0x3
+#define THERM_IRQ_MEM_MASK                     (TH_INTR_UP_DN_EN << 24)
+#define THERM_IRQ_GPU_MASK                     (TH_INTR_UP_DN_EN << 16)
+#define THERM_IRQ_CPU_MASK                     (TH_INTR_UP_DN_EN << 8)
+#define THERM_IRQ_TSENSE_MASK                  (TH_INTR_UP_DN_EN << 0)
+
 #define SENSOR_PDIV                            0x1c0
 #define SENSOR_PDIV_CPU_MASK                   (0xf << 12)
 #define SENSOR_PDIV_GPU_MASK                   (0xf << 8)
@@ -70,6 +79,7 @@ struct tegra_tsensor_group {
        u32 thermtrip_enable_mask;
        u32 thermtrip_any_en_mask;
        u32 thermtrip_threshold_mask;
+       u32 thermctl_isr_mask;
        u16 thermctl_lvl0_offset;
        u32 thermctl_lvl0_up_thresh_mask;
        u32 thermctl_lvl0_dn_thresh_mask;
@@ -92,6 +102,11 @@ struct tegra_tsensor {
        const struct tegra_tsensor_group *group;
 };
 
+struct tsensor_group_thermtrips {
+       u8 id;
+       u32 temp;
+};
+
 struct tegra_soctherm_fuse {
        u32 fuse_base_cp_mask, fuse_base_cp_shift;
        u32 fuse_base_ft_mask, fuse_base_ft_shift;
@@ -113,6 +128,7 @@ struct tegra_soctherm_soc {
        const int thresh_grain;
        const unsigned int bptt;
        const bool use_ccroc;
+       struct tsensor_group_thermtrips *thermtrips;
 };
 
 int tegra_calc_shared_calib(const struct tegra_soctherm_fuse *tfuse,
index 3676863..20ad27f 100644 (file)
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2018, NVIDIA CORPORATION.  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
@@ -55,6 +56,7 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_cpu = {
        .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA124_THERMTRIP_CPU_EN_MASK,
        .thermtrip_threshold_mask = TEGRA124_THERMTRIP_CPU_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_CPU_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
        .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -73,6 +75,7 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_gpu = {
        .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA124_THERMTRIP_GPU_EN_MASK,
        .thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_GPU_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
        .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -89,6 +92,7 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_pll = {
        .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA124_THERMTRIP_TSENSE_EN_MASK,
        .thermtrip_threshold_mask = TEGRA124_THERMTRIP_TSENSE_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_TSENSE_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
        .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -107,6 +111,7 @@ static const struct tegra_tsensor_group tegra124_tsensor_group_mem = {
        .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA124_THERMTRIP_MEM_EN_MASK,
        .thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_MEM_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
        .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
index 97fa305..b76308f 100644 (file)
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2018, NVIDIA CORPORATION.  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
@@ -55,6 +56,7 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_cpu = {
        .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA132_THERMTRIP_CPU_EN_MASK,
        .thermtrip_threshold_mask = TEGRA132_THERMTRIP_CPU_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_CPU_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
        .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -73,6 +75,7 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_gpu = {
        .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA132_THERMTRIP_GPU_EN_MASK,
        .thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_GPU_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
        .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -89,6 +92,7 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_pll = {
        .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA132_THERMTRIP_TSENSE_EN_MASK,
        .thermtrip_threshold_mask = TEGRA132_THERMTRIP_TSENSE_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_TSENSE_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
        .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -107,6 +111,7 @@ static const struct tegra_tsensor_group tegra132_tsensor_group_mem = {
        .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA132_THERMTRIP_MEM_EN_MASK,
        .thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_MEM_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
        .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
index ad53169..d31b500 100644 (file)
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2018, NVIDIA CORPORATION.  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
@@ -56,6 +57,7 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_cpu = {
        .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA210_THERMTRIP_CPU_EN_MASK,
        .thermtrip_threshold_mask = TEGRA210_THERMTRIP_CPU_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_CPU_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU,
        .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -74,6 +76,7 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_gpu = {
        .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA210_THERMTRIP_GPU_EN_MASK,
        .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_GPU_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU,
        .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -90,6 +93,7 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_pll = {
        .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA210_THERMTRIP_TSENSE_EN_MASK,
        .thermtrip_threshold_mask = TEGRA210_THERMTRIP_TSENSE_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_TSENSE_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE,
        .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -108,6 +112,7 @@ static const struct tegra_tsensor_group tegra210_tsensor_group_mem = {
        .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK,
        .thermtrip_enable_mask = TEGRA210_THERMTRIP_MEM_EN_MASK,
        .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK,
+       .thermctl_isr_mask = THERM_IRQ_MEM_MASK,
        .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM,
        .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK,
        .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK,
@@ -203,6 +208,13 @@ static const struct tegra_soctherm_fuse tegra210_soctherm_fuse = {
        .fuse_spare_realignment = 0,
 };
 
+struct tsensor_group_thermtrips tegra210_tsensor_thermtrips[] = {
+       {.id = TEGRA124_SOCTHERM_SENSOR_NUM},
+       {.id = TEGRA124_SOCTHERM_SENSOR_NUM},
+       {.id = TEGRA124_SOCTHERM_SENSOR_NUM},
+       {.id = TEGRA124_SOCTHERM_SENSOR_NUM},
+};
+
 const struct tegra_soctherm_soc tegra210_soctherm = {
        .tsensors = tegra210_tsensors,
        .num_tsensors = ARRAY_SIZE(tegra210_tsensors),
@@ -212,4 +224,5 @@ const struct tegra_soctherm_soc tegra210_soctherm = {
        .thresh_grain = TEGRA210_THRESH_GRAIN,
        .bptt = TEGRA210_BPTT,
        .use_ccroc = false,
+       .thermtrips = tegra210_tsensor_thermtrips,
 };
index e22fc60..deb244f 100644 (file)
@@ -29,6 +29,9 @@ static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val)
        int temp, temp_hi, temp_lo, adc_hi, adc_lo;
        int i;
 
+       if (!gti->lookup_table)
+               return val;
+
        for (i = 0; i < gti->nlookup_table; i++) {
                if (val >= gti->lookup_table[2 * i + 1])
                        break;
@@ -81,9 +84,9 @@ static int gadc_thermal_read_linear_lookup_table(struct device *dev,
 
        ntable = of_property_count_elems_of_size(np, "temperature-lookup-table",
                                                 sizeof(u32));
-       if (ntable < 0) {
-               dev_err(dev, "Lookup table is not provided\n");
-               return ntable;
+       if (ntable <= 0) {
+               dev_notice(dev, "no lookup table, assuming DAC channel returns milliCelcius\n");
+               return 0;
        }
 
        if (ntable % 2) {
index 6590bb5..46cfb7d 100644 (file)
@@ -266,7 +266,7 @@ static int __init thermal_register_governors(void)
        return thermal_gov_power_allocator_register();
 }
 
-static void thermal_unregister_governors(void)
+static void __init thermal_unregister_governors(void)
 {
        thermal_gov_step_wise_unregister();
        thermal_gov_fair_share_unregister();
@@ -941,7 +941,7 @@ static void bind_cdev(struct thermal_cooling_device *cdev)
  */
 static struct thermal_cooling_device *
 __thermal_cooling_device_register(struct device_node *np,
-                                 char *type, void *devdata,
+                                 const char *type, void *devdata,
                                  const struct thermal_cooling_device_ops *ops)
 {
        struct thermal_cooling_device *cdev;
@@ -1015,7 +1015,7 @@ __thermal_cooling_device_register(struct device_node *np,
  * ERR_PTR. Caller must check return value with IS_ERR*() helpers.
  */
 struct thermal_cooling_device *
-thermal_cooling_device_register(char *type, void *devdata,
+thermal_cooling_device_register(const char *type, void *devdata,
                                const struct thermal_cooling_device_ops *ops)
 {
        return __thermal_cooling_device_register(NULL, type, devdata, ops);
@@ -1039,13 +1039,62 @@ EXPORT_SYMBOL_GPL(thermal_cooling_device_register);
  */
 struct thermal_cooling_device *
 thermal_of_cooling_device_register(struct device_node *np,
-                                  char *type, void *devdata,
+                                  const char *type, void *devdata,
                                   const struct thermal_cooling_device_ops *ops)
 {
        return __thermal_cooling_device_register(np, type, devdata, ops);
 }
 EXPORT_SYMBOL_GPL(thermal_of_cooling_device_register);
 
+static void thermal_cooling_device_release(struct device *dev, void *res)
+{
+       thermal_cooling_device_unregister(
+                               *(struct thermal_cooling_device **)res);
+}
+
+/**
+ * devm_thermal_of_cooling_device_register() - register an OF thermal cooling
+ *                                            device
+ * @dev:       a valid struct device pointer of a sensor device.
+ * @np:                a pointer to a device tree node.
+ * @type:      the thermal cooling device type.
+ * @devdata:   device private data.
+ * @ops:       standard thermal cooling devices callbacks.
+ *
+ * This function will register a cooling device with device tree node reference.
+ * This interface function adds a new thermal cooling device (fan/processor/...)
+ * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself
+ * to all the thermal zone devices registered at the same time.
+ *
+ * Return: a pointer to the created struct thermal_cooling_device or an
+ * ERR_PTR. Caller must check return value with IS_ERR*() helpers.
+ */
+struct thermal_cooling_device *
+devm_thermal_of_cooling_device_register(struct device *dev,
+                               struct device_node *np,
+                               char *type, void *devdata,
+                               const struct thermal_cooling_device_ops *ops)
+{
+       struct thermal_cooling_device **ptr, *tcd;
+
+       ptr = devres_alloc(thermal_cooling_device_release, sizeof(*ptr),
+                          GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       tcd = __thermal_cooling_device_register(np, type, devdata, ops);
+       if (IS_ERR(tcd)) {
+               devres_free(ptr);
+               return tcd;
+       }
+
+       *ptr = tcd;
+       devres_add(dev, ptr);
+
+       return tcd;
+}
+EXPORT_SYMBOL_GPL(devm_thermal_of_cooling_device_register);
+
 static void __unbind(struct thermal_zone_device *tz, int mask,
                     struct thermal_cooling_device *cdev)
 {
@@ -1494,6 +1543,7 @@ static int thermal_pm_notify(struct notifier_block *nb,
                             unsigned long mode, void *_unused)
 {
        struct thermal_zone_device *tz;
+       enum thermal_device_mode tz_mode;
 
        switch (mode) {
        case PM_HIBERNATION_PREPARE:
@@ -1506,6 +1556,13 @@ static int thermal_pm_notify(struct notifier_block *nb,
        case PM_POST_SUSPEND:
                atomic_set(&in_suspend, 0);
                list_for_each_entry(tz, &thermal_tz_list, node) {
+                       tz_mode = THERMAL_DEVICE_ENABLED;
+                       if (tz->ops->get_mode)
+                               tz->ops->get_mode(tz, &tz_mode);
+
+                       if (tz_mode == THERMAL_DEVICE_DISABLED)
+                               continue;
+
                        thermal_zone_device_init(tz);
                        thermal_zone_device_update(tz,
                                                   THERMAL_EVENT_UNSPECIFIED);
@@ -1563,19 +1620,4 @@ error:
        mutex_destroy(&poweroff_lock);
        return result;
 }
-
-static void __exit thermal_exit(void)
-{
-       unregister_pm_notifier(&thermal_pm_nb);
-       of_thermal_destroy_zones();
-       genetlink_exit();
-       class_unregister(&thermal_class);
-       thermal_unregister_governors();
-       ida_destroy(&thermal_tz_ida);
-       ida_destroy(&thermal_cdev_ida);
-       mutex_destroy(&thermal_list_lock);
-       mutex_destroy(&thermal_governor_lock);
-}
-
 fs_initcall(thermal_init);
-module_exit(thermal_exit);
diff --git a/drivers/thermal/thermal_mmio.c b/drivers/thermal/thermal_mmio.c
new file mode 100644 (file)
index 0000000..de3ccee
--- /dev/null
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+
+struct thermal_mmio {
+       void __iomem *mmio_base;
+       u32 (*read_mmio)(void __iomem *mmio_base);
+       u32 mask;
+       int factor;
+};
+
+static u32 thermal_mmio_readb(void __iomem *mmio_base)
+{
+       return readb(mmio_base);
+}
+
+static int thermal_mmio_get_temperature(void *private, int *temp)
+{
+       int t;
+       struct thermal_mmio *sensor =
+               (struct thermal_mmio *)private;
+
+       t = sensor->read_mmio(sensor->mmio_base) & sensor->mask;
+       t *= sensor->factor;
+
+       *temp = t;
+
+       return 0;
+}
+
+static struct thermal_zone_of_device_ops thermal_mmio_ops = {
+       .get_temp = thermal_mmio_get_temperature,
+};
+
+static int thermal_mmio_probe(struct platform_device *pdev)
+{
+       struct resource *resource;
+       struct thermal_mmio *sensor;
+       int (*sensor_init_func)(struct platform_device *pdev,
+                               struct thermal_mmio *sensor);
+       struct thermal_zone_device *thermal_zone;
+       int ret;
+       int temperature;
+
+       sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL);
+       if (!sensor)
+               return -ENOMEM;
+
+       resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (IS_ERR(resource)) {
+               dev_err(&pdev->dev,
+                       "fail to get platform memory resource (%ld)\n",
+                       PTR_ERR(resource));
+               return PTR_ERR(resource);
+       }
+
+       sensor->mmio_base = devm_ioremap_resource(&pdev->dev, resource);
+       if (IS_ERR(sensor->mmio_base)) {
+               dev_err(&pdev->dev, "failed to ioremap memory (%ld)\n",
+                       PTR_ERR(sensor->mmio_base));
+               return PTR_ERR(sensor->mmio_base);
+       }
+
+       sensor_init_func = device_get_match_data(&pdev->dev);
+       if (sensor_init_func) {
+               ret = sensor_init_func(pdev, sensor);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "failed to initialize sensor (%d)\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       thermal_zone = devm_thermal_zone_of_sensor_register(&pdev->dev,
+                                                           0,
+                                                           sensor,
+                                                           &thermal_mmio_ops);
+       if (IS_ERR(thermal_zone)) {
+               dev_err(&pdev->dev,
+                       "failed to register sensor (%ld)\n",
+                       PTR_ERR(thermal_zone));
+               return PTR_ERR(thermal_zone);
+       }
+
+       thermal_mmio_get_temperature(sensor, &temperature);
+       dev_info(&pdev->dev,
+                "thermal mmio sensor %s registered, current temperature: %d\n",
+                pdev->name, temperature);
+
+       return 0;
+}
+
+static int al_thermal_init(struct platform_device *pdev,
+                          struct thermal_mmio *sensor)
+{
+       sensor->read_mmio = thermal_mmio_readb;
+       sensor->mask = 0xff;
+       sensor->factor = 1000;
+
+       return 0;
+}
+
+static const struct of_device_id thermal_mmio_id_table[] = {
+       { .compatible = "amazon,al-thermal", .data = al_thermal_init},
+       {}
+};
+MODULE_DEVICE_TABLE(of, thermal_mmio_id_table);
+
+static struct platform_driver thermal_mmio_driver = {
+       .probe = thermal_mmio_probe,
+       .driver = {
+               .name = "thermal-mmio",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(thermal_mmio_id_table),
+       },
+};
+
+module_platform_driver(thermal_mmio_driver);
+
+MODULE_AUTHOR("Talel Shenhar <talel@amazon.com>");
+MODULE_DESCRIPTION("Thermal MMIO Driver");
+MODULE_LICENSE("GPL v2");
index 59e82e6..573b205 100644 (file)
@@ -527,8 +527,12 @@ void __handle_sysrq(int key, bool check_mask)
 {
        struct sysrq_key_op *op_p;
        int orig_log_level;
+       int orig_suppress_printk;
        int i;
 
+       orig_suppress_printk = suppress_printk;
+       suppress_printk = 0;
+
        rcu_sysrq_start();
        rcu_read_lock();
        /*
@@ -574,6 +578,8 @@ void __handle_sysrq(int key, bool check_mask)
        }
        rcu_read_unlock();
        rcu_sysrq_end();
+
+       suppress_printk = orig_suppress_printk;
 }
 
 void handle_sysrq(int key)
index ca8a94f..38183ac 100644 (file)
@@ -40,8 +40,6 @@ struct da8xx_ohci_hcd {
        struct phy *usb11_phy;
        struct regulator *vbus_reg;
        struct notifier_block nb;
-       unsigned int reg_enabled;
-       struct gpio_desc *vbus_gpio;
        struct gpio_desc *oc_gpio;
 };
 
@@ -92,29 +90,21 @@ static int ohci_da8xx_set_power(struct usb_hcd *hcd, int on)
        struct device *dev = hcd->self.controller;
        int ret;
 
-       if (da8xx_ohci->vbus_gpio) {
-               gpiod_set_value_cansleep(da8xx_ohci->vbus_gpio, on);
-               return 0;
-       }
-
        if (!da8xx_ohci->vbus_reg)
                return 0;
 
-       if (on && !da8xx_ohci->reg_enabled) {
+       if (on) {
                ret = regulator_enable(da8xx_ohci->vbus_reg);
                if (ret) {
                        dev_err(dev, "Failed to enable regulator: %d\n", ret);
                        return ret;
                }
-               da8xx_ohci->reg_enabled = 1;
-
-       } else if (!on && da8xx_ohci->reg_enabled) {
+       } else {
                ret = regulator_disable(da8xx_ohci->vbus_reg);
                if (ret) {
                        dev_err(dev, "Failed  to disable regulator: %d\n", ret);
                        return ret;
                }
-               da8xx_ohci->reg_enabled = 0;
        }
 
        return 0;
@@ -124,9 +114,6 @@ static int ohci_da8xx_get_power(struct usb_hcd *hcd)
 {
        struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
 
-       if (da8xx_ohci->vbus_gpio)
-               return gpiod_get_value_cansleep(da8xx_ohci->vbus_gpio);
-
        if (da8xx_ohci->vbus_reg)
                return regulator_is_enabled(da8xx_ohci->vbus_reg);
 
@@ -159,9 +146,6 @@ static int ohci_da8xx_has_set_power(struct usb_hcd *hcd)
 {
        struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
 
-       if (da8xx_ohci->vbus_gpio)
-               return 1;
-
        if (da8xx_ohci->vbus_reg)
                return 1;
 
@@ -206,12 +190,18 @@ static int ohci_da8xx_regulator_event(struct notifier_block *nb,
        return 0;
 }
 
-static irqreturn_t ohci_da8xx_oc_handler(int irq, void *data)
+static irqreturn_t ohci_da8xx_oc_thread(int irq, void *data)
 {
        struct da8xx_ohci_hcd *da8xx_ohci = data;
+       struct device *dev = da8xx_ohci->hcd->self.controller;
+       int ret;
 
-       if (gpiod_get_value(da8xx_ohci->oc_gpio))
-               gpiod_set_value(da8xx_ohci->vbus_gpio, 0);
+       if (gpiod_get_value_cansleep(da8xx_ohci->oc_gpio) &&
+           da8xx_ohci->vbus_reg) {
+               ret = regulator_disable(da8xx_ohci->vbus_reg);
+               if (ret)
+                       dev_err(dev, "Failed to disable regulator: %d\n", ret);
+       }
 
        return IRQ_HANDLED;
 }
@@ -424,11 +414,6 @@ static int ohci_da8xx_probe(struct platform_device *pdev)
                }
        }
 
-       da8xx_ohci->vbus_gpio = devm_gpiod_get_optional(dev, "vbus",
-                                                       GPIOD_OUT_HIGH);
-       if (IS_ERR(da8xx_ohci->vbus_gpio))
-               goto err;
-
        da8xx_ohci->oc_gpio = devm_gpiod_get_optional(dev, "oc", GPIOD_IN);
        if (IS_ERR(da8xx_ohci->oc_gpio))
                goto err;
@@ -438,8 +423,9 @@ static int ohci_da8xx_probe(struct platform_device *pdev)
                if (oc_irq < 0)
                        goto err;
 
-               error = devm_request_irq(dev, oc_irq, ohci_da8xx_oc_handler,
-                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+               error = devm_request_threaded_irq(dev, oc_irq, NULL,
+                               ohci_da8xx_oc_thread, IRQF_TRIGGER_RISING |
+                               IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                "OHCI over-current indicator", da8xx_ohci);
                if (error)
                        goto err;
index be04c11..c97f270 100644 (file)
@@ -142,7 +142,6 @@ config USB_FTDI_ELAN
 
 config USB_APPLEDISPLAY
        tristate "Apple Cinema Display support"
-       select BACKLIGHT_LCD_SUPPORT
        select BACKLIGHT_CLASS_DEVICE
        help
          Say Y here if you want to control the backlight of Apple Cinema
index 6b64e45..40ddc0c 100644 (file)
@@ -532,7 +532,8 @@ static int tce_iommu_use_page(unsigned long tce, unsigned long *hpa)
        enum dma_data_direction direction = iommu_tce_direction(tce);
 
        if (get_user_pages_fast(tce & PAGE_MASK, 1,
-                       direction != DMA_TO_DEVICE, &page) != 1)
+                       direction != DMA_TO_DEVICE ? FOLL_WRITE : 0,
+                       &page) != 1)
                return -EFAULT;
 
        *hpa = __pa((unsigned long) page_address(page));
index 3be1db3..3ddc375 100644 (file)
@@ -358,7 +358,8 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
 
        down_read(&mm->mmap_sem);
        if (mm == current->mm) {
-               ret = get_user_pages_longterm(vaddr, 1, flags, page, vmas);
+               ret = get_user_pages(vaddr, 1, flags | FOLL_LONGTERM, page,
+                                    vmas);
        } else {
                ret = get_user_pages_remote(NULL, mm, vaddr, 1, flags, page,
                                            vmas, NULL);
index 618fb64..c090d17 100644 (file)
@@ -1443,7 +1443,6 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs,
                        tpg->tv_tpg_vhost_count++;
                        tpg->vhost_scsi = vs;
                        vs_tpg[tpg->tport_tpgt] = tpg;
-                       smp_mb__after_atomic();
                        match = true;
                }
                mutex_unlock(&tpg->tv_tpg_mutex);
index 351af88..1e3ed41 100644 (file)
@@ -1704,7 +1704,7 @@ static int set_bit_to_user(int nr, void __user *addr)
        int bit = nr + (log % PAGE_SIZE) * 8;
        int r;
 
-       r = get_user_pages_fast(log, 1, 1, &page);
+       r = get_user_pages_fast(log, 1, FOLL_WRITE, &page);
        if (r < 0)
                return r;
        BUG_ON(r != 1);
index 71ee978..3ed1d90 100644 (file)
@@ -2,13 +2,7 @@
 # Backlight & LCD drivers configuration
 #
 
-menuconfig BACKLIGHT_LCD_SUPPORT
-       bool "Backlight & LCD device support"
-       help
-         Enable this to be able to choose the drivers for controlling the
-         backlight and the LCD panel on some platforms, for example on PDAs.
-
-if BACKLIGHT_LCD_SUPPORT
+menu "Backlight & LCD device support"
 
 #
 # LCD
@@ -199,7 +193,6 @@ config BACKLIGHT_IPAQ_MICRO
 
 config BACKLIGHT_LM3533
        tristate "Backlight Driver for LM3533"
-       depends on BACKLIGHT_CLASS_DEVICE
        depends on MFD_LM3533
        help
          Say Y to enable the backlight driver for National Semiconductor / TI
@@ -323,7 +316,7 @@ config BACKLIGHT_ADP5520
 
 config BACKLIGHT_ADP8860
        tristate "Backlight Driver for ADP8860/ADP8861/ADP8863 using WLED"
-       depends on BACKLIGHT_CLASS_DEVICE && I2C
+       depends on I2C
        select NEW_LEDS
        select LEDS_CLASS
        help
@@ -335,7 +328,7 @@ config BACKLIGHT_ADP8860
 
 config BACKLIGHT_ADP8870
        tristate "Backlight Driver for ADP8870 using WLED"
-       depends on BACKLIGHT_CLASS_DEVICE && I2C
+       depends on I2C
        select NEW_LEDS
        select LEDS_CLASS
        help
@@ -353,28 +346,28 @@ config BACKLIGHT_88PM860X
 
 config BACKLIGHT_PCF50633
        tristate "Backlight driver for NXP PCF50633 MFD"
-       depends on BACKLIGHT_CLASS_DEVICE && MFD_PCF50633
+       depends on MFD_PCF50633
        help
          If you have a backlight driven by a NXP PCF50633 MFD, say Y here to
          enable its driver.
 
 config BACKLIGHT_AAT2870
        tristate "AnalogicTech AAT2870 Backlight"
-       depends on BACKLIGHT_CLASS_DEVICE && MFD_AAT2870_CORE
+       depends on MFD_AAT2870_CORE
        help
          If you have a AnalogicTech AAT2870 say Y to enable the
          backlight driver.
 
 config BACKLIGHT_LM3630A
        tristate "Backlight Driver for LM3630A"
-       depends on BACKLIGHT_CLASS_DEVICE && I2C && PWM
+       depends on I2C && PWM
        select REGMAP_I2C
        help
          This supports TI LM3630A Backlight Driver
 
 config BACKLIGHT_LM3639
        tristate "Backlight Driver for LM3639"
-       depends on BACKLIGHT_CLASS_DEVICE && I2C
+       depends on I2C
        select REGMAP_I2C
        select NEW_LEDS
        select LEDS_CLASS
@@ -383,20 +376,20 @@ config BACKLIGHT_LM3639
 
 config BACKLIGHT_LP855X
        tristate "Backlight driver for TI LP855X"
-       depends on BACKLIGHT_CLASS_DEVICE && I2C && PWM
+       depends on I2C && PWM
        help
          This supports TI LP8550, LP8551, LP8552, LP8553, LP8555, LP8556 and
          LP8557 backlight driver.
 
 config BACKLIGHT_LP8788
        tristate "Backlight driver for TI LP8788 MFD"
-       depends on BACKLIGHT_CLASS_DEVICE && MFD_LP8788 && PWM
+       depends on MFD_LP8788 && PWM
        help
          This supports TI LP8788 backlight driver.
 
 config BACKLIGHT_OT200
        tristate "Backlight driver for ot200 visualisation device"
-       depends on BACKLIGHT_CLASS_DEVICE && CS5535_MFGPT && GPIO_CS5535
+       depends on CS5535_MFGPT && GPIO_CS5535
        help
          To compile this driver as a module, choose M here: the module will be
          called ot200_bl.
@@ -410,7 +403,7 @@ config BACKLIGHT_PANDORA
 
 config BACKLIGHT_SKY81452
        tristate "Backlight driver for SKY81452"
-       depends on BACKLIGHT_CLASS_DEVICE && MFD_SKY81452
+       depends on MFD_SKY81452
        help
          If you have a Skyworks SKY81452, say Y to enable the
          backlight driver.
@@ -420,14 +413,14 @@ config BACKLIGHT_SKY81452
 
 config BACKLIGHT_TPS65217
        tristate "TPS65217 Backlight"
-       depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217
+       depends on MFD_TPS65217
        help
          If you have a Texas Instruments TPS65217 say Y to enable the
          backlight driver.
 
 config BACKLIGHT_AS3711
        tristate "AS3711 Backlight"
-       depends on BACKLIGHT_CLASS_DEVICE && MFD_AS3711
+       depends on MFD_AS3711
        help
          If you have an Austrian Microsystems AS3711 say Y to enable the
          backlight driver.
@@ -466,4 +459,4 @@ config BACKLIGHT_RAVE_SP
 
 endif # BACKLIGHT_CLASS_DEVICE
 
-endif # BACKLIGHT_LCD_SUPPORT
+endmenu
index 2030a6b..75d9964 100644 (file)
 #define REG_MAX                0x50
 
 #define INT_DEBOUNCE_MSEC      10
+
+#define LM3630A_BANK_0         0
+#define LM3630A_BANK_1         1
+
+#define LM3630A_NUM_SINKS      2
+#define LM3630A_SINK_0         0
+#define LM3630A_SINK_1         1
+
 struct lm3630a_chip {
        struct device *dev;
        struct delayed_work work;
@@ -201,7 +209,7 @@ static int lm3630a_bank_a_update_status(struct backlight_device *bl)
                                      LM3630A_LEDA_ENABLE, LM3630A_LEDA_ENABLE);
        if (ret < 0)
                goto out_i2c_err;
-       return bl->props.brightness;
+       return 0;
 
 out_i2c_err:
        dev_err(pchip->dev, "i2c failed to access\n");
@@ -278,7 +286,7 @@ static int lm3630a_bank_b_update_status(struct backlight_device *bl)
                                      LM3630A_LEDB_ENABLE, LM3630A_LEDB_ENABLE);
        if (ret < 0)
                goto out_i2c_err;
-       return bl->props.brightness;
+       return 0;
 
 out_i2c_err:
        dev_err(pchip->dev, "i2c failed to access REG_CTRL\n");
@@ -329,15 +337,17 @@ static const struct backlight_ops lm3630a_bank_b_ops = {
 
 static int lm3630a_backlight_register(struct lm3630a_chip *pchip)
 {
-       struct backlight_properties props;
        struct lm3630a_platform_data *pdata = pchip->pdata;
+       struct backlight_properties props;
+       const char *label;
 
        props.type = BACKLIGHT_RAW;
        if (pdata->leda_ctrl != LM3630A_LEDA_DISABLE) {
                props.brightness = pdata->leda_init_brt;
                props.max_brightness = pdata->leda_max_brt;
+               label = pdata->leda_label ? pdata->leda_label : "lm3630a_leda";
                pchip->bleda =
-                   devm_backlight_device_register(pchip->dev, "lm3630a_leda",
+                   devm_backlight_device_register(pchip->dev, label,
                                                   pchip->dev, pchip,
                                                   &lm3630a_bank_a_ops, &props);
                if (IS_ERR(pchip->bleda))
@@ -348,8 +358,9 @@ static int lm3630a_backlight_register(struct lm3630a_chip *pchip)
            (pdata->ledb_ctrl != LM3630A_LEDB_ON_A)) {
                props.brightness = pdata->ledb_init_brt;
                props.max_brightness = pdata->ledb_max_brt;
+               label = pdata->ledb_label ? pdata->ledb_label : "lm3630a_ledb";
                pchip->bledb =
-                   devm_backlight_device_register(pchip->dev, "lm3630a_ledb",
+                   devm_backlight_device_register(pchip->dev, label,
                                                   pchip->dev, pchip,
                                                   &lm3630a_bank_b_ops, &props);
                if (IS_ERR(pchip->bledb))
@@ -364,6 +375,123 @@ static const struct regmap_config lm3630a_regmap = {
        .max_register = REG_MAX,
 };
 
+static int lm3630a_parse_led_sources(struct fwnode_handle *node,
+                                    int default_led_sources)
+{
+       u32 sources[LM3630A_NUM_SINKS];
+       int ret, num_sources, i;
+
+       num_sources = fwnode_property_read_u32_array(node, "led-sources", NULL,
+                                                    0);
+       if (num_sources < 0)
+               return default_led_sources;
+       else if (num_sources > ARRAY_SIZE(sources))
+               return -EINVAL;
+
+       ret = fwnode_property_read_u32_array(node, "led-sources", sources,
+                                            num_sources);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < num_sources; i++) {
+               if (sources[i] < LM3630A_SINK_0 || sources[i] > LM3630A_SINK_1)
+                       return -EINVAL;
+
+               ret |= BIT(sources[i]);
+       }
+
+       return ret;
+}
+
+static int lm3630a_parse_bank(struct lm3630a_platform_data *pdata,
+                             struct fwnode_handle *node, int *seen_led_sources)
+{
+       int led_sources, ret;
+       const char *label;
+       u32 bank, val;
+       bool linear;
+
+       ret = fwnode_property_read_u32(node, "reg", &bank);
+       if (ret)
+               return ret;
+
+       if (bank < LM3630A_BANK_0 || bank > LM3630A_BANK_1)
+               return -EINVAL;
+
+       led_sources = lm3630a_parse_led_sources(node, BIT(bank));
+       if (led_sources < 0)
+               return led_sources;
+
+       if (*seen_led_sources & led_sources)
+               return -EINVAL;
+
+       *seen_led_sources |= led_sources;
+
+       linear = fwnode_property_read_bool(node,
+                                          "ti,linear-mapping-mode");
+       if (bank) {
+               if (led_sources & BIT(LM3630A_SINK_0) ||
+                   !(led_sources & BIT(LM3630A_SINK_1)))
+                       return -EINVAL;
+
+               pdata->ledb_ctrl = linear ?
+                       LM3630A_LEDB_ENABLE_LINEAR :
+                       LM3630A_LEDB_ENABLE;
+       } else {
+               if (!(led_sources & BIT(LM3630A_SINK_0)))
+                       return -EINVAL;
+
+               pdata->leda_ctrl = linear ?
+                       LM3630A_LEDA_ENABLE_LINEAR :
+                       LM3630A_LEDA_ENABLE;
+
+               if (led_sources & BIT(LM3630A_SINK_1))
+                       pdata->ledb_ctrl = LM3630A_LEDB_ON_A;
+       }
+
+       ret = fwnode_property_read_string(node, "label", &label);
+       if (!ret) {
+               if (bank)
+                       pdata->ledb_label = label;
+               else
+                       pdata->leda_label = label;
+       }
+
+       ret = fwnode_property_read_u32(node, "default-brightness",
+                                      &val);
+       if (!ret) {
+               if (bank)
+                       pdata->ledb_init_brt = val;
+               else
+                       pdata->leda_init_brt = val;
+       }
+
+       ret = fwnode_property_read_u32(node, "max-brightness", &val);
+       if (!ret) {
+               if (bank)
+                       pdata->ledb_max_brt = val;
+               else
+                       pdata->leda_max_brt = val;
+       }
+
+       return 0;
+}
+
+static int lm3630a_parse_node(struct lm3630a_chip *pchip,
+                             struct lm3630a_platform_data *pdata)
+{
+       int ret = -ENODEV, seen_led_sources = 0;
+       struct fwnode_handle *node;
+
+       device_for_each_child_node(pchip->dev, node) {
+               ret = lm3630a_parse_bank(pdata, node, &seen_led_sources);
+               if (ret)
+                       return ret;
+       }
+
+       return ret;
+}
+
 static int lm3630a_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
@@ -396,13 +524,18 @@ static int lm3630a_probe(struct i2c_client *client,
                                     GFP_KERNEL);
                if (pdata == NULL)
                        return -ENOMEM;
+
                /* default values */
-               pdata->leda_ctrl = LM3630A_LEDA_ENABLE;
-               pdata->ledb_ctrl = LM3630A_LEDB_ENABLE;
                pdata->leda_max_brt = LM3630A_MAX_BRIGHTNESS;
                pdata->ledb_max_brt = LM3630A_MAX_BRIGHTNESS;
                pdata->leda_init_brt = LM3630A_MAX_BRIGHTNESS;
                pdata->ledb_init_brt = LM3630A_MAX_BRIGHTNESS;
+
+               rval = lm3630a_parse_node(pchip, pdata);
+               if (rval) {
+                       dev_err(&client->dev, "fail : parse node\n");
+                       return rval;
+               }
        }
        pchip->pdata = pdata;
 
@@ -470,11 +603,17 @@ static const struct i2c_device_id lm3630a_id[] = {
        {}
 };
 
+static const struct of_device_id lm3630a_match_table[] = {
+       { .compatible = "ti,lm3630a", },
+       { },
+};
+
 MODULE_DEVICE_TABLE(i2c, lm3630a_id);
 
 static struct i2c_driver lm3630a_i2c_driver = {
        .driver = {
                   .name = LM3630A_NAME,
+                  .of_match_table = lm3630a_match_table,
                   },
        .probe = lm3630a_probe,
        .remove = lm3630a_remove,
index 53b8cee..fb45f86 100644 (file)
@@ -155,21 +155,6 @@ static const struct backlight_ops pwm_backlight_ops = {
 #ifdef CONFIG_OF
 #define PWM_LUMINANCE_SCALE    10000 /* luminance scale */
 
-/* An integer based power function */
-static u64 int_pow(u64 base, int exp)
-{
-       u64 result = 1;
-
-       while (exp) {
-               if (exp & 1)
-                       result *= base;
-               exp >>= 1;
-               base *= base;
-       }
-
-       return result;
-}
-
 /*
  * CIE lightness to PWM conversion.
  *
index 47ecf9a..bf6b77b 100644 (file)
@@ -186,7 +186,6 @@ config FB_MACMODES
 config FB_BACKLIGHT
        tristate
        depends on FB
-       select BACKLIGHT_LCD_SUPPORT
        select BACKLIGHT_CLASS_DEVICE
 
 config FB_MODE_HELPERS
@@ -281,7 +280,6 @@ config FB_ARMCLCD
        select FB_CFB_IMAGEBLIT
        select FB_MODE_HELPERS if OF
        select VIDEOMODE_HELPERS if OF
-       select BACKLIGHT_LCD_SUPPORT if OF
        select BACKLIGHT_CLASS_DEVICE if OF
        help
          This framebuffer device driver is for the ARM PrimeCell PL110
@@ -307,7 +305,6 @@ config FB_ACORN
 config FB_CLPS711X
        tristate "CLPS711X LCD support"
        depends on FB && (ARCH_CLPS711X || COMPILE_TEST)
-       select BACKLIGHT_LCD_SUPPORT
        select FB_MODE_HELPERS
        select FB_SYS_FILLRECT
        select FB_SYS_COPYAREA
@@ -335,7 +332,6 @@ config FB_SA1100
 config FB_IMX
        tristate "Freescale i.MX1/21/25/27 LCD support"
        depends on FB && ARCH_MXC
-       select BACKLIGHT_LCD_SUPPORT
        select LCD_CLASS_DEVICE
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
@@ -2184,7 +2180,6 @@ config FB_MX3
        tristate "MX3 Framebuffer support"
        depends on FB && MX3_IPU
        select BACKLIGHT_CLASS_DEVICE
-       select BACKLIGHT_LCD_SUPPORT
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
index d9e816d..1bddcc2 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/console.h>
 #include <linux/mm.h>
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/pgtable.h>
 #include <mach/hardware.h>
 
index dfed532..4e4d6a0 100644 (file)
@@ -686,7 +686,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
        if (!pages)
                return -ENOMEM;
 
-       ret = get_user_pages_fast((unsigned long)buf, nr_pages, true, pages);
+       ret = get_user_pages_fast((unsigned long)buf, nr_pages, FOLL_WRITE, pages);
        if (ret < nr_pages) {
                nr_pages = ret;
                ret = -EINVAL;
index 8ba726e..93d5beb 100644 (file)
@@ -215,6 +215,9 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
         * hypervisor.
         */
        lb_offset = param.local_vaddr & (PAGE_SIZE - 1);
+       if (param.count == 0 ||
+           param.count > U64_MAX - lb_offset - PAGE_SIZE + 1)
+               return -EINVAL;
        num_pages = (param.count + lb_offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
        /* Allocate the buffers we need */
@@ -244,7 +247,7 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
 
        /* Get the physical addresses of the source buffer */
        num_pinned = get_user_pages_fast(param.local_vaddr - lb_offset,
-               num_pages, param.source != -1, pages);
+               num_pages, param.source != -1 ? FOLL_WRITE : 0, pages);
 
        if (num_pinned != num_pages) {
                /* get_user_pages() failed */
@@ -331,8 +334,8 @@ static long ioctl_dtprop(struct fsl_hv_ioctl_prop __user *p, int set)
        struct fsl_hv_ioctl_prop param;
        char __user *upath, *upropname;
        void __user *upropval;
-       char *path = NULL, *propname = NULL;
-       void *propval = NULL;
+       char *path, *propname;
+       void *propval;
        int ret = 0;
 
        /* Get the parameters from the user. */
@@ -344,32 +347,30 @@ static long ioctl_dtprop(struct fsl_hv_ioctl_prop __user *p, int set)
        upropval = (void __user *)(uintptr_t)param.propval;
 
        path = strndup_user(upath, FH_DTPROP_MAX_PATHLEN);
-       if (IS_ERR(path)) {
-               ret = PTR_ERR(path);
-               goto out;
-       }
+       if (IS_ERR(path))
+               return PTR_ERR(path);
 
        propname = strndup_user(upropname, FH_DTPROP_MAX_PATHLEN);
        if (IS_ERR(propname)) {
                ret = PTR_ERR(propname);
-               goto out;
+               goto err_free_path;
        }
 
        if (param.proplen > FH_DTPROP_MAX_PROPLEN) {
                ret = -EINVAL;
-               goto out;
+               goto err_free_propname;
        }
 
        propval = kmalloc(param.proplen, GFP_KERNEL);
        if (!propval) {
                ret = -ENOMEM;
-               goto out;
+               goto err_free_propname;
        }
 
        if (set) {
                if (copy_from_user(propval, upropval, param.proplen)) {
                        ret = -EFAULT;
-                       goto out;
+                       goto err_free_propval;
                }
 
                param.ret = fh_partition_set_dtprop(param.handle,
@@ -388,7 +389,7 @@ static long ioctl_dtprop(struct fsl_hv_ioctl_prop __user *p, int set)
                        if (copy_to_user(upropval, propval, param.proplen) ||
                            put_user(param.proplen, &p->proplen)) {
                                ret = -EFAULT;
-                               goto out;
+                               goto err_free_propval;
                        }
                }
        }
@@ -396,10 +397,12 @@ static long ioctl_dtprop(struct fsl_hv_ioctl_prop __user *p, int set)
        if (put_user(param.ret, &p->ret))
                ret = -EFAULT;
 
-out:
-       kfree(path);
+err_free_propval:
        kfree(propval);
+err_free_propname:
        kfree(propname);
+err_free_path:
+       kfree(path);
 
        return ret;
 }
index 5df92c3..0a7b3ce 100644 (file)
@@ -1004,6 +1004,7 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq,
 
        if (unlikely(vq->vq.num_free < 1)) {
                pr_debug("Can't add buf len 1 - avail = 0\n");
+               kfree(desc);
                END_USE(vq);
                return -ENOSPC;
        }
@@ -1718,10 +1719,10 @@ static inline int virtqueue_add(struct virtqueue *_vq,
 
 /**
  * virtqueue_add_sgs - expose buffers to other end
- * @vq: the struct virtqueue we're talking about.
+ * @_vq: the struct virtqueue we're talking about.
  * @sgs: array of terminated scatterlists.
- * @out_num: the number of scatterlists readable by other side
- * @in_num: the number of scatterlists which are writable (after readable ones)
+ * @out_sgs: the number of scatterlists readable by other side
+ * @in_sgs: the number of scatterlists which are writable (after readable ones)
  * @data: the token identifying the buffer.
  * @gfp: how to do memory allocations (if necessary).
  *
@@ -1821,7 +1822,7 @@ EXPORT_SYMBOL_GPL(virtqueue_add_inbuf_ctx);
 
 /**
  * virtqueue_kick_prepare - first half of split virtqueue_kick call.
- * @vq: the struct virtqueue
+ * @_vq: the struct virtqueue
  *
  * Instead of virtqueue_kick(), you can do:
  *     if (virtqueue_kick_prepare(vq))
@@ -1841,7 +1842,7 @@ EXPORT_SYMBOL_GPL(virtqueue_kick_prepare);
 
 /**
  * virtqueue_notify - second half of split virtqueue_kick call.
- * @vq: the struct virtqueue
+ * @_vq: the struct virtqueue
  *
  * This does not need to be serialized.
  *
@@ -1885,8 +1886,9 @@ EXPORT_SYMBOL_GPL(virtqueue_kick);
 
 /**
  * virtqueue_get_buf - get the next used buffer
- * @vq: the struct virtqueue we're talking about.
+ * @_vq: the struct virtqueue we're talking about.
  * @len: the length written into the buffer
+ * @ctx: extra context for the token
  *
  * If the device wrote data into the buffer, @len will be set to the
  * amount written.  This means you don't need to clear the buffer
@@ -1916,7 +1918,7 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
 EXPORT_SYMBOL_GPL(virtqueue_get_buf);
 /**
  * virtqueue_disable_cb - disable callbacks
- * @vq: the struct virtqueue we're talking about.
+ * @_vq: the struct virtqueue we're talking about.
  *
  * Note that this is not necessarily synchronous, hence unreliable and only
  * useful as an optimization.
@@ -1936,7 +1938,7 @@ EXPORT_SYMBOL_GPL(virtqueue_disable_cb);
 
 /**
  * virtqueue_enable_cb_prepare - restart callbacks after disable_cb
- * @vq: the struct virtqueue we're talking about.
+ * @_vq: the struct virtqueue we're talking about.
  *
  * This re-enables callbacks; it returns current queue state
  * in an opaque unsigned value. This value should be later tested by
@@ -1957,7 +1959,7 @@ EXPORT_SYMBOL_GPL(virtqueue_enable_cb_prepare);
 
 /**
  * virtqueue_poll - query pending used buffers
- * @vq: the struct virtqueue we're talking about.
+ * @_vq: the struct virtqueue we're talking about.
  * @last_used_idx: virtqueue state (from call to virtqueue_enable_cb_prepare).
  *
  * Returns "true" if there are pending used buffers in the queue.
@@ -1976,7 +1978,7 @@ EXPORT_SYMBOL_GPL(virtqueue_poll);
 
 /**
  * virtqueue_enable_cb - restart callbacks after disable_cb.
- * @vq: the struct virtqueue we're talking about.
+ * @_vq: the struct virtqueue we're talking about.
  *
  * This re-enables callbacks; it returns "false" if there are pending
  * buffers in the queue, to detect a possible race between the driver
@@ -1995,7 +1997,7 @@ EXPORT_SYMBOL_GPL(virtqueue_enable_cb);
 
 /**
  * virtqueue_enable_cb_delayed - restart callbacks after disable_cb.
- * @vq: the struct virtqueue we're talking about.
+ * @_vq: the struct virtqueue we're talking about.
  *
  * This re-enables callbacks but hints to the other side to delay
  * interrupts until most of the available buffers have been processed;
@@ -2017,7 +2019,7 @@ EXPORT_SYMBOL_GPL(virtqueue_enable_cb_delayed);
 
 /**
  * virtqueue_detach_unused_buf - detach first unused buffer
- * @vq: the struct virtqueue we're talking about.
+ * @_vq: the struct virtqueue we're talking about.
  *
  * Returns NULL or the "data" token handed to virtqueue_add_*().
  * This is not valid on an active queue; it is useful only for device
@@ -2249,7 +2251,7 @@ EXPORT_SYMBOL_GPL(vring_transport_features);
 
 /**
  * virtqueue_get_vring_size - return the size of the virtqueue's vring
- * @vq: the struct virtqueue containing the vring of interest.
+ * @_vq: the struct virtqueue containing the vring of interest.
  *
  * Returns the size of the vring.  This is mainly used for boasting to
  * userspace.  Unlike other operations, this need not be serialized.
index dd139cd..9067998 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
+#include <linux/of.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
@@ -176,6 +177,14 @@ static int __init ixp4xx_wdt_init(void)
 {
        int ret;
 
+       /*
+        * FIXME: we bail out on device tree boot but this really needs
+        * to be fixed in a nicer way: this registers the MDIO bus before
+        * even matching the driver infrastructure, we should only probe
+        * detected hardware.
+        */
+       if (of_have_populated_dt())
+               return -ENODEV;
        if (!(read_cpuid_id() & 0xf) && !cpu_is_ixp46x()) {
                pr_err("Rev. A0 IXP42x CPU detected - watchdog disabled\n");
 
index 7cf9c51..469dfbd 100644 (file)
@@ -526,20 +526,20 @@ static int mn_invl_range_start(struct mmu_notifier *mn,
        struct gntdev_grant_map *map;
        int ret = 0;
 
-       if (range->blockable)
+       if (mmu_notifier_range_blockable(range))
                mutex_lock(&priv->lock);
        else if (!mutex_trylock(&priv->lock))
                return -EAGAIN;
 
        list_for_each_entry(map, &priv->maps, next) {
                ret = unmap_if_in_range(map, range->start, range->end,
-                                       range->blockable);
+                                       mmu_notifier_range_blockable(range));
                if (ret)
                        goto out_unlock;
        }
        list_for_each_entry(map, &priv->freeable_maps, next) {
                ret = unmap_if_in_range(map, range->start, range->end,
-                                       range->blockable);
+                                       mmu_notifier_range_blockable(range));
                if (ret)
                        goto out_unlock;
        }
@@ -852,7 +852,7 @@ static int gntdev_get_page(struct gntdev_copy_batch *batch, void __user *virt,
        unsigned long xen_pfn;
        int ret;
 
-       ret = get_user_pages_fast(addr, 1, writeable, &page);
+       ret = get_user_pages_fast(addr, 1, writeable ? FOLL_WRITE : 0, &page);
        if (ret < 0)
                return ret;
 
@@ -1084,7 +1084,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
        int index = vma->vm_pgoff;
        int count = vma_pages(vma);
        struct gntdev_grant_map *map;
-       int i, err = -EINVAL;
+       int err = -EINVAL;
 
        if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED))
                return -EINVAL;
@@ -1145,12 +1145,9 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
                goto out_put_map;
 
        if (!use_ptemod) {
-               for (i = 0; i < count; i++) {
-                       err = vm_insert_page(vma, vma->vm_start + i*PAGE_SIZE,
-                               map->pages[i]);
-                       if (err)
-                               goto out_put_map;
-               }
+               err = vm_map_pages(vma, map->pages, map->count);
+               if (err)
+                       goto out_put_map;
        } else {
 #ifdef CONFIG_X86
                /*
index a1c61e3..dd5bbb6 100644 (file)
@@ -165,12 +165,8 @@ static int privcmd_buf_mmap(struct file *file, struct vm_area_struct *vma)
        if (vma_priv->n_pages != count)
                ret = -ENOMEM;
        else
-               for (i = 0; i < vma_priv->n_pages; i++) {
-                       ret = vm_insert_page(vma, vma->vm_start + i * PAGE_SIZE,
-                                            vma_priv->pages[i]);
-                       if (ret)
-                               break;
-               }
+               ret = vm_map_pages_zero(vma, vma_priv->pages,
+                                               vma_priv->n_pages);
 
        if (ret)
                privcmd_buf_vmapriv_free(vma_priv);
index 23f7f6e..833b2d2 100644 (file)
@@ -697,7 +697,7 @@ static int xen_pcibk_xenbus_probe(struct xenbus_device *dev,
        /* We need to force a call to our callback here in case
         * xend already configured us!
         */
-       xen_pcibk_be_watch(&pdev->be_watch, NULL, 0);
+       xen_pcibk_be_watch(&pdev->be_watch, NULL, NULL);
 
 out:
        return err;
index 0782ff3..faf452d 100644 (file)
@@ -465,7 +465,6 @@ static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u)
        struct watch_adapter *watch;
        char *path, *token;
        int err, rc;
-       LIST_HEAD(staging_q);
 
        path = u->u.buffer + sizeof(u->u.msg);
        token = memchr(path, 0, u->u.msg.len);
@@ -523,7 +522,6 @@ static ssize_t xenbus_file_write(struct file *filp,
        uint32_t msg_type;
        int rc = len;
        int ret;
-       LIST_HEAD(staging_q);
 
        /*
         * We're expecting usermode to be writing properly formed
index 967db33..9eaff55 100644 (file)
@@ -251,7 +251,7 @@ struct afs_vlserver_list *afs_dns_query(struct afs_cell *cell, time64_t *_expiry
        _enter("%s", cell->name);
 
        ret = dns_query("afsdb", cell->name, cell->name_len, "srv=1",
-                       &result, _expiry);
+                       &result, _expiry, true);
        if (ret < 0) {
                _leave(" = %d [dns]", ret);
                return ERR_PTR(ret);
index d12ffb4..3f4e460 100644 (file)
@@ -23,6 +23,9 @@
 #define AFSPATHMAX             1024    /* Maximum length of a pathname plus NUL */
 #define AFSOPAQUEMAX           1024    /* Maximum length of an opaque field */
 
+#define AFS_VL_MAX_LIFESPAN    (120 * HZ)
+#define AFS_PROBE_MAX_LIFESPAN (30 * HZ)
+
 typedef u64                    afs_volid_t;
 typedef u64                    afs_vnodeid_t;
 typedef u64                    afs_dataversion_t;
@@ -69,8 +72,8 @@ typedef enum {
 
 struct afs_callback {
        time64_t                expires_at;     /* Time at which expires */
-       unsigned                version;        /* Callback version */
-       afs_callback_type_t     type;           /* Type of callback */
+       //unsigned              version;        /* Callback version */
+       //afs_callback_type_t   type;           /* Type of callback */
 };
 
 struct afs_callback_break {
@@ -144,6 +147,15 @@ struct afs_file_status {
        u32                     abort_code;     /* Abort if bulk-fetching this failed */
 };
 
+struct afs_status_cb {
+       struct afs_file_status  status;
+       struct afs_callback     callback;
+       unsigned int            cb_break;       /* Pre-op callback break counter */
+       bool                    have_status;    /* True if status record was retrieved */
+       bool                    have_cb;        /* True if cb record was retrieved */
+       bool                    have_error;     /* True if status.abort_code indicates an error */
+};
+
 /*
  * AFS file status change request
  */
index 128f2db..d441bef 100644 (file)
@@ -94,15 +94,15 @@ int afs_register_server_cb_interest(struct afs_vnode *vnode,
        struct afs_server *server = entry->server;
 
 again:
-       if (vnode->cb_interest &&
-           likely(vnode->cb_interest == entry->cb_interest))
+       vcbi = rcu_dereference_protected(vnode->cb_interest,
+                                        lockdep_is_held(&vnode->io_lock));
+       if (vcbi && likely(vcbi == entry->cb_interest))
                return 0;
 
        read_lock(&slist->lock);
        cbi = afs_get_cb_interest(entry->cb_interest);
        read_unlock(&slist->lock);
 
-       vcbi = vnode->cb_interest;
        if (vcbi) {
                if (vcbi == cbi) {
                        afs_put_cb_interest(afs_v2net(vnode), cbi);
@@ -114,8 +114,9 @@ again:
                 */
                if (cbi && vcbi->server == cbi->server) {
                        write_seqlock(&vnode->cb_lock);
-                       old = vnode->cb_interest;
-                       vnode->cb_interest = cbi;
+                       old = rcu_dereference_protected(vnode->cb_interest,
+                                                       lockdep_is_held(&vnode->cb_lock.lock));
+                       rcu_assign_pointer(vnode->cb_interest, cbi);
                        write_sequnlock(&vnode->cb_lock);
                        afs_put_cb_interest(afs_v2net(vnode), old);
                        return 0;
@@ -160,8 +161,9 @@ again:
         */
        write_seqlock(&vnode->cb_lock);
 
-       old = vnode->cb_interest;
-       vnode->cb_interest = cbi;
+       old = rcu_dereference_protected(vnode->cb_interest,
+                                       lockdep_is_held(&vnode->cb_lock.lock));
+       rcu_assign_pointer(vnode->cb_interest, cbi);
        vnode->cb_s_break = cbi->server->cb_s_break;
        vnode->cb_v_break = vnode->volume->cb_v_break;
        clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
@@ -191,10 +193,11 @@ void afs_put_cb_interest(struct afs_net *net, struct afs_cb_interest *cbi)
                                vi = NULL;
 
                        write_unlock(&cbi->server->cb_break_lock);
-                       kfree(vi);
+                       if (vi)
+                               kfree_rcu(vi, rcu);
                        afs_put_server(net, cbi->server);
                }
-               kfree(cbi);
+               kfree_rcu(cbi, rcu);
        }
 }
 
@@ -218,14 +221,8 @@ void __afs_break_callback(struct afs_vnode *vnode)
                vnode->cb_break++;
                afs_clear_permits(vnode);
 
-               spin_lock(&vnode->lock);
-
-               _debug("break callback");
-
-               if (list_empty(&vnode->granted_locks) &&
-                   !list_empty(&vnode->pending_locks))
+               if (vnode->lock_state == AFS_VNODE_LOCK_WAITING_FOR_CB)
                        afs_lock_may_be_available(vnode);
-               spin_unlock(&vnode->lock);
        }
 }
 
index 9de4611..9c3b07b 100644 (file)
@@ -123,6 +123,7 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
                                       const char *name, unsigned int namelen,
                                       const char *addresses)
 {
+       struct afs_vlserver_list *vllist;
        struct afs_cell *cell;
        int i, ret;
 
@@ -151,18 +152,14 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
 
        atomic_set(&cell->usage, 2);
        INIT_WORK(&cell->manager, afs_manage_cell);
-       cell->flags = ((1 << AFS_CELL_FL_NOT_READY) |
-                      (1 << AFS_CELL_FL_NO_LOOKUP_YET));
        INIT_LIST_HEAD(&cell->proc_volumes);
        rwlock_init(&cell->proc_lock);
        rwlock_init(&cell->vl_servers_lock);
 
-       /* Fill in the VL server list if we were given a list of addresses to
-        * use.
+       /* Provide a VL server list, filling it in if we were given a list of
+        * addresses to use.
         */
        if (addresses) {
-               struct afs_vlserver_list *vllist;
-
                vllist = afs_parse_text_addrs(net,
                                              addresses, strlen(addresses), ':',
                                              VL_SERVICE, AFS_VL_PORT);
@@ -171,19 +168,32 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
                        goto parse_failed;
                }
 
-               rcu_assign_pointer(cell->vl_servers, vllist);
+               vllist->source = DNS_RECORD_FROM_CONFIG;
+               vllist->status = DNS_LOOKUP_NOT_DONE;
                cell->dns_expiry = TIME64_MAX;
-               __clear_bit(AFS_CELL_FL_NO_LOOKUP_YET, &cell->flags);
        } else {
+               ret = -ENOMEM;
+               vllist = afs_alloc_vlserver_list(0);
+               if (!vllist)
+                       goto error;
+               vllist->source = DNS_RECORD_UNAVAILABLE;
+               vllist->status = DNS_LOOKUP_NOT_DONE;
                cell->dns_expiry = ktime_get_real_seconds();
        }
 
+       rcu_assign_pointer(cell->vl_servers, vllist);
+
+       cell->dns_source = vllist->source;
+       cell->dns_status = vllist->status;
+       smp_store_release(&cell->dns_lookup_count, 1); /* vs source/status */
+
        _leave(" = %p", cell);
        return cell;
 
 parse_failed:
        if (ret == -EINVAL)
                printk(KERN_ERR "kAFS: bad VL server IP address\n");
+error:
        kfree(cell);
        _leave(" = %d", ret);
        return ERR_PTR(ret);
@@ -208,6 +218,7 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
 {
        struct afs_cell *cell, *candidate, *cursor;
        struct rb_node *parent, **pp;
+       enum afs_cell_state state;
        int ret, n;
 
        _enter("%s,%s", name, vllist);
@@ -267,18 +278,16 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
 
 wait_for_cell:
        _debug("wait_for_cell");
-       ret = wait_on_bit(&cell->flags, AFS_CELL_FL_NOT_READY, TASK_INTERRUPTIBLE);
-       smp_rmb();
-
-       switch (READ_ONCE(cell->state)) {
-       case AFS_CELL_FAILED:
+       wait_var_event(&cell->state,
+                      ({
+                              state = smp_load_acquire(&cell->state); /* vs error */
+                              state == AFS_CELL_ACTIVE || state == AFS_CELL_FAILED;
+                      }));
+
+       /* Check the state obtained from the wait check. */
+       if (state == AFS_CELL_FAILED) {
                ret = cell->error;
                goto error;
-       default:
-               _debug("weird %u %d", cell->state, cell->error);
-               goto error;
-       case AFS_CELL_ACTIVE:
-               break;
        }
 
        _leave(" = %p [cell]", cell);
@@ -360,16 +369,46 @@ int afs_cell_init(struct afs_net *net, const char *rootcell)
 /*
  * Update a cell's VL server address list from the DNS.
  */
-static void afs_update_cell(struct afs_cell *cell)
+static int afs_update_cell(struct afs_cell *cell)
 {
-       struct afs_vlserver_list *vllist, *old;
+       struct afs_vlserver_list *vllist, *old = NULL, *p;
        unsigned int min_ttl = READ_ONCE(afs_cell_min_ttl);
        unsigned int max_ttl = READ_ONCE(afs_cell_max_ttl);
        time64_t now, expiry = 0;
+       int ret = 0;
 
        _enter("%s", cell->name);
 
        vllist = afs_dns_query(cell, &expiry);
+       if (IS_ERR(vllist)) {
+               ret = PTR_ERR(vllist);
+
+               _debug("%s: fail %d", cell->name, ret);
+               if (ret == -ENOMEM)
+                       goto out_wake;
+
+               ret = -ENOMEM;
+               vllist = afs_alloc_vlserver_list(0);
+               if (!vllist)
+                       goto out_wake;
+
+               switch (ret) {
+               case -ENODATA:
+               case -EDESTADDRREQ:
+                       vllist->status = DNS_LOOKUP_GOT_NOT_FOUND;
+                       break;
+               case -EAGAIN:
+               case -ECONNREFUSED:
+                       vllist->status = DNS_LOOKUP_GOT_TEMP_FAILURE;
+                       break;
+               default:
+                       vllist->status = DNS_LOOKUP_GOT_LOCAL_FAILURE;
+                       break;
+               }
+       }
+
+       _debug("%s: got list %d %d", cell->name, vllist->source, vllist->status);
+       cell->dns_status = vllist->status;
 
        now = ktime_get_real_seconds();
        if (min_ttl > max_ttl)
@@ -379,48 +418,47 @@ static void afs_update_cell(struct afs_cell *cell)
        else if (expiry > now + max_ttl)
                expiry = now + max_ttl;
 
-       if (IS_ERR(vllist)) {
-               switch (PTR_ERR(vllist)) {
-               case -ENODATA:
-               case -EDESTADDRREQ:
+       _debug("%s: status %d", cell->name, vllist->status);
+       if (vllist->source == DNS_RECORD_UNAVAILABLE) {
+               switch (vllist->status) {
+               case DNS_LOOKUP_GOT_NOT_FOUND:
                        /* The DNS said that the cell does not exist or there
                         * weren't any addresses to be had.
                         */
-                       set_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags);
-                       clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
                        cell->dns_expiry = expiry;
                        break;
 
-               case -EAGAIN:
-               case -ECONNREFUSED:
+               case DNS_LOOKUP_BAD:
+               case DNS_LOOKUP_GOT_LOCAL_FAILURE:
+               case DNS_LOOKUP_GOT_TEMP_FAILURE:
+               case DNS_LOOKUP_GOT_NS_FAILURE:
                default:
-                       set_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
                        cell->dns_expiry = now + 10;
                        break;
                }
-
-               cell->error = -EDESTADDRREQ;
        } else {
-               clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
-               clear_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags);
-
-               /* Exclusion on changing vl_addrs is achieved by a
-                * non-reentrant work item.
-                */
-               old = rcu_dereference_protected(cell->vl_servers, true);
-               rcu_assign_pointer(cell->vl_servers, vllist);
                cell->dns_expiry = expiry;
-
-               if (old)
-                       afs_put_vlserverlist(cell->net, old);
        }
 
-       if (test_and_clear_bit(AFS_CELL_FL_NO_LOOKUP_YET, &cell->flags))
-               wake_up_bit(&cell->flags, AFS_CELL_FL_NO_LOOKUP_YET);
+       /* Replace the VL server list if the new record has servers or the old
+        * record doesn't.
+        */
+       write_lock(&cell->vl_servers_lock);
+       p = rcu_dereference_protected(cell->vl_servers, true);
+       if (vllist->nr_servers > 0 || p->nr_servers == 0) {
+               rcu_assign_pointer(cell->vl_servers, vllist);
+               cell->dns_source = vllist->source;
+               old = p;
+       }
+       write_unlock(&cell->vl_servers_lock);
+       afs_put_vlserverlist(cell->net, old);
 
-       now = ktime_get_real_seconds();
-       afs_set_cell_timer(cell->net, cell->dns_expiry - now);
-       _leave("");
+out_wake:
+       smp_store_release(&cell->dns_lookup_count,
+                         cell->dns_lookup_count + 1); /* vs source/status */
+       wake_up_var(&cell->dns_lookup_count);
+       _leave(" = %d", ret);
+       return ret;
 }
 
 /*
@@ -491,8 +529,7 @@ void afs_put_cell(struct afs_net *net, struct afs_cell *cell)
        now = ktime_get_real_seconds();
        cell->last_inactive = now;
        expire_delay = 0;
-       if (!test_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags) &&
-           !test_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags))
+       if (cell->vl_servers->nr_servers)
                expire_delay = afs_cell_gc_delay;
 
        if (atomic_dec_return(&cell->usage) > 1)
@@ -623,11 +660,13 @@ again:
                        goto final_destruction;
                if (cell->state == AFS_CELL_FAILED)
                        goto done;
-               cell->state = AFS_CELL_UNSET;
+               smp_store_release(&cell->state, AFS_CELL_UNSET);
+               wake_up_var(&cell->state);
                goto again;
 
        case AFS_CELL_UNSET:
-               cell->state = AFS_CELL_ACTIVATING;
+               smp_store_release(&cell->state, AFS_CELL_ACTIVATING);
+               wake_up_var(&cell->state);
                goto again;
 
        case AFS_CELL_ACTIVATING:
@@ -635,28 +674,29 @@ again:
                if (ret < 0)
                        goto activation_failed;
 
-               cell->state = AFS_CELL_ACTIVE;
-               smp_wmb();
-               clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags);
-               wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY);
+               smp_store_release(&cell->state, AFS_CELL_ACTIVE);
+               wake_up_var(&cell->state);
                goto again;
 
        case AFS_CELL_ACTIVE:
                if (atomic_read(&cell->usage) > 1) {
-                       time64_t now = ktime_get_real_seconds();
-                       if (cell->dns_expiry <= now && net->live)
-                               afs_update_cell(cell);
+                       if (test_and_clear_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags)) {
+                               ret = afs_update_cell(cell);
+                               if (ret < 0)
+                                       cell->error = ret;
+                       }
                        goto done;
                }
-               cell->state = AFS_CELL_DEACTIVATING;
+               smp_store_release(&cell->state, AFS_CELL_DEACTIVATING);
+               wake_up_var(&cell->state);
                goto again;
 
        case AFS_CELL_DEACTIVATING:
-               set_bit(AFS_CELL_FL_NOT_READY, &cell->flags);
                if (atomic_read(&cell->usage) > 1)
                        goto reverse_deactivation;
                afs_deactivate_cell(net, cell);
-               cell->state = AFS_CELL_INACTIVE;
+               smp_store_release(&cell->state, AFS_CELL_INACTIVE);
+               wake_up_var(&cell->state);
                goto again;
 
        default:
@@ -669,17 +709,13 @@ activation_failed:
        cell->error = ret;
        afs_deactivate_cell(net, cell);
 
-       cell->state = AFS_CELL_FAILED;
-       smp_wmb();
-       if (test_and_clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags))
-               wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY);
+       smp_store_release(&cell->state, AFS_CELL_FAILED); /* vs error */
+       wake_up_var(&cell->state);
        goto again;
 
 reverse_deactivation:
-       cell->state = AFS_CELL_ACTIVE;
-       smp_wmb();
-       clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags);
-       wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY);
+       smp_store_release(&cell->state, AFS_CELL_ACTIVE);
+       wake_up_var(&cell->state);
        _leave(" [deact->act]");
        return;
 
@@ -739,11 +775,16 @@ void afs_manage_cells(struct work_struct *work)
                }
 
                if (usage == 1) {
+                       struct afs_vlserver_list *vllist;
                        time64_t expire_at = cell->last_inactive;
 
-                       if (!test_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags) &&
-                           !test_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags))
+                       read_lock(&cell->vl_servers_lock);
+                       vllist = rcu_dereference_protected(
+                               cell->vl_servers,
+                               lockdep_is_held(&cell->vl_servers_lock));
+                       if (vllist->nr_servers > 0)
                                expire_at += afs_cell_gc_delay;
+                       read_unlock(&cell->vl_servers_lock);
                        if (purging || expire_at <= now)
                                sched_cell = true;
                        else if (expire_at < next_manage)
@@ -751,10 +792,8 @@ void afs_manage_cells(struct work_struct *work)
                }
 
                if (!purging) {
-                       if (cell->dns_expiry <= now)
+                       if (test_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags))
                                sched_cell = true;
-                       else if (cell->dns_expiry <= next_manage)
-                               next_manage = cell->dns_expiry;
                }
 
                if (sched_cell)
index 7480900..01437cf 100644 (file)
@@ -213,7 +213,7 @@ static int afs_find_cm_server_by_peer(struct afs_call *call)
                return 0;
        }
 
-       call->cm_server = server;
+       call->server = server;
        return afs_record_cm_probe(call, server);
 }
 
@@ -234,7 +234,7 @@ static int afs_find_cm_server_by_uuid(struct afs_call *call,
                return 0;
        }
 
-       call->cm_server = server;
+       call->server = server;
        return afs_record_cm_probe(call, server);
 }
 
@@ -260,8 +260,8 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
         * server holds up change visibility till it receives our reply so as
         * to maintain cache coherency.
         */
-       if (call->cm_server)
-               afs_break_callbacks(call->cm_server, call->count, call->request);
+       if (call->server)
+               afs_break_callbacks(call->server, call->count, call->request);
 
        afs_send_empty_reply(call);
        afs_put_call(call);
@@ -376,10 +376,10 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work)
 {
        struct afs_call *call = container_of(work, struct afs_call, work);
 
-       _enter("{%p}", call->cm_server);
+       _enter("{%p}", call->server);
 
-       if (call->cm_server)
-               afs_init_callback_state(call->cm_server);
+       if (call->server)
+               afs_init_callback_state(call->server);
        afs_send_empty_reply(call);
        afs_put_call(call);
        _leave("");
index 9a466be..79d93a2 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/sched.h>
 #include <linux/task_io_accounting_ops.h>
 #include "internal.h"
+#include "afs_fs.h"
 #include "xdr_fs.h"
 
 static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
@@ -102,8 +103,8 @@ struct afs_lookup_cookie {
        bool                    found;
        bool                    one_only;
        unsigned short          nr_fids;
-       struct afs_file_status  *statuses;
-       struct afs_callback     *callbacks;
+       struct inode            **inodes;
+       struct afs_status_cb    *statuses;
        struct afs_fid          fids[50];
 };
 
@@ -638,12 +639,14 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
                                   struct key *key)
 {
        struct afs_lookup_cookie *cookie;
-       struct afs_cb_interest *cbi = NULL;
+       struct afs_cb_interest *dcbi, *cbi = NULL;
        struct afs_super_info *as = dir->i_sb->s_fs_info;
-       struct afs_iget_data data;
+       struct afs_status_cb *scb;
+       struct afs_iget_data iget_data;
        struct afs_fs_cursor fc;
-       struct afs_vnode *dvnode = AFS_FS_I(dir);
-       struct inode *inode = NULL;
+       struct afs_server *server;
+       struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
+       struct inode *inode = NULL, *ti;
        int ret, i;
 
        _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
@@ -657,10 +660,14 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
        cookie->nr_fids = 1; /* slot 0 is saved for the fid we actually want */
 
        read_seqlock_excl(&dvnode->cb_lock);
-       if (dvnode->cb_interest &&
-           dvnode->cb_interest->server &&
-           test_bit(AFS_SERVER_FL_NO_IBULK, &dvnode->cb_interest->server->flags))
-               cookie->one_only = true;
+       dcbi = rcu_dereference_protected(dvnode->cb_interest,
+                                        lockdep_is_held(&dvnode->cb_lock.lock));
+       if (dcbi) {
+               server = dcbi->server;
+               if (server &&
+                   test_bit(AFS_SERVER_FL_NO_IBULK, &server->flags))
+                       cookie->one_only = true;
+       }
        read_sequnlock_excl(&dvnode->cb_lock);
 
        for (i = 0; i < 50; i++)
@@ -678,24 +685,43 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
                goto out;
 
        /* Check to see if we already have an inode for the primary fid. */
-       data.volume = dvnode->volume;
-       data.fid = cookie->fids[0];
-       inode = ilookup5(dir->i_sb, cookie->fids[0].vnode, afs_iget5_test, &data);
+       iget_data.fid = cookie->fids[0];
+       iget_data.volume = dvnode->volume;
+       iget_data.cb_v_break = dvnode->volume->cb_v_break;
+       iget_data.cb_s_break = 0;
+       inode = ilookup5(dir->i_sb, cookie->fids[0].vnode,
+                        afs_iget5_test, &iget_data);
        if (inode)
                goto out;
 
        /* Need space for examining all the selected files */
        inode = ERR_PTR(-ENOMEM);
-       cookie->statuses = kcalloc(cookie->nr_fids, sizeof(struct afs_file_status),
-                                  GFP_KERNEL);
+       cookie->statuses = kvcalloc(cookie->nr_fids, sizeof(struct afs_status_cb),
+                                   GFP_KERNEL);
        if (!cookie->statuses)
                goto out;
 
-       cookie->callbacks = kcalloc(cookie->nr_fids, sizeof(struct afs_callback),
-                                   GFP_KERNEL);
-       if (!cookie->callbacks)
+       cookie->inodes = kcalloc(cookie->nr_fids, sizeof(struct inode *),
+                                GFP_KERNEL);
+       if (!cookie->inodes)
                goto out_s;
 
+       for (i = 1; i < cookie->nr_fids; i++) {
+               scb = &cookie->statuses[i];
+
+               /* Find any inodes that already exist and get their
+                * callback counters.
+                */
+               iget_data.fid = cookie->fids[i];
+               ti = ilookup5_nowait(dir->i_sb, iget_data.fid.vnode,
+                                    afs_iget5_test, &iget_data);
+               if (!IS_ERR_OR_NULL(ti)) {
+                       vnode = AFS_FS_I(ti);
+                       scb->cb_break = afs_calc_vnode_cb_break(vnode);
+                       cookie->inodes[i] = ti;
+               }
+       }
+
        /* Try FS.InlineBulkStatus first.  Abort codes for the individual
         * lookups contained therein are stored in the reply without aborting
         * the whole operation.
@@ -704,7 +730,7 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
                goto no_inline_bulk_status;
 
        inode = ERR_PTR(-ERESTARTSYS);
-       if (afs_begin_vnode_operation(&fc, dvnode, key)) {
+       if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
                while (afs_select_fileserver(&fc)) {
                        if (test_bit(AFS_SERVER_FL_NO_IBULK,
                                      &fc.cbi->server->flags)) {
@@ -712,11 +738,12 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
                                fc.ac.error = -ECONNABORTED;
                                break;
                        }
+                       iget_data.cb_v_break = dvnode->volume->cb_v_break;
+                       iget_data.cb_s_break = fc.cbi->server->cb_s_break;
                        afs_fs_inline_bulk_status(&fc,
                                                  afs_v2net(dvnode),
                                                  cookie->fids,
                                                  cookie->statuses,
-                                                 cookie->callbacks,
                                                  cookie->nr_fids, NULL);
                }
 
@@ -737,15 +764,16 @@ no_inline_bulk_status:
         * any of the lookups fails - so, for the moment, revert to
         * FS.FetchStatus for just the primary fid.
         */
-       cookie->nr_fids = 1;
        inode = ERR_PTR(-ERESTARTSYS);
-       if (afs_begin_vnode_operation(&fc, dvnode, key)) {
+       if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
                while (afs_select_fileserver(&fc)) {
+                       iget_data.cb_v_break = dvnode->volume->cb_v_break;
+                       iget_data.cb_s_break = fc.cbi->server->cb_s_break;
+                       scb = &cookie->statuses[0];
                        afs_fs_fetch_status(&fc,
                                            afs_v2net(dvnode),
                                            cookie->fids,
-                                           cookie->statuses,
-                                           cookie->callbacks,
+                                           scb,
                                            NULL);
                }
 
@@ -757,26 +785,36 @@ no_inline_bulk_status:
        if (IS_ERR(inode))
                goto out_c;
 
-       for (i = 0; i < cookie->nr_fids; i++)
-               cookie->statuses[i].abort_code = 0;
-
 success:
        /* Turn all the files into inodes and save the first one - which is the
         * one we actually want.
         */
-       if (cookie->statuses[0].abort_code != 0)
-               inode = ERR_PTR(afs_abort_to_error(cookie->statuses[0].abort_code));
+       scb = &cookie->statuses[0];
+       if (scb->status.abort_code != 0)
+               inode = ERR_PTR(afs_abort_to_error(scb->status.abort_code));
 
        for (i = 0; i < cookie->nr_fids; i++) {
-               struct inode *ti;
+               struct afs_status_cb *scb = &cookie->statuses[i];
+
+               if (!scb->have_status && !scb->have_error)
+                       continue;
+
+               if (cookie->inodes[i]) {
+                       afs_vnode_commit_status(&fc, AFS_FS_I(cookie->inodes[i]),
+                                               scb->cb_break, NULL, scb);
+                       continue;
+               }
 
-               if (cookie->statuses[i].abort_code != 0)
+               if (scb->status.abort_code != 0)
                        continue;
 
-               ti = afs_iget(dir->i_sb, key, &cookie->fids[i],
-                             &cookie->statuses[i],
-                             &cookie->callbacks[i],
-                             cbi, dvnode);
+               iget_data.fid = cookie->fids[i];
+               ti = afs_iget(dir->i_sb, key, &iget_data, scb, cbi, dvnode);
+               if (!IS_ERR(ti))
+                       afs_cache_permit(AFS_FS_I(ti), key,
+                                        0 /* Assume vnode->cb_break is 0 */ +
+                                        iget_data.cb_v_break,
+                                        scb);
                if (i == 0) {
                        inode = ti;
                } else {
@@ -787,9 +825,13 @@ success:
 
 out_c:
        afs_put_cb_interest(afs_v2net(dvnode), cbi);
-       kfree(cookie->callbacks);
+       if (cookie->inodes) {
+               for (i = 0; i < cookie->nr_fids; i++)
+                       iput(cookie->inodes[i]);
+               kfree(cookie->inodes);
+       }
 out_s:
-       kfree(cookie->statuses);
+       kvfree(cookie->statuses);
 out:
        kfree(cookie);
        return inode;
@@ -1114,9 +1156,8 @@ void afs_d_release(struct dentry *dentry)
  */
 static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
                                struct dentry *new_dentry,
-                               struct afs_fid *newfid,
-                               struct afs_file_status *newstatus,
-                               struct afs_callback *newcb)
+                               struct afs_iget_data *new_data,
+                               struct afs_status_cb *new_scb)
 {
        struct afs_vnode *vnode;
        struct inode *inode;
@@ -1125,7 +1166,7 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
                return;
 
        inode = afs_iget(fc->vnode->vfs_inode.i_sb, fc->key,
-                        newfid, newstatus, newcb, fc->cbi, fc->vnode);
+                        new_data, new_scb, fc->cbi, fc->vnode);
        if (IS_ERR(inode)) {
                /* ENOMEM or EINTR at a really inconvenient time - just abandon
                 * the new directory on the server.
@@ -1136,22 +1177,29 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
 
        vnode = AFS_FS_I(inode);
        set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
-       afs_vnode_commit_status(fc, vnode, 0);
+       if (fc->ac.error == 0)
+               afs_cache_permit(vnode, fc->key, vnode->cb_break, new_scb);
        d_instantiate(new_dentry, inode);
 }
 
+static void afs_prep_for_new_inode(struct afs_fs_cursor *fc,
+                                  struct afs_iget_data *iget_data)
+{
+       iget_data->volume = fc->vnode->volume;
+       iget_data->cb_v_break = fc->vnode->volume->cb_v_break;
+       iget_data->cb_s_break = fc->cbi->server->cb_s_break;
+}
+
 /*
  * create a directory on an AFS filesystem
  */
 static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
-       struct afs_file_status newstatus;
+       struct afs_iget_data iget_data;
+       struct afs_status_cb *scb;
        struct afs_fs_cursor fc;
-       struct afs_callback newcb;
        struct afs_vnode *dvnode = AFS_FS_I(dir);
-       struct afs_fid newfid;
        struct key *key;
-       u64 data_version = dvnode->status.data_version;
        int ret;
 
        mode |= S_IFDIR;
@@ -1159,23 +1207,32 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        _enter("{%llx:%llu},{%pd},%ho",
               dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
 
+       ret = -ENOMEM;
+       scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               goto error;
+
        key = afs_request_key(dvnode->volume->cell);
        if (IS_ERR(key)) {
                ret = PTR_ERR(key);
-               goto error;
+               goto error_scb;
        }
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, dvnode, key)) {
+       if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
+               afs_dataversion_t data_version = dvnode->status.data_version + 1;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(dvnode);
-                       afs_fs_create(&fc, dentry->d_name.name, mode, data_version,
-                                     &newfid, &newstatus, &newcb);
+                       afs_prep_for_new_inode(&fc, &iget_data);
+                       afs_fs_create(&fc, dentry->d_name.name, mode,
+                                     &scb[0], &iget_data.fid, &scb[1]);
                }
 
-               afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
-               afs_vnode_new_inode(&fc, dentry, &newfid, &newstatus, &newcb);
+               afs_check_for_remote_deletion(&fc, dvnode);
+               afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
+                                       &data_version, &scb[0]);
+               afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
                ret = afs_end_vnode_operation(&fc);
                if (ret < 0)
                        goto error_key;
@@ -1185,15 +1242,18 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 
        if (ret == 0 &&
            test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
-               afs_edit_dir_add(dvnode, &dentry->d_name, &newfid,
+               afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
                                 afs_edit_dir_for_create);
 
        key_put(key);
+       kfree(scb);
        _leave(" = 0");
        return 0;
 
 error_key:
        key_put(key);
+error_scb:
+       kfree(scb);
 error:
        d_drop(dentry);
        _leave(" = %d", ret);
@@ -1220,15 +1280,19 @@ static void afs_dir_remove_subdir(struct dentry *dentry)
  */
 static int afs_rmdir(struct inode *dir, struct dentry *dentry)
 {
+       struct afs_status_cb *scb;
        struct afs_fs_cursor fc;
        struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL;
        struct key *key;
-       u64 data_version = dvnode->status.data_version;
        int ret;
 
        _enter("{%llx:%llu},{%pd}",
               dvnode->fid.vid, dvnode->fid.vnode, dentry);
 
+       scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               return -ENOMEM;
+
        key = afs_request_key(dvnode->volume->cell);
        if (IS_ERR(key)) {
                ret = PTR_ERR(key);
@@ -1250,14 +1314,16 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
        }
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, dvnode, key)) {
+       if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
+               afs_dataversion_t data_version = dvnode->status.data_version + 1;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(dvnode);
-                       afs_fs_remove(&fc, vnode, dentry->d_name.name, true,
-                                     data_version);
+                       afs_fs_remove(&fc, vnode, dentry->d_name.name, true, scb);
                }
 
-               afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
+               afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
+                                       &data_version, scb);
                ret = afs_end_vnode_operation(&fc);
                if (ret == 0) {
                        afs_dir_remove_subdir(dentry);
@@ -1272,6 +1338,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
 error_key:
        key_put(key);
 error:
+       kfree(scb);
        return ret;
 }
 
@@ -1285,32 +1352,27 @@ error:
  * However, if we didn't have a callback promise outstanding, or it was
  * outstanding on a different server, then it won't break it either...
  */
-int afs_dir_remove_link(struct dentry *dentry, struct key *key,
-                       unsigned long d_version_before,
-                       unsigned long d_version_after)
+static int afs_dir_remove_link(struct afs_vnode *dvnode, struct dentry *dentry,
+                              struct key *key)
 {
-       bool dir_valid;
        int ret = 0;
 
-       /* There were no intervening changes on the server if the version
-        * number we got back was incremented by exactly 1.
-        */
-       dir_valid = (d_version_after == d_version_before + 1);
-
        if (d_really_is_positive(dentry)) {
                struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
 
                if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
                        /* Already done */
-               } else if (dir_valid) {
+               } else if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
+                       write_seqlock(&vnode->cb_lock);
                        drop_nlink(&vnode->vfs_inode);
                        if (vnode->vfs_inode.i_nlink == 0) {
                                set_bit(AFS_VNODE_DELETED, &vnode->flags);
-                               clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
+                               __afs_break_callback(vnode);
                        }
+                       write_sequnlock(&vnode->cb_lock);
                        ret = 0;
                } else {
-                       clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
+                       afs_break_callback(vnode);
 
                        if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
                                kdebug("AFS_VNODE_DELETED");
@@ -1331,11 +1393,10 @@ int afs_dir_remove_link(struct dentry *dentry, struct key *key,
 static int afs_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct afs_fs_cursor fc;
+       struct afs_status_cb *scb;
        struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL;
        struct key *key;
-       unsigned long d_version = (unsigned long)dentry->d_fsdata;
        bool need_rehash = false;
-       u64 data_version = dvnode->status.data_version;
        int ret;
 
        _enter("{%llx:%llu},{%pd}",
@@ -1344,10 +1405,15 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
        if (dentry->d_name.len >= AFSNAMEMAX)
                return -ENAMETOOLONG;
 
+       ret = -ENOMEM;
+       scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               goto error;
+
        key = afs_request_key(dvnode->volume->cell);
        if (IS_ERR(key)) {
                ret = PTR_ERR(key);
-               goto error;
+               goto error_scb;
        }
 
        /* Try to make sure we have a callback promise on the victim. */
@@ -1374,30 +1440,34 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
        spin_unlock(&dentry->d_lock);
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, dvnode, key)) {
+       if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
+               afs_dataversion_t data_version = dvnode->status.data_version + 1;
+               afs_dataversion_t data_version_2 = vnode->status.data_version;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(dvnode);
+                       fc.cb_break_2 = afs_calc_vnode_cb_break(vnode);
 
                        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc.cbi->server->flags) &&
                            !test_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags)) {
                                yfs_fs_remove_file2(&fc, vnode, dentry->d_name.name,
-                                                   data_version);
+                                                   &scb[0], &scb[1]);
                                if (fc.ac.error != -ECONNABORTED ||
                                    fc.ac.abort_code != RXGEN_OPCODE)
                                        continue;
                                set_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags);
                        }
 
-                       afs_fs_remove(&fc, vnode, dentry->d_name.name, false,
-                                     data_version);
+                       afs_fs_remove(&fc, vnode, dentry->d_name.name, false, &scb[0]);
                }
 
-               afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
+               afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
+                                       &data_version, &scb[0]);
+               afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
+                                       &data_version_2, &scb[1]);
                ret = afs_end_vnode_operation(&fc);
-               if (ret == 0)
-                       ret = afs_dir_remove_link(
-                               dentry, key, d_version,
-                               (unsigned long)dvnode->status.data_version);
+               if (ret == 0 && !(scb[1].have_status || scb[1].have_error))
+                       ret = afs_dir_remove_link(dvnode, dentry, key);
                if (ret == 0 &&
                    test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
                        afs_edit_dir_remove(dvnode, &dentry->d_name,
@@ -1409,6 +1479,8 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
 
 error_key:
        key_put(key);
+error_scb:
+       kfree(scb);
 error:
        _leave(" = %d", ret);
        return ret;
@@ -1420,13 +1492,11 @@ error:
 static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
                      bool excl)
 {
+       struct afs_iget_data iget_data;
        struct afs_fs_cursor fc;
-       struct afs_file_status newstatus;
-       struct afs_callback newcb;
+       struct afs_status_cb *scb;
        struct afs_vnode *dvnode = AFS_FS_I(dir);
-       struct afs_fid newfid;
        struct key *key;
-       u64 data_version = dvnode->status.data_version;
        int ret;
 
        mode |= S_IFREG;
@@ -1444,17 +1514,26 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
                goto error;
        }
 
+       ret = -ENOMEM;
+       scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               goto error_scb;
+
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, dvnode, key)) {
+       if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
+               afs_dataversion_t data_version = dvnode->status.data_version + 1;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(dvnode);
-                       afs_fs_create(&fc, dentry->d_name.name, mode, data_version,
-                                     &newfid, &newstatus, &newcb);
+                       afs_prep_for_new_inode(&fc, &iget_data);
+                       afs_fs_create(&fc, dentry->d_name.name, mode,
+                                     &scb[0], &iget_data.fid, &scb[1]);
                }
 
-               afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
-               afs_vnode_new_inode(&fc, dentry, &newfid, &newstatus, &newcb);
+               afs_check_for_remote_deletion(&fc, dvnode);
+               afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
+                                       &data_version, &scb[0]);
+               afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
                ret = afs_end_vnode_operation(&fc);
                if (ret < 0)
                        goto error_key;
@@ -1463,13 +1542,16 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        }
 
        if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
-               afs_edit_dir_add(dvnode, &dentry->d_name, &newfid,
+               afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
                                 afs_edit_dir_for_create);
 
+       kfree(scb);
        key_put(key);
        _leave(" = 0");
        return 0;
 
+error_scb:
+       kfree(scb);
 error_key:
        key_put(key);
 error:
@@ -1485,15 +1567,12 @@ static int afs_link(struct dentry *from, struct inode *dir,
                    struct dentry *dentry)
 {
        struct afs_fs_cursor fc;
-       struct afs_vnode *dvnode, *vnode;
+       struct afs_status_cb *scb;
+       struct afs_vnode *dvnode = AFS_FS_I(dir);
+       struct afs_vnode *vnode = AFS_FS_I(d_inode(from));
        struct key *key;
-       u64 data_version;
        int ret;
 
-       vnode = AFS_FS_I(d_inode(from));
-       dvnode = AFS_FS_I(dir);
-       data_version = dvnode->status.data_version;
-
        _enter("{%llx:%llu},{%llx:%llu},{%pd}",
               vnode->fid.vid, vnode->fid.vnode,
               dvnode->fid.vid, dvnode->fid.vnode,
@@ -1503,14 +1582,21 @@ static int afs_link(struct dentry *from, struct inode *dir,
        if (dentry->d_name.len >= AFSNAMEMAX)
                goto error;
 
+       ret = -ENOMEM;
+       scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               goto error;
+
        key = afs_request_key(dvnode->volume->cell);
        if (IS_ERR(key)) {
                ret = PTR_ERR(key);
-               goto error;
+               goto error_scb;
        }
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, dvnode, key)) {
+       if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
+               afs_dataversion_t data_version = dvnode->status.data_version + 1;
+
                if (mutex_lock_interruptible_nested(&vnode->io_lock, 1) < 0) {
                        afs_end_vnode_operation(&fc);
                        goto error_key;
@@ -1519,11 +1605,14 @@ static int afs_link(struct dentry *from, struct inode *dir,
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(dvnode);
                        fc.cb_break_2 = afs_calc_vnode_cb_break(vnode);
-                       afs_fs_link(&fc, vnode, dentry->d_name.name, data_version);
+                       afs_fs_link(&fc, vnode, dentry->d_name.name,
+                                   &scb[0], &scb[1]);
                }
 
-               afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
-               afs_vnode_commit_status(&fc, vnode, fc.cb_break_2);
+               afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
+                                       &data_version, &scb[0]);
+               afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
+                                       NULL, &scb[1]);
                ihold(&vnode->vfs_inode);
                d_instantiate(dentry, &vnode->vfs_inode);
 
@@ -1540,11 +1629,14 @@ static int afs_link(struct dentry *from, struct inode *dir,
                                 afs_edit_dir_for_link);
 
        key_put(key);
+       kfree(scb);
        _leave(" = 0");
        return 0;
 
 error_key:
        key_put(key);
+error_scb:
+       kfree(scb);
 error:
        d_drop(dentry);
        _leave(" = %d", ret);
@@ -1557,12 +1649,11 @@ error:
 static int afs_symlink(struct inode *dir, struct dentry *dentry,
                       const char *content)
 {
+       struct afs_iget_data iget_data;
        struct afs_fs_cursor fc;
-       struct afs_file_status newstatus;
+       struct afs_status_cb *scb;
        struct afs_vnode *dvnode = AFS_FS_I(dir);
-       struct afs_fid newfid;
        struct key *key;
-       u64 data_version = dvnode->status.data_version;
        int ret;
 
        _enter("{%llx:%llu},{%pd},%s",
@@ -1577,24 +1668,32 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
        if (strlen(content) >= AFSPATHMAX)
                goto error;
 
+       ret = -ENOMEM;
+       scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               goto error;
+
        key = afs_request_key(dvnode->volume->cell);
        if (IS_ERR(key)) {
                ret = PTR_ERR(key);
-               goto error;
+               goto error_scb;
        }
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, dvnode, key)) {
+       if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
+               afs_dataversion_t data_version = dvnode->status.data_version + 1;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(dvnode);
-                       afs_fs_symlink(&fc, dentry->d_name.name,
-                                      content, data_version,
-                                      &newfid, &newstatus);
+                       afs_prep_for_new_inode(&fc, &iget_data);
+                       afs_fs_symlink(&fc, dentry->d_name.name, content,
+                                      &scb[0], &iget_data.fid, &scb[1]);
                }
 
-               afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
-               afs_vnode_new_inode(&fc, dentry, &newfid, &newstatus, NULL);
+               afs_check_for_remote_deletion(&fc, dvnode);
+               afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
+                                       &data_version, &scb[0]);
+               afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
                ret = afs_end_vnode_operation(&fc);
                if (ret < 0)
                        goto error_key;
@@ -1603,15 +1702,18 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
        }
 
        if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
-               afs_edit_dir_add(dvnode, &dentry->d_name, &newfid,
+               afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
                                 afs_edit_dir_for_symlink);
 
        key_put(key);
+       kfree(scb);
        _leave(" = 0");
        return 0;
 
 error_key:
        key_put(key);
+error_scb:
+       kfree(scb);
 error:
        d_drop(dentry);
        _leave(" = %d", ret);
@@ -1626,11 +1728,11 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                      unsigned int flags)
 {
        struct afs_fs_cursor fc;
+       struct afs_status_cb *scb;
        struct afs_vnode *orig_dvnode, *new_dvnode, *vnode;
        struct dentry *tmp = NULL, *rehash = NULL;
        struct inode *new_inode;
        struct key *key;
-       u64 orig_data_version, new_data_version;
        bool new_negative = d_is_negative(new_dentry);
        int ret;
 
@@ -1644,8 +1746,6 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
        vnode = AFS_FS_I(d_inode(old_dentry));
        orig_dvnode = AFS_FS_I(old_dir);
        new_dvnode = AFS_FS_I(new_dir);
-       orig_data_version = orig_dvnode->status.data_version;
-       new_data_version = new_dvnode->status.data_version;
 
        _enter("{%llx:%llu},{%llx:%llu},{%llx:%llu},{%pd}",
               orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
@@ -1653,10 +1753,15 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
               new_dvnode->fid.vid, new_dvnode->fid.vnode,
               new_dentry);
 
+       ret = -ENOMEM;
+       scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               goto error;
+
        key = afs_request_key(orig_dvnode->volume->cell);
        if (IS_ERR(key)) {
                ret = PTR_ERR(key);
-               goto error;
+               goto error_scb;
        }
 
        /* For non-directories, check whether the target is busy and if so,
@@ -1690,31 +1795,43 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        new_dentry = tmp;
                        rehash = NULL;
                        new_negative = true;
-                       orig_data_version = orig_dvnode->status.data_version;
-                       new_data_version = new_dvnode->status.data_version;
                }
        }
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, orig_dvnode, key)) {
+       if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) {
+               afs_dataversion_t orig_data_version;
+               afs_dataversion_t new_data_version;
+               struct afs_status_cb *new_scb = &scb[1];
+
+               orig_data_version = orig_dvnode->status.data_version + 1;
+
                if (orig_dvnode != new_dvnode) {
                        if (mutex_lock_interruptible_nested(&new_dvnode->io_lock, 1) < 0) {
                                afs_end_vnode_operation(&fc);
                                goto error_rehash;
                        }
+                       new_data_version = new_dvnode->status.data_version;
+               } else {
+                       new_data_version = orig_data_version;
+                       new_scb = &scb[0];
                }
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(orig_dvnode);
                        fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode);
                        afs_fs_rename(&fc, old_dentry->d_name.name,
                                      new_dvnode, new_dentry->d_name.name,
-                                     orig_data_version, new_data_version);
+                                     &scb[0], new_scb);
                }
 
-               afs_vnode_commit_status(&fc, orig_dvnode, fc.cb_break);
-               afs_vnode_commit_status(&fc, new_dvnode, fc.cb_break_2);
-               if (orig_dvnode != new_dvnode)
+               afs_vnode_commit_status(&fc, orig_dvnode, fc.cb_break,
+                                       &orig_data_version, &scb[0]);
+               if (new_dvnode != orig_dvnode) {
+                       afs_vnode_commit_status(&fc, new_dvnode, fc.cb_break_2,
+                                               &new_data_version, &scb[1]);
                        mutex_unlock(&new_dvnode->io_lock);
+               }
                ret = afs_end_vnode_operation(&fc);
                if (ret < 0)
                        goto error_rehash;
@@ -1754,6 +1871,8 @@ error_tmp:
        if (tmp)
                dput(tmp);
        key_put(key);
+error_scb:
+       kfree(scb);
 error:
        _leave(" = %d", ret);
        return ret;
index f6f89fd..28f4aa0 100644 (file)
@@ -24,21 +24,28 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
                               struct key *key)
 {
        struct afs_fs_cursor fc;
-       u64 dir_data_version = dvnode->status.data_version;
+       struct afs_status_cb *scb;
        int ret = -ERESTARTSYS;
 
        _enter("%pd,%pd", old, new);
 
+       scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               return -ENOMEM;
+
        trace_afs_silly_rename(vnode, false);
-       if (afs_begin_vnode_operation(&fc, dvnode, key)) {
+       if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
+               afs_dataversion_t dir_data_version = dvnode->status.data_version + 1;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(dvnode);
                        afs_fs_rename(&fc, old->d_name.name,
                                      dvnode, new->d_name.name,
-                                     dir_data_version, dir_data_version);
+                                     scb, scb);
                }
 
-               afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
+               afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
+                                       &dir_data_version, scb);
                ret = afs_end_vnode_operation(&fc);
        }
 
@@ -64,6 +71,7 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode
                fsnotify_nameremove(old, 0);
        }
 
+       kfree(scb);
        _leave(" = %d", ret);
        return ret;
 }
@@ -143,31 +151,37 @@ static int afs_do_silly_unlink(struct afs_vnode *dvnode, struct afs_vnode *vnode
                               struct dentry *dentry, struct key *key)
 {
        struct afs_fs_cursor fc;
-       u64 dir_data_version = dvnode->status.data_version;
+       struct afs_status_cb *scb;
        int ret = -ERESTARTSYS;
 
        _enter("");
 
+       scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               return -ENOMEM;
+
        trace_afs_silly_rename(vnode, true);
-       if (afs_begin_vnode_operation(&fc, dvnode, key)) {
+       if (afs_begin_vnode_operation(&fc, dvnode, key, false)) {
+               afs_dataversion_t dir_data_version = dvnode->status.data_version + 1;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(dvnode);
 
                        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc.cbi->server->flags) &&
                            !test_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags)) {
                                yfs_fs_remove_file2(&fc, vnode, dentry->d_name.name,
-                                                   dir_data_version);
+                                                   &scb[0], &scb[1]);
                                if (fc.ac.error != -ECONNABORTED ||
                                    fc.ac.abort_code != RXGEN_OPCODE)
                                        continue;
                                set_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags);
                        }
 
-                       afs_fs_remove(&fc, vnode, dentry->d_name.name, false,
-                                     dir_data_version);
+                       afs_fs_remove(&fc, vnode, dentry->d_name.name, false, &scb[0]);
                }
 
-               afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
+               afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
+                                       &dir_data_version, &scb[0]);
                ret = afs_end_vnode_operation(&fc);
                if (ret == 0) {
                        drop_nlink(&vnode->vfs_inode);
@@ -182,6 +196,7 @@ static int afs_do_silly_unlink(struct afs_vnode *dvnode, struct afs_vnode *vnode
                                            afs_edit_dir_for_unlink);
        }
 
+       kfree(scb);
        _leave(" = %d", ret);
        return ret;
 }
index a9ba81d..af1689d 100644 (file)
@@ -46,7 +46,7 @@ static int afs_probe_cell_name(struct dentry *dentry)
                return 0;
        }
 
-       ret = dns_query("afsdb", name, len, "srv=1", NULL, NULL);
+       ret = dns_query("afsdb", name, len, "srv=1", NULL, NULL, false);
        if (ret == -ENODATA)
                ret = -EDESTADDRREQ;
        return ret;
@@ -261,8 +261,7 @@ int afs_dynroot_populate(struct super_block *sb)
        struct afs_net *net = afs_sb2net(sb);
        int ret;
 
-       if (mutex_lock_interruptible(&net->proc_cells_lock) < 0)
-               return -ERESTARTSYS;
+       mutex_lock(&net->proc_cells_lock);
 
        net->dynroot_sb = sb;
        hlist_for_each_entry(cell, &net->proc_cells, proc_link) {
index e8d6619..11e69c5 100644 (file)
@@ -170,11 +170,12 @@ int afs_release(struct inode *inode, struct file *file)
 {
        struct afs_vnode *vnode = AFS_FS_I(inode);
        struct afs_file *af = file->private_data;
+       int ret = 0;
 
        _enter("{%llx:%llu},", vnode->fid.vid, vnode->fid.vnode);
 
        if ((file->f_mode & FMODE_WRITE))
-               return vfs_fsync(file, 0);
+               ret = vfs_fsync(file, 0);
 
        file->private_data = NULL;
        if (af->wb)
@@ -182,8 +183,8 @@ int afs_release(struct inode *inode, struct file *file)
        key_put(af->key);
        kfree(af);
        afs_prune_wb_keys(vnode);
-       _leave(" = 0");
-       return 0;
+       _leave(" = %d", ret);
+       return ret;
 }
 
 /*
@@ -227,6 +228,7 @@ static void afs_file_readpage_read_complete(struct page *page,
 int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *desc)
 {
        struct afs_fs_cursor fc;
+       struct afs_status_cb *scb;
        int ret;
 
        _enter("%s{%llx:%llu.%u},%x,,,",
@@ -236,15 +238,22 @@ int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *de
               vnode->fid.unique,
               key_serial(key));
 
+       scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               return -ENOMEM;
+
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
+               afs_dataversion_t data_version = vnode->status.data_version;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
-                       afs_fs_fetch_data(&fc, desc);
+                       afs_fs_fetch_data(&fc, scb, desc);
                }
 
-               afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, vnode, fc.cb_break);
+               afs_check_for_remote_deletion(&fc, vnode);
+               afs_vnode_commit_status(&fc, vnode, fc.cb_break,
+                                       &data_version, scb);
                ret = afs_end_vnode_operation(&fc);
        }
 
@@ -254,6 +263,7 @@ int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *de
                                &afs_v2net(vnode)->n_fetch_bytes);
        }
 
+       kfree(scb);
        _leave(" = %d", ret);
        return ret;
 }
@@ -404,10 +414,10 @@ static int afs_readpage(struct file *file, struct page *page)
 /*
  * Make pages available as they're filled.
  */
-static void afs_readpages_page_done(struct afs_call *call, struct afs_read *req)
+static void afs_readpages_page_done(struct afs_read *req)
 {
 #ifdef CONFIG_AFS_FSCACHE
-       struct afs_vnode *vnode = call->reply[0];
+       struct afs_vnode *vnode = req->vnode;
 #endif
        struct page *page = req->pages[req->index];
 
@@ -461,6 +471,7 @@ static int afs_readpages_one(struct file *file, struct address_space *mapping,
                return -ENOMEM;
 
        refcount_set(&req->usage, 1);
+       req->vnode = vnode;
        req->page_done = afs_readpages_page_done;
        req->pos = first->index;
        req->pos <<= PAGE_SHIFT;
index adc88ef..ed3ac03 100644 (file)
@@ -41,9 +41,6 @@ void afs_lock_may_be_available(struct afs_vnode *vnode)
 {
        _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
 
-       if (vnode->lock_state != AFS_VNODE_LOCK_WAITING_FOR_CB)
-               return;
-
        spin_lock(&vnode->lock);
        if (vnode->lock_state == AFS_VNODE_LOCK_WAITING_FOR_CB)
                afs_next_locker(vnode, 0);
@@ -77,7 +74,7 @@ static void afs_schedule_lock_extension(struct afs_vnode *vnode)
  */
 void afs_lock_op_done(struct afs_call *call)
 {
-       struct afs_vnode *vnode = call->reply[0];
+       struct afs_vnode *vnode = call->lvnode;
 
        if (call->error == 0) {
                spin_lock(&vnode->lock);
@@ -185,6 +182,7 @@ static void afs_kill_lockers_enoent(struct afs_vnode *vnode)
 static int afs_set_lock(struct afs_vnode *vnode, struct key *key,
                        afs_lock_type_t type)
 {
+       struct afs_status_cb *scb;
        struct afs_fs_cursor fc;
        int ret;
 
@@ -195,18 +193,23 @@ static int afs_set_lock(struct afs_vnode *vnode, struct key *key,
               vnode->fid.unique,
               key_serial(key), type);
 
+       scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               return -ENOMEM;
+
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
-                       afs_fs_set_lock(&fc, type);
+                       afs_fs_set_lock(&fc, type, scb);
                }
 
-               afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, vnode, fc.cb_break);
+               afs_check_for_remote_deletion(&fc, vnode);
+               afs_vnode_commit_status(&fc, vnode, fc.cb_break, NULL, scb);
                ret = afs_end_vnode_operation(&fc);
        }
 
+       kfree(scb);
        _leave(" = %d", ret);
        return ret;
 }
@@ -216,6 +219,7 @@ static int afs_set_lock(struct afs_vnode *vnode, struct key *key,
  */
 static int afs_extend_lock(struct afs_vnode *vnode, struct key *key)
 {
+       struct afs_status_cb *scb;
        struct afs_fs_cursor fc;
        int ret;
 
@@ -226,18 +230,23 @@ static int afs_extend_lock(struct afs_vnode *vnode, struct key *key)
               vnode->fid.unique,
               key_serial(key));
 
+       scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               return -ENOMEM;
+
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, key, false)) {
                while (afs_select_current_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
-                       afs_fs_extend_lock(&fc);
+                       afs_fs_extend_lock(&fc, scb);
                }
 
-               afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, vnode, fc.cb_break);
+               afs_check_for_remote_deletion(&fc, vnode);
+               afs_vnode_commit_status(&fc, vnode, fc.cb_break, NULL, scb);
                ret = afs_end_vnode_operation(&fc);
        }
 
+       kfree(scb);
        _leave(" = %d", ret);
        return ret;
 }
@@ -247,6 +256,7 @@ static int afs_extend_lock(struct afs_vnode *vnode, struct key *key)
  */
 static int afs_release_lock(struct afs_vnode *vnode, struct key *key)
 {
+       struct afs_status_cb *scb;
        struct afs_fs_cursor fc;
        int ret;
 
@@ -257,18 +267,23 @@ static int afs_release_lock(struct afs_vnode *vnode, struct key *key)
               vnode->fid.unique,
               key_serial(key));
 
+       scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               return -ENOMEM;
+
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, key, false)) {
                while (afs_select_current_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
-                       afs_fs_release_lock(&fc);
+                       afs_fs_release_lock(&fc, scb);
                }
 
-               afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, vnode, fc.cb_break);
+               afs_check_for_remote_deletion(&fc, vnode);
+               afs_vnode_commit_status(&fc, vnode, fc.cb_break, NULL, scb);
                ret = afs_end_vnode_operation(&fc);
        }
 
+       kfree(scb);
        _leave(" = %d", ret);
        return ret;
 }
@@ -736,7 +751,7 @@ static int afs_do_getlk(struct file *file, struct file_lock *fl)
        posix_test_lock(file, fl);
        if (fl->fl_type == F_UNLCK) {
                /* no local locks; consult the server */
-               ret = afs_fetch_status(vnode, key, false);
+               ret = afs_fetch_status(vnode, key, false, NULL);
                if (ret < 0)
                        goto error;
 
index 5d3abde..9b72662 100644 (file)
@@ -33,8 +33,8 @@ static bool afs_fs_probe_done(struct afs_server *server)
 void afs_fileserver_probe_result(struct afs_call *call)
 {
        struct afs_addr_list *alist = call->alist;
-       struct afs_server *server = call->reply[0];
-       unsigned int server_index = (long)call->reply[1];
+       struct afs_server *server = call->server;
+       unsigned int server_index = call->server_index;
        unsigned int index = call->addr_ix;
        unsigned int rtt = UINT_MAX;
        bool have_result = false;
index 1296f5d..4829840 100644 (file)
@@ -59,79 +59,18 @@ static void xdr_dump_bad(const __be32 *bp)
        pr_notice("0x50: %08x\n", ntohl(x[0]));
 }
 
-/*
- * Update the core inode struct from a returned status record.
- */
-void afs_update_inode_from_status(struct afs_vnode *vnode,
-                                 struct afs_file_status *status,
-                                 const afs_dataversion_t *expected_version,
-                                 u8 flags)
-{
-       struct timespec64 t;
-       umode_t mode;
-
-       t = status->mtime_client;
-       vnode->vfs_inode.i_ctime = t;
-       vnode->vfs_inode.i_mtime = t;
-       vnode->vfs_inode.i_atime = t;
-
-       if (flags & (AFS_VNODE_META_CHANGED | AFS_VNODE_NOT_YET_SET)) {
-               vnode->vfs_inode.i_uid = make_kuid(&init_user_ns, status->owner);
-               vnode->vfs_inode.i_gid = make_kgid(&init_user_ns, status->group);
-               set_nlink(&vnode->vfs_inode, status->nlink);
-
-               mode = vnode->vfs_inode.i_mode;
-               mode &= ~S_IALLUGO;
-               mode |= status->mode;
-               barrier();
-               vnode->vfs_inode.i_mode = mode;
-       }
-
-       if (!(flags & AFS_VNODE_NOT_YET_SET)) {
-               if (expected_version &&
-                   *expected_version != status->data_version) {
-                       _debug("vnode modified %llx on {%llx:%llu} [exp %llx]",
-                              (unsigned long long) status->data_version,
-                              vnode->fid.vid, vnode->fid.vnode,
-                              (unsigned long long) *expected_version);
-                       vnode->invalid_before = status->data_version;
-                       if (vnode->status.type == AFS_FTYPE_DIR) {
-                               if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
-                                       afs_stat_v(vnode, n_inval);
-                       } else {
-                               set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
-                       }
-               } else if (vnode->status.type == AFS_FTYPE_DIR) {
-                       /* Expected directory change is handled elsewhere so
-                        * that we can locally edit the directory and save on a
-                        * download.
-                        */
-                       if (test_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
-                               flags &= ~AFS_VNODE_DATA_CHANGED;
-               }
-       }
-
-       if (flags & (AFS_VNODE_DATA_CHANGED | AFS_VNODE_NOT_YET_SET)) {
-               inode_set_iversion_raw(&vnode->vfs_inode, status->data_version);
-               i_size_write(&vnode->vfs_inode, status->size);
-       }
-}
-
 /*
  * decode an AFSFetchStatus block
  */
-static int xdr_decode_AFSFetchStatus(struct afs_call *call,
-                                    const __be32 **_bp,
-                                    struct afs_file_status *status,
-                                    struct afs_vnode *vnode,
-                                    const afs_dataversion_t *expected_version,
-                                    struct afs_read *read_req)
+static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
+                                    struct afs_call *call,
+                                    struct afs_status_cb *scb)
 {
        const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp;
+       struct afs_file_status *status = &scb->status;
        bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
        u64 data_version, size;
        u32 type, abort_code;
-       u8 flags = 0;
 
        abort_code = ntohl(xdr->abort_code);
 
@@ -144,6 +83,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
                         * case.
                         */
                        status->abort_code = abort_code;
+                       scb->have_error = true;
                        return 0;
                }
 
@@ -161,44 +101,25 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
        case AFS_FTYPE_FILE:
        case AFS_FTYPE_DIR:
        case AFS_FTYPE_SYMLINK:
-               if (type != status->type &&
-                   vnode &&
-                   !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
-                       pr_warning("Vnode %llx:%llx:%x changed type %u to %u\n",
-                                  vnode->fid.vid,
-                                  vnode->fid.vnode,
-                                  vnode->fid.unique,
-                                  status->type, type);
-                       goto bad;
-               }
                status->type = type;
                break;
        default:
                goto bad;
        }
 
-#define EXTRACT_M(FIELD)                                       \
-       do {                                                    \
-               u32 x = ntohl(xdr->FIELD);                      \
-               if (status->FIELD != x) {                       \
-                       flags |= AFS_VNODE_META_CHANGED;        \
-                       status->FIELD = x;                      \
-               }                                               \
-       } while (0)
-
-       EXTRACT_M(nlink);
-       EXTRACT_M(author);
-       EXTRACT_M(owner);
-       EXTRACT_M(caller_access); /* call ticket dependent */
-       EXTRACT_M(anon_access);
-       EXTRACT_M(mode);
-       EXTRACT_M(group);
+       status->nlink           = ntohl(xdr->nlink);
+       status->author          = ntohl(xdr->author);
+       status->owner           = ntohl(xdr->owner);
+       status->caller_access   = ntohl(xdr->caller_access); /* Ticket dependent */
+       status->anon_access     = ntohl(xdr->anon_access);
+       status->mode            = ntohl(xdr->mode) & S_IALLUGO;
+       status->group           = ntohl(xdr->group);
+       status->lock_count      = ntohl(xdr->lock_count);
 
        status->mtime_client.tv_sec = ntohl(xdr->mtime_client);
        status->mtime_client.tv_nsec = 0;
        status->mtime_server.tv_sec = ntohl(xdr->mtime_server);
        status->mtime_server.tv_nsec = 0;
-       status->lock_count   = ntohl(xdr->lock_count);
 
        size  = (u64)ntohl(xdr->size_lo);
        size |= (u64)ntohl(xdr->size_hi) << 32;
@@ -206,25 +127,10 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
 
        data_version  = (u64)ntohl(xdr->data_version_lo);
        data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
-       if (data_version != status->data_version) {
-               status->data_version = data_version;
-               flags |= AFS_VNODE_DATA_CHANGED;
-       }
-
-       if (read_req) {
-               read_req->data_version = data_version;
-               read_req->file_size = size;
-       }
+       status->data_version = data_version;
+       scb->have_status = true;
 
        *_bp = (const void *)*_bp + sizeof(*xdr);
-
-       if (vnode) {
-               if (test_bit(AFS_VNODE_UNSET, &vnode->flags))
-                       flags |= AFS_VNODE_NOT_YET_SET;
-               afs_update_inode_from_status(vnode, status, expected_version,
-                                            flags);
-       }
-
        return 0;
 
 bad:
@@ -232,77 +138,22 @@ bad:
        return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
 }
 
-/*
- * Decode the file status.  We need to lock the target vnode if we're going to
- * update its status so that stat() sees the attributes update atomically.
- */
-static int afs_decode_status(struct afs_call *call,
-                            const __be32 **_bp,
-                            struct afs_file_status *status,
-                            struct afs_vnode *vnode,
-                            const afs_dataversion_t *expected_version,
-                            struct afs_read *read_req)
+static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
 {
-       int ret;
-
-       if (!vnode)
-               return xdr_decode_AFSFetchStatus(call, _bp, status, vnode,
-                                                expected_version, read_req);
-
-       write_seqlock(&vnode->cb_lock);
-       ret = xdr_decode_AFSFetchStatus(call, _bp, status, vnode,
-                                       expected_version, read_req);
-       write_sequnlock(&vnode->cb_lock);
-       return ret;
+       return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry;
 }
 
-/*
- * decode an AFSCallBack block
- */
-static void xdr_decode_AFSCallBack(struct afs_call *call,
-                                  struct afs_vnode *vnode,
-                                  const __be32 **_bp)
+static void xdr_decode_AFSCallBack(const __be32 **_bp,
+                                  struct afs_call *call,
+                                  struct afs_status_cb *scb)
 {
-       struct afs_cb_interest *old, *cbi = call->cbi;
+       struct afs_callback *cb = &scb->callback;
        const __be32 *bp = *_bp;
-       u32 cb_expiry;
-
-       write_seqlock(&vnode->cb_lock);
-
-       if (!afs_cb_is_broken(call->cb_break, vnode, cbi)) {
-               vnode->cb_version       = ntohl(*bp++);
-               cb_expiry               = ntohl(*bp++);
-               vnode->cb_type          = ntohl(*bp++);
-               vnode->cb_expires_at    = cb_expiry + ktime_get_real_seconds();
-               old = vnode->cb_interest;
-               if (old != call->cbi) {
-                       vnode->cb_interest = cbi;
-                       cbi = old;
-               }
-               set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
-       } else {
-               bp += 3;
-       }
 
-       write_sequnlock(&vnode->cb_lock);
-       call->cbi = cbi;
-       *_bp = bp;
-}
-
-static ktime_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
-{
-       return ktime_add_ns(call->reply_time, expiry * NSEC_PER_SEC);
-}
-
-static void xdr_decode_AFSCallBack_raw(struct afs_call *call,
-                                      const __be32 **_bp,
-                                      struct afs_callback *cb)
-{
-       const __be32 *bp = *_bp;
-
-       cb->version     = ntohl(*bp++);
+       bp++; /* version */
        cb->expires_at  = xdr_decode_expiry(call, ntohl(*bp++));
-       cb->type        = ntohl(*bp++);
+       bp++; /* type */
+       scb->have_cb    = true;
        *_bp = bp;
 }
 
@@ -395,7 +246,6 @@ static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
  */
 static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
 {
-       struct afs_vnode *vnode = call->reply[0];
        const __be32 *bp;
        int ret;
 
@@ -403,16 +253,13 @@ static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
        if (ret < 0)
                return ret;
 
-       _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
-
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       ret = afs_decode_status(call, &bp, &vnode->status, vnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
        if (ret < 0)
                return ret;
-       xdr_decode_AFSCallBack(call, vnode, &bp);
-       xdr_decode_AFSVolSync(&bp, call->reply[1]);
+       xdr_decode_AFSCallBack(&bp, call, call->out_scb);
+       xdr_decode_AFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
        return 0;
@@ -431,8 +278,8 @@ static const struct afs_call_type afs_RXFSFetchStatus_vnode = {
 /*
  * fetch the status information for a file
  */
-int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync,
-                            bool new_inode)
+int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_status_cb *scb,
+                            struct afs_volsync *volsync)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -440,7 +287,7 @@ int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy
        __be32 *bp;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
-               return yfs_fs_fetch_file_status(fc, volsync, new_inode);
+               return yfs_fs_fetch_file_status(fc, scb, volsync);
 
        _enter(",%x,{%llx:%llu},,",
               key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
@@ -453,10 +300,8 @@ int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy
        }
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->reply[1] = volsync;
-       call->expected_version = new_inode ? 1 : vnode->status.data_version;
-       call->want_reply_time = true;
+       call->out_scb = scb;
+       call->out_volsync = volsync;
 
        /* marshall the parameters */
        bp = call->request;
@@ -465,10 +310,10 @@ int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy
        bp[2] = htonl(vnode->fid.vnode);
        bp[3] = htonl(vnode->fid.unique);
 
-       call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
 
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -478,8 +323,7 @@ int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy
  */
 static int afs_deliver_fs_fetch_data(struct afs_call *call)
 {
-       struct afs_vnode *vnode = call->reply[0];
-       struct afs_read *req = call->reply[2];
+       struct afs_read *req = call->read_request;
        const __be32 *bp;
        unsigned int size;
        int ret;
@@ -541,7 +385,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
                if (req->offset == PAGE_SIZE) {
                        req->offset = 0;
                        if (req->page_done)
-                               req->page_done(call, req);
+                               req->page_done(req);
                        req->index++;
                        if (req->remain > 0)
                                goto begin_page;
@@ -575,12 +419,14 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
                        return ret;
 
                bp = call->buffer;
-               ret = afs_decode_status(call, &bp, &vnode->status, vnode,
-                                       &vnode->status.data_version, req);
+               ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
                if (ret < 0)
                        return ret;
-               xdr_decode_AFSCallBack(call, vnode, &bp);
-               xdr_decode_AFSVolSync(&bp, call->reply[1]);
+               xdr_decode_AFSCallBack(&bp, call, call->out_scb);
+               xdr_decode_AFSVolSync(&bp, call->out_volsync);
+
+               req->data_version = call->out_scb->status.data_version;
+               req->file_size = call->out_scb->status.size;
 
                call->unmarshall++;
 
@@ -593,7 +439,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
                        zero_user_segment(req->pages[req->index],
                                          req->offset, PAGE_SIZE);
                if (req->page_done)
-                       req->page_done(call, req);
+                       req->page_done(req);
                req->offset = 0;
        }
 
@@ -603,7 +449,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
 
 static void afs_fetch_data_destructor(struct afs_call *call)
 {
-       struct afs_read *req = call->reply[2];
+       struct afs_read *req = call->read_request;
 
        afs_put_read(req);
        afs_flat_call_destructor(call);
@@ -629,7 +475,9 @@ static const struct afs_call_type afs_RXFSFetchData64 = {
 /*
  * fetch data from a very large file
  */
-static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req)
+static int afs_fs_fetch_data64(struct afs_fs_cursor *fc,
+                              struct afs_status_cb *scb,
+                              struct afs_read *req)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -643,11 +491,9 @@ static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->reply[1] = NULL; /* volsync */
-       call->reply[2] = req;
-       call->expected_version = vnode->status.data_version;
-       call->want_reply_time = true;
+       call->out_scb = scb;
+       call->out_volsync = NULL;
+       call->read_request = req;
 
        /* marshall the parameters */
        bp = call->request;
@@ -661,9 +507,9 @@ static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req)
        bp[7] = htonl(lower_32_bits(req->len));
 
        refcount_inc(&req->usage);
-       call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -671,7 +517,9 @@ static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req)
 /*
  * fetch data from a file
  */
-int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
+int afs_fs_fetch_data(struct afs_fs_cursor *fc,
+                     struct afs_status_cb *scb,
+                     struct afs_read *req)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -679,12 +527,12 @@ int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
        __be32 *bp;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
-               return yfs_fs_fetch_data(fc, req);
+               return yfs_fs_fetch_data(fc, scb, req);
 
        if (upper_32_bits(req->pos) ||
            upper_32_bits(req->len) ||
            upper_32_bits(req->pos + req->len))
-               return afs_fs_fetch_data64(fc, req);
+               return afs_fs_fetch_data64(fc, scb, req);
 
        _enter("");
 
@@ -693,11 +541,9 @@ int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->reply[1] = NULL; /* volsync */
-       call->reply[2] = req;
-       call->expected_version = vnode->status.data_version;
-       call->want_reply_time = true;
+       call->out_scb = scb;
+       call->out_volsync = NULL;
+       call->read_request = req;
 
        /* marshall the parameters */
        bp = call->request;
@@ -709,9 +555,9 @@ int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
        bp[5] = htonl(lower_32_bits(req->len));
 
        refcount_inc(&req->usage);
-       call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -721,28 +567,24 @@ int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
  */
 static int afs_deliver_fs_create_vnode(struct afs_call *call)
 {
-       struct afs_vnode *vnode = call->reply[0];
        const __be32 *bp;
        int ret;
 
-       _enter("{%u}", call->unmarshall);
-
        ret = afs_transfer_reply(call);
        if (ret < 0)
                return ret;
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       xdr_decode_AFSFid(&bp, call->reply[1]);
-       ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
+       xdr_decode_AFSFid(&bp, call->out_fid);
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
        if (ret < 0)
                return ret;
-       ret = afs_decode_status(call, &bp, &vnode->status, vnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
        if (ret < 0)
                return ret;
-       xdr_decode_AFSCallBack_raw(call, &bp, call->reply[3]);
-       /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
+       xdr_decode_AFSCallBack(&bp, call, call->out_scb);
+       xdr_decode_AFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
        return 0;
@@ -771,24 +613,23 @@ static const struct afs_call_type afs_RXFSMakeDir = {
 int afs_fs_create(struct afs_fs_cursor *fc,
                  const char *name,
                  umode_t mode,
-                 u64 current_data_version,
+                 struct afs_status_cb *dvnode_scb,
                  struct afs_fid *newfid,
-                 struct afs_file_status *newstatus,
-                 struct afs_callback *newcb)
+                 struct afs_status_cb *new_scb)
 {
-       struct afs_vnode *vnode = fc->vnode;
+       struct afs_vnode *dvnode = fc->vnode;
        struct afs_call *call;
-       struct afs_net *net = afs_v2net(vnode);
+       struct afs_net *net = afs_v2net(dvnode);
        size_t namesz, reqsz, padsz;
        __be32 *bp;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)){
                if (S_ISDIR(mode))
-                       return yfs_fs_make_dir(fc, name, mode, current_data_version,
-                                              newfid, newstatus, newcb);
+                       return yfs_fs_make_dir(fc, name, mode, dvnode_scb,
+                                              newfid, new_scb);
                else
-                       return yfs_fs_create_file(fc, name, mode, current_data_version,
-                                                 newfid, newstatus, newcb);
+                       return yfs_fs_create_file(fc, name, mode, dvnode_scb,
+                                                 newfid, new_scb);
        }
 
        _enter("");
@@ -804,19 +645,16 @@ int afs_fs_create(struct afs_fs_cursor *fc,
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->reply[1] = newfid;
-       call->reply[2] = newstatus;
-       call->reply[3] = newcb;
-       call->expected_version = current_data_version + 1;
-       call->want_reply_time = true;
+       call->out_dir_scb = dvnode_scb;
+       call->out_fid = newfid;
+       call->out_scb = new_scb;
 
        /* marshall the parameters */
        bp = call->request;
        *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
-       *bp++ = htonl(vnode->fid.vid);
-       *bp++ = htonl(vnode->fid.vnode);
-       *bp++ = htonl(vnode->fid.unique);
+       *bp++ = htonl(dvnode->fid.vid);
+       *bp++ = htonl(dvnode->fid.vnode);
+       *bp++ = htonl(dvnode->fid.unique);
        *bp++ = htonl(namesz);
        memcpy(bp, name, namesz);
        bp = (void *) bp + namesz;
@@ -825,41 +663,38 @@ int afs_fs_create(struct afs_fs_cursor *fc,
                bp = (void *) bp + padsz;
        }
        *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
-       *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
+       *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */
        *bp++ = 0; /* owner */
        *bp++ = 0; /* group */
        *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
        *bp++ = 0; /* segment size */
 
        afs_use_fs_server(call, fc->cbi);
-       trace_afs_make_fs_call1(call, &vnode->fid, name);
+       trace_afs_make_fs_call1(call, &dvnode->fid, name);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
 /*
- * Deliver reply data to any operation that returns file status and volume
+ * Deliver reply data to any operation that returns directory status and volume
  * sync.
  */
-static int afs_deliver_fs_status_and_vol(struct afs_call *call)
+static int afs_deliver_fs_dir_status_and_vol(struct afs_call *call)
 {
-       struct afs_vnode *vnode = call->reply[0];
        const __be32 *bp;
        int ret;
 
-       _enter("{%u}", call->unmarshall);
-
        ret = afs_transfer_reply(call);
        if (ret < 0)
                return ret;
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       ret = afs_decode_status(call, &bp, &vnode->status, vnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
        if (ret < 0)
                return ret;
-       /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
+       xdr_decode_AFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
        return 0;
@@ -871,14 +706,14 @@ static int afs_deliver_fs_status_and_vol(struct afs_call *call)
 static const struct afs_call_type afs_RXFSRemoveFile = {
        .name           = "FS.RemoveFile",
        .op             = afs_FS_RemoveFile,
-       .deliver        = afs_deliver_fs_status_and_vol,
+       .deliver        = afs_deliver_fs_dir_status_and_vol,
        .destructor     = afs_flat_call_destructor,
 };
 
 static const struct afs_call_type afs_RXFSRemoveDir = {
        .name           = "FS.RemoveDir",
        .op             = afs_FS_RemoveDir,
-       .deliver        = afs_deliver_fs_status_and_vol,
+       .deliver        = afs_deliver_fs_dir_status_and_vol,
        .destructor     = afs_flat_call_destructor,
 };
 
@@ -886,7 +721,7 @@ static const struct afs_call_type afs_RXFSRemoveDir = {
  * remove a file or directory
  */
 int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
-                 const char *name, bool isdir, u64 current_data_version)
+                 const char *name, bool isdir, struct afs_status_cb *dvnode_scb)
 {
        struct afs_vnode *dvnode = fc->vnode;
        struct afs_call *call;
@@ -895,7 +730,7 @@ int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
        __be32 *bp;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
-               return yfs_fs_remove(fc, vnode, name, isdir, current_data_version);
+               return yfs_fs_remove(fc, vnode, name, isdir, dvnode_scb);
 
        _enter("");
 
@@ -910,9 +745,7 @@ int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = dvnode;
-       call->reply[1] = vnode;
-       call->expected_version = current_data_version + 1;
+       call->out_dir_scb = dvnode_scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -930,6 +763,7 @@ int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call1(call, &dvnode->fid, name);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -939,7 +773,6 @@ int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
  */
 static int afs_deliver_fs_link(struct afs_call *call)
 {
-       struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1];
        const __be32 *bp;
        int ret;
 
@@ -951,14 +784,13 @@ static int afs_deliver_fs_link(struct afs_call *call)
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       ret = afs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL);
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
        if (ret < 0)
                return ret;
-       ret = afs_decode_status(call, &bp, &dvnode->status, dvnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
        if (ret < 0)
                return ret;
-       /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
+       xdr_decode_AFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
        return 0;
@@ -978,7 +810,9 @@ static const struct afs_call_type afs_RXFSLink = {
  * make a hard link
  */
 int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
-               const char *name, u64 current_data_version)
+               const char *name,
+               struct afs_status_cb *dvnode_scb,
+               struct afs_status_cb *vnode_scb)
 {
        struct afs_vnode *dvnode = fc->vnode;
        struct afs_call *call;
@@ -987,7 +821,7 @@ int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
        __be32 *bp;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
-               return yfs_fs_link(fc, vnode, name, current_data_version);
+               return yfs_fs_link(fc, vnode, name, dvnode_scb, vnode_scb);
 
        _enter("");
 
@@ -1000,9 +834,8 @@ int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = dvnode;
-       call->reply[1] = vnode;
-       call->expected_version = current_data_version + 1;
+       call->out_dir_scb = dvnode_scb;
+       call->out_scb = vnode_scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1023,6 +856,7 @@ int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call1(call, &vnode->fid, name);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1032,7 +866,6 @@ int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
  */
 static int afs_deliver_fs_symlink(struct afs_call *call)
 {
-       struct afs_vnode *vnode = call->reply[0];
        const __be32 *bp;
        int ret;
 
@@ -1044,15 +877,14 @@ static int afs_deliver_fs_symlink(struct afs_call *call)
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       xdr_decode_AFSFid(&bp, call->reply[1]);
-       ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
+       xdr_decode_AFSFid(&bp, call->out_fid);
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
        if (ret < 0)
                return ret;
-       ret = afs_decode_status(call, &bp, &vnode->status, vnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
        if (ret < 0)
                return ret;
-       /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
+       xdr_decode_AFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
        return 0;
@@ -1074,19 +906,19 @@ static const struct afs_call_type afs_RXFSSymlink = {
 int afs_fs_symlink(struct afs_fs_cursor *fc,
                   const char *name,
                   const char *contents,
-                  u64 current_data_version,
+                  struct afs_status_cb *dvnode_scb,
                   struct afs_fid *newfid,
-                  struct afs_file_status *newstatus)
+                  struct afs_status_cb *new_scb)
 {
-       struct afs_vnode *vnode = fc->vnode;
+       struct afs_vnode *dvnode = fc->vnode;
        struct afs_call *call;
-       struct afs_net *net = afs_v2net(vnode);
+       struct afs_net *net = afs_v2net(dvnode);
        size_t namesz, reqsz, padsz, c_namesz, c_padsz;
        __be32 *bp;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
-               return yfs_fs_symlink(fc, name, contents, current_data_version,
-                                     newfid, newstatus);
+               return yfs_fs_symlink(fc, name, contents, dvnode_scb,
+                                     newfid, new_scb);
 
        _enter("");
 
@@ -1104,17 +936,16 @@ int afs_fs_symlink(struct afs_fs_cursor *fc,
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->reply[1] = newfid;
-       call->reply[2] = newstatus;
-       call->expected_version = current_data_version + 1;
+       call->out_dir_scb = dvnode_scb;
+       call->out_fid = newfid;
+       call->out_scb = new_scb;
 
        /* marshall the parameters */
        bp = call->request;
        *bp++ = htonl(FSSYMLINK);
-       *bp++ = htonl(vnode->fid.vid);
-       *bp++ = htonl(vnode->fid.vnode);
-       *bp++ = htonl(vnode->fid.unique);
+       *bp++ = htonl(dvnode->fid.vid);
+       *bp++ = htonl(dvnode->fid.vnode);
+       *bp++ = htonl(dvnode->fid.unique);
        *bp++ = htonl(namesz);
        memcpy(bp, name, namesz);
        bp = (void *) bp + namesz;
@@ -1130,14 +961,15 @@ int afs_fs_symlink(struct afs_fs_cursor *fc,
                bp = (void *) bp + c_padsz;
        }
        *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME);
-       *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */
+       *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */
        *bp++ = 0; /* owner */
        *bp++ = 0; /* group */
        *bp++ = htonl(S_IRWXUGO); /* unix mode */
        *bp++ = 0; /* segment size */
 
        afs_use_fs_server(call, fc->cbi);
-       trace_afs_make_fs_call1(call, &vnode->fid, name);
+       trace_afs_make_fs_call1(call, &dvnode->fid, name);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1147,29 +979,24 @@ int afs_fs_symlink(struct afs_fs_cursor *fc,
  */
 static int afs_deliver_fs_rename(struct afs_call *call)
 {
-       struct afs_vnode *orig_dvnode = call->reply[0], *new_dvnode = call->reply[1];
        const __be32 *bp;
        int ret;
 
-       _enter("{%u}", call->unmarshall);
-
        ret = afs_transfer_reply(call);
        if (ret < 0)
                return ret;
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       ret = afs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
        if (ret < 0)
                return ret;
-       if (new_dvnode != orig_dvnode) {
-               ret = afs_decode_status(call, &bp, &new_dvnode->status, new_dvnode,
-                                       &call->expected_version_2, NULL);
+       if (call->out_dir_scb != call->out_scb) {
+               ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
                if (ret < 0)
                        return ret;
        }
-       /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
+       xdr_decode_AFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
        return 0;
@@ -1186,14 +1013,14 @@ static const struct afs_call_type afs_RXFSRename = {
 };
 
 /*
- * create a symbolic link
+ * Rename/move a file or directory.
  */
 int afs_fs_rename(struct afs_fs_cursor *fc,
                  const char *orig_name,
                  struct afs_vnode *new_dvnode,
                  const char *new_name,
-                 u64 current_orig_data_version,
-                 u64 current_new_data_version)
+                 struct afs_status_cb *orig_dvnode_scb,
+                 struct afs_status_cb *new_dvnode_scb)
 {
        struct afs_vnode *orig_dvnode = fc->vnode;
        struct afs_call *call;
@@ -1204,8 +1031,8 @@ int afs_fs_rename(struct afs_fs_cursor *fc,
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
                return yfs_fs_rename(fc, orig_name,
                                     new_dvnode, new_name,
-                                    current_orig_data_version,
-                                    current_new_data_version);
+                                    orig_dvnode_scb,
+                                    new_dvnode_scb);
 
        _enter("");
 
@@ -1225,10 +1052,8 @@ int afs_fs_rename(struct afs_fs_cursor *fc,
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = orig_dvnode;
-       call->reply[1] = new_dvnode;
-       call->expected_version = current_orig_data_version + 1;
-       call->expected_version_2 = current_new_data_version + 1;
+       call->out_dir_scb = orig_dvnode_scb;
+       call->out_scb = new_dvnode_scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1257,6 +1082,7 @@ int afs_fs_rename(struct afs_fs_cursor *fc,
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call2(call, &orig_dvnode->fid, orig_name, new_name);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1266,7 +1092,6 @@ int afs_fs_rename(struct afs_fs_cursor *fc,
  */
 static int afs_deliver_fs_store_data(struct afs_call *call)
 {
-       struct afs_vnode *vnode = call->reply[0];
        const __be32 *bp;
        int ret;
 
@@ -1278,13 +1103,10 @@ static int afs_deliver_fs_store_data(struct afs_call *call)
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       ret = afs_decode_status(call, &bp, &vnode->status, vnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
        if (ret < 0)
                return ret;
-       /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
-
-       afs_pages_written_back(vnode, call);
+       xdr_decode_AFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
        return 0;
@@ -1314,7 +1136,8 @@ static int afs_fs_store_data64(struct afs_fs_cursor *fc,
                               struct address_space *mapping,
                               pgoff_t first, pgoff_t last,
                               unsigned offset, unsigned to,
-                              loff_t size, loff_t pos, loff_t i_size)
+                              loff_t size, loff_t pos, loff_t i_size,
+                              struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1332,13 +1155,12 @@ static int afs_fs_store_data64(struct afs_fs_cursor *fc,
 
        call->key = fc->key;
        call->mapping = mapping;
-       call->reply[0] = vnode;
        call->first = first;
        call->last = last;
        call->first_offset = offset;
        call->last_to = to;
        call->send_pages = true;
-       call->expected_version = vnode->status.data_version + 1;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1362,6 +1184,7 @@ static int afs_fs_store_data64(struct afs_fs_cursor *fc,
        *bp++ = htonl((u32) i_size);
 
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1371,7 +1194,8 @@ static int afs_fs_store_data64(struct afs_fs_cursor *fc,
  */
 int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
                      pgoff_t first, pgoff_t last,
-                     unsigned offset, unsigned to)
+                     unsigned offset, unsigned to,
+                     struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1380,7 +1204,7 @@ int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
        __be32 *bp;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
-               return yfs_fs_store_data(fc, mapping, first, last, offset, to);
+               return yfs_fs_store_data(fc, mapping, first, last, offset, to, scb);
 
        _enter(",%x,{%llx:%llu},,",
               key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
@@ -1401,7 +1225,7 @@ int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
 
        if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
                return afs_fs_store_data64(fc, mapping, first, last, offset, to,
-                                          size, pos, i_size);
+                                          size, pos, i_size, scb);
 
        call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
                                   (4 + 6 + 3) * 4,
@@ -1411,13 +1235,12 @@ int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
 
        call->key = fc->key;
        call->mapping = mapping;
-       call->reply[0] = vnode;
        call->first = first;
        call->last = last;
        call->first_offset = offset;
        call->last_to = to;
        call->send_pages = true;
-       call->expected_version = vnode->status.data_version + 1;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1439,6 +1262,7 @@ int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1448,7 +1272,6 @@ int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
  */
 static int afs_deliver_fs_store_status(struct afs_call *call)
 {
-       struct afs_vnode *vnode = call->reply[0];
        const __be32 *bp;
        int ret;
 
@@ -1460,11 +1283,10 @@ static int afs_deliver_fs_store_status(struct afs_call *call)
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       ret = afs_decode_status(call, &bp, &vnode->status, vnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
        if (ret < 0)
                return ret;
-       /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
+       xdr_decode_AFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
        return 0;
@@ -1498,7 +1320,8 @@ static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
  * set the attributes on a very large file, using FS.StoreData rather than
  * FS.StoreStatus so as to alter the file size also
  */
-static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
+static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr,
+                                struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1517,8 +1340,7 @@ static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->expected_version = vnode->status.data_version + 1;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1538,6 +1360,7 @@ static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1546,7 +1369,8 @@ static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
  * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
  * so as to alter the file size also
  */
-static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
+static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr,
+                              struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1558,7 +1382,7 @@ static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
 
        ASSERT(attr->ia_valid & ATTR_SIZE);
        if (attr->ia_size >> 32)
-               return afs_fs_setattr_size64(fc, attr);
+               return afs_fs_setattr_size64(fc, attr, scb);
 
        call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status,
                                   (4 + 6 + 3) * 4,
@@ -1567,8 +1391,7 @@ static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->expected_version = vnode->status.data_version + 1;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1585,6 +1408,7 @@ static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1593,7 +1417,8 @@ static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
  * set the attributes on a file, using FS.StoreData if there's a change in file
  * size, and FS.StoreStatus otherwise
  */
-int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
+int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr,
+                  struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1601,10 +1426,10 @@ int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
        __be32 *bp;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
-               return yfs_fs_setattr(fc, attr);
+               return yfs_fs_setattr(fc, attr, scb);
 
        if (attr->ia_valid & ATTR_SIZE)
-               return afs_fs_setattr_size(fc, attr);
+               return afs_fs_setattr_size(fc, attr, scb);
 
        _enter(",%x,{%llx:%llu},,",
               key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
@@ -1616,8 +1441,7 @@ int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->expected_version = vnode->status.data_version;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1630,6 +1454,7 @@ int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1659,7 +1484,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
                        return ret;
 
                bp = call->buffer;
-               xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]);
+               xdr_decode_AFSFetchVolumeStatus(&bp, call->out_volstatus);
                call->unmarshall++;
                afs_extract_to_tmp(call);
 
@@ -1675,7 +1500,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
                        return afs_protocol_error(call, -EBADMSG,
                                                  afs_eproto_volname_len);
                size = (call->count + 3) & ~3; /* It's padded */
-               afs_extract_begin(call, call->reply[2], size);
+               afs_extract_to_buf(call, size);
                call->unmarshall++;
 
                /* Fall through - and extract the volume name */
@@ -1685,7 +1510,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
                if (ret < 0)
                        return ret;
 
-               p = call->reply[2];
+               p = call->buffer;
                p[call->count] = 0;
                _debug("volname '%s'", p);
                afs_extract_to_tmp(call);
@@ -1703,7 +1528,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
                        return afs_protocol_error(call, -EBADMSG,
                                                  afs_eproto_offline_msg_len);
                size = (call->count + 3) & ~3; /* It's padded */
-               afs_extract_begin(call, call->reply[2], size);
+               afs_extract_to_buf(call, size);
                call->unmarshall++;
 
                /* Fall through - and extract the offline message */
@@ -1713,7 +1538,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
                if (ret < 0)
                        return ret;
 
-               p = call->reply[2];
+               p = call->buffer;
                p[call->count] = 0;
                _debug("offline '%s'", p);
 
@@ -1732,7 +1557,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
                        return afs_protocol_error(call, -EBADMSG,
                                                  afs_eproto_motd_len);
                size = (call->count + 3) & ~3; /* It's padded */
-               afs_extract_begin(call, call->reply[2], size);
+               afs_extract_to_buf(call, size);
                call->unmarshall++;
 
                /* Fall through - and extract the message of the day */
@@ -1742,7 +1567,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
                if (ret < 0)
                        return ret;
 
-               p = call->reply[2];
+               p = call->buffer;
                p[call->count] = 0;
                _debug("motd '%s'", p);
 
@@ -1756,16 +1581,6 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
        return 0;
 }
 
-/*
- * destroy an FS.GetVolumeStatus call
- */
-static void afs_get_volume_status_call_destructor(struct afs_call *call)
-{
-       kfree(call->reply[2]);
-       call->reply[2] = NULL;
-       afs_flat_call_destructor(call);
-}
-
 /*
  * FS.GetVolumeStatus operation type
  */
@@ -1773,7 +1588,7 @@ static const struct afs_call_type afs_RXFSGetVolumeStatus = {
        .name           = "FS.GetVolumeStatus",
        .op             = afs_FS_GetVolumeStatus,
        .deliver        = afs_deliver_fs_get_volume_status,
-       .destructor     = afs_get_volume_status_call_destructor,
+       .destructor     = afs_flat_call_destructor,
 };
 
 /*
@@ -1786,27 +1601,19 @@ int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
        struct afs_call *call;
        struct afs_net *net = afs_v2net(vnode);
        __be32 *bp;
-       void *tmpbuf;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
                return yfs_fs_get_volume_status(fc, vs);
 
        _enter("");
 
-       tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
-       if (!tmpbuf)
-               return -ENOMEM;
-
-       call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
-       if (!call) {
-               kfree(tmpbuf);
+       call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4,
+                                  max(12 * 4, AFSOPAQUEMAX + 1));
+       if (!call)
                return -ENOMEM;
-       }
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->reply[1] = vs;
-       call->reply[2] = tmpbuf;
+       call->out_volstatus = vs;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1815,6 +1622,7 @@ int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1835,7 +1643,7 @@ static int afs_deliver_fs_xxxx_lock(struct afs_call *call)
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
+       xdr_decode_AFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
        return 0;
@@ -1876,7 +1684,8 @@ static const struct afs_call_type afs_RXFSReleaseLock = {
 /*
  * Set a lock on a file
  */
-int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
+int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type,
+                   struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1884,7 +1693,7 @@ int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
        __be32 *bp;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
-               return yfs_fs_set_lock(fc, type);
+               return yfs_fs_set_lock(fc, type, scb);
 
        _enter("");
 
@@ -1893,8 +1702,8 @@ int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->want_reply_time = true;
+       call->lvnode = vnode;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1906,6 +1715,7 @@ int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_calli(call, &vnode->fid, type);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1913,7 +1723,7 @@ int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
 /*
  * extend a lock on a file
  */
-int afs_fs_extend_lock(struct afs_fs_cursor *fc)
+int afs_fs_extend_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1921,7 +1731,7 @@ int afs_fs_extend_lock(struct afs_fs_cursor *fc)
        __be32 *bp;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
-               return yfs_fs_extend_lock(fc);
+               return yfs_fs_extend_lock(fc, scb);
 
        _enter("");
 
@@ -1930,8 +1740,8 @@ int afs_fs_extend_lock(struct afs_fs_cursor *fc)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->want_reply_time = true;
+       call->lvnode = vnode;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1942,6 +1752,7 @@ int afs_fs_extend_lock(struct afs_fs_cursor *fc)
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1949,7 +1760,7 @@ int afs_fs_extend_lock(struct afs_fs_cursor *fc)
 /*
  * release a lock on a file
  */
-int afs_fs_release_lock(struct afs_fs_cursor *fc)
+int afs_fs_release_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1957,7 +1768,7 @@ int afs_fs_release_lock(struct afs_fs_cursor *fc)
        __be32 *bp;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
-               return yfs_fs_release_lock(fc);
+               return yfs_fs_release_lock(fc, scb);
 
        _enter("");
 
@@ -1966,7 +1777,8 @@ int afs_fs_release_lock(struct afs_fs_cursor *fc)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
+       call->lvnode = vnode;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1977,6 +1789,7 @@ int afs_fs_release_lock(struct afs_fs_cursor *fc)
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -2071,14 +1884,6 @@ static int afs_deliver_fs_get_capabilities(struct afs_call *call)
        return 0;
 }
 
-static void afs_destroy_fs_get_capabilities(struct afs_call *call)
-{
-       struct afs_server *server = call->reply[0];
-
-       afs_put_server(call->net, server);
-       afs_flat_call_destructor(call);
-}
-
 /*
  * FS.GetCapabilities operation type
  */
@@ -2087,7 +1892,7 @@ static const struct afs_call_type afs_RXFSGetCapabilities = {
        .op             = afs_FS_GetCapabilities,
        .deliver        = afs_deliver_fs_get_capabilities,
        .done           = afs_fileserver_probe_result,
-       .destructor     = afs_destroy_fs_get_capabilities,
+       .destructor     = afs_flat_call_destructor,
 };
 
 /*
@@ -2110,11 +1915,11 @@ struct afs_call *afs_fs_get_capabilities(struct afs_net *net,
                return ERR_PTR(-ENOMEM);
 
        call->key = key;
-       call->reply[0] = afs_get_server(server);
-       call->reply[1] = (void *)(long)server_index;
+       call->server = afs_get_server(server);
+       call->server_index = server_index;
        call->upgrade = true;
-       call->want_reply_time = true;
        call->async = true;
+       call->max_lifespan = AFS_PROBE_MAX_LIFESPAN;
 
        /* marshall the parameters */
        bp = call->request;
@@ -2131,10 +1936,6 @@ struct afs_call *afs_fs_get_capabilities(struct afs_net *net,
  */
 static int afs_deliver_fs_fetch_status(struct afs_call *call)
 {
-       struct afs_file_status *status = call->reply[1];
-       struct afs_callback *callback = call->reply[2];
-       struct afs_volsync *volsync = call->reply[3];
-       struct afs_fid *fid = call->reply[0];
        const __be32 *bp;
        int ret;
 
@@ -2142,16 +1943,13 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call)
        if (ret < 0)
                return ret;
 
-       _enter("{%llx:%llu}", fid->vid, fid->vnode);
-
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       ret = afs_decode_status(call, &bp, status, NULL,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
        if (ret < 0)
                return ret;
-       xdr_decode_AFSCallBack_raw(call, &bp, callback);
-       xdr_decode_AFSVolSync(&bp, volsync);
+       xdr_decode_AFSCallBack(&bp, call, call->out_scb);
+       xdr_decode_AFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
        return 0;
@@ -2173,15 +1971,14 @@ static const struct afs_call_type afs_RXFSFetchStatus = {
 int afs_fs_fetch_status(struct afs_fs_cursor *fc,
                        struct afs_net *net,
                        struct afs_fid *fid,
-                       struct afs_file_status *status,
-                       struct afs_callback *callback,
+                       struct afs_status_cb *scb,
                        struct afs_volsync *volsync)
 {
        struct afs_call *call;
        __be32 *bp;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
-               return yfs_fs_fetch_status(fc, net, fid, status, callback, volsync);
+               return yfs_fs_fetch_status(fc, net, fid, scb, volsync);
 
        _enter(",%x,{%llx:%llu},,",
               key_serial(fc->key), fid->vid, fid->vnode);
@@ -2193,12 +1990,9 @@ int afs_fs_fetch_status(struct afs_fs_cursor *fc,
        }
 
        call->key = fc->key;
-       call->reply[0] = fid;
-       call->reply[1] = status;
-       call->reply[2] = callback;
-       call->reply[3] = volsync;
-       call->expected_version = 1; /* vnode->status.data_version */
-       call->want_reply_time = true;
+       call->out_fid = fid;
+       call->out_scb = scb;
+       call->out_volsync = volsync;
 
        /* marshall the parameters */
        bp = call->request;
@@ -2207,9 +2001,9 @@ int afs_fs_fetch_status(struct afs_fs_cursor *fc,
        bp[2] = htonl(fid->vnode);
        bp[3] = htonl(fid->unique);
 
-       call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -2219,9 +2013,7 @@ int afs_fs_fetch_status(struct afs_fs_cursor *fc,
  */
 static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
 {
-       struct afs_file_status *statuses;
-       struct afs_callback *callbacks;
-       struct afs_vnode *vnode = call->reply[0];
+       struct afs_status_cb *scb;
        const __be32 *bp;
        u32 tmp;
        int ret;
@@ -2260,10 +2052,8 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
                        return ret;
 
                bp = call->buffer;
-               statuses = call->reply[1];
-               ret = afs_decode_status(call, &bp, &statuses[call->count],
-                                       call->count == 0 ? vnode : NULL,
-                                       NULL, NULL);
+               scb = &call->out_scb[call->count];
+               ret = xdr_decode_AFSFetchStatus(&bp, call, scb);
                if (ret < 0)
                        return ret;
 
@@ -2302,13 +2092,8 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
 
                _debug("unmarshall CB array");
                bp = call->buffer;
-               callbacks = call->reply[2];
-               callbacks[call->count].version  = ntohl(bp[0]);
-               callbacks[call->count].expires_at = xdr_decode_expiry(call, ntohl(bp[1]));
-               callbacks[call->count].type     = ntohl(bp[2]);
-               statuses = call->reply[1];
-               if (call->count == 0 && vnode && statuses[0].abort_code == 0)
-                       xdr_decode_AFSCallBack(call, vnode, &bp);
+               scb = &call->out_scb[call->count];
+               xdr_decode_AFSCallBack(&bp, call, scb);
                call->count++;
                if (call->count < call->count2)
                        goto more_cbs;
@@ -2323,7 +2108,7 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
                        return ret;
 
                bp = call->buffer;
-               xdr_decode_AFSVolSync(&bp, call->reply[3]);
+               xdr_decode_AFSVolSync(&bp, call->out_volsync);
 
                call->unmarshall++;
 
@@ -2351,8 +2136,7 @@ static const struct afs_call_type afs_RXFSInlineBulkStatus = {
 int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
                              struct afs_net *net,
                              struct afs_fid *fids,
-                             struct afs_file_status *statuses,
-                             struct afs_callback *callbacks,
+                             struct afs_status_cb *statuses,
                              unsigned int nr_fids,
                              struct afs_volsync *volsync)
 {
@@ -2361,7 +2145,7 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
        int i;
 
        if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
-               return yfs_fs_inline_bulk_status(fc, net, fids, statuses, callbacks,
+               return yfs_fs_inline_bulk_status(fc, net, fids, statuses,
                                                 nr_fids, volsync);
 
        _enter(",%x,{%llx:%llu},%u",
@@ -2376,12 +2160,9 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
        }
 
        call->key = fc->key;
-       call->reply[0] = NULL; /* vnode for fid[0] */
-       call->reply[1] = statuses;
-       call->reply[2] = callbacks;
-       call->reply[3] = volsync;
+       call->out_scb = statuses;
+       call->out_volsync = volsync;
        call->count2 = nr_fids;
-       call->want_reply_time = true;
 
        /* marshall the parameters */
        bp = call->request;
@@ -2393,9 +2174,9 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
                *bp++ = htonl(fids[i].unique);
        }
 
-       call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &fids[0]);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -2405,7 +2186,6 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
  */
 static int afs_deliver_fs_fetch_acl(struct afs_call *call)
 {
-       struct afs_vnode *vnode = call->reply[1];
        struct afs_acl *acl;
        const __be32 *bp;
        unsigned int size;
@@ -2430,7 +2210,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call)
                acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
                if (!acl)
                        return -ENOMEM;
-               call->reply[0] = acl;
+               call->ret_acl = acl;
                acl->size = call->count2;
                afs_extract_begin(call, acl->data, size);
                call->unmarshall++;
@@ -2451,11 +2231,10 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call)
                        return ret;
 
                bp = call->buffer;
-               ret = afs_decode_status(call, &bp, &vnode->status, vnode,
-                                       &vnode->status.data_version, NULL);
+               ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
                if (ret < 0)
                        return ret;
-               xdr_decode_AFSVolSync(&bp, call->reply[2]);
+               xdr_decode_AFSVolSync(&bp, call->out_volsync);
 
                call->unmarshall++;
 
@@ -2469,7 +2248,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call)
 
 static void afs_destroy_fs_fetch_acl(struct afs_call *call)
 {
-       kfree(call->reply[0]);
+       kfree(call->ret_acl);
        afs_flat_call_destructor(call);
 }
 
@@ -2486,7 +2265,8 @@ static const struct afs_call_type afs_RXFSFetchACL = {
 /*
  * Fetch the ACL for a file.
  */
-struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc)
+struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc,
+                                struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -2503,10 +2283,9 @@ struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc)
        }
 
        call->key = fc->key;
-       call->reply[0] = NULL;
-       call->reply[1] = vnode;
-       call->reply[2] = NULL; /* volsync */
-       call->ret_reply0 = true;
+       call->ret_acl = NULL;
+       call->out_scb = scb;
+       call->out_volsync = NULL;
 
        /* marshall the parameters */
        bp = call->request;
@@ -2515,27 +2294,50 @@ struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc)
        bp[2] = htonl(vnode->fid.vnode);
        bp[3] = htonl(vnode->fid.unique);
 
-       call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
        afs_make_call(&fc->ac, call, GFP_KERNEL);
        return (struct afs_acl *)afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
+/*
+ * Deliver reply data to any operation that returns file status and volume
+ * sync.
+ */
+static int afs_deliver_fs_file_status_and_vol(struct afs_call *call)
+{
+       const __be32 *bp;
+       int ret;
+
+       ret = afs_transfer_reply(call);
+       if (ret < 0)
+               return ret;
+
+       bp = call->buffer;
+       ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
+       if (ret < 0)
+               return ret;
+       xdr_decode_AFSVolSync(&bp, call->out_volsync);
+
+       _leave(" = 0 [done]");
+       return 0;
+}
+
 /*
  * FS.StoreACL operation type
  */
 static const struct afs_call_type afs_RXFSStoreACL = {
        .name           = "FS.StoreACL",
        .op             = afs_FS_StoreACL,
-       .deliver        = afs_deliver_fs_status_and_vol,
+       .deliver        = afs_deliver_fs_file_status_and_vol,
        .destructor     = afs_flat_call_destructor,
 };
 
 /*
  * Fetch the ACL for a file.
  */
-int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl)
+int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl,
+                    struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -2555,8 +2357,8 @@ int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl)
        }
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->reply[2] = NULL; /* volsync */
+       call->out_scb = scb;
+       call->out_volsync = NULL;
 
        /* marshall the parameters */
        bp = call->request;
index c4652b4..b42d9d0 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/namei.h>
 #include <linux/iversion.h>
 #include "internal.h"
+#include "afs_fs.h"
 
 static const struct inode_operations afs_symlink_inode_operations = {
        .get_link       = page_get_link,
@@ -58,38 +59,50 @@ static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *paren
  * Initialise an inode from the vnode status.
  */
 static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key,
-                                     struct afs_vnode *parent_vnode)
+                                     struct afs_cb_interest *cbi,
+                                     struct afs_vnode *parent_vnode,
+                                     struct afs_status_cb *scb)
 {
+       struct afs_cb_interest *old_cbi = NULL;
+       struct afs_file_status *status = &scb->status;
        struct inode *inode = AFS_VNODE_TO_I(vnode);
+       struct timespec64 t;
 
        _debug("FS: ft=%d lk=%d sz=%llu ver=%Lu mod=%hu",
-              vnode->status.type,
-              vnode->status.nlink,
-              (unsigned long long) vnode->status.size,
-              vnode->status.data_version,
-              vnode->status.mode);
+              status->type,
+              status->nlink,
+              (unsigned long long) status->size,
+              status->data_version,
+              status->mode);
 
-       read_seqlock_excl(&vnode->cb_lock);
+       write_seqlock(&vnode->cb_lock);
 
-       afs_update_inode_from_status(vnode, &vnode->status, NULL,
-                                    AFS_VNODE_NOT_YET_SET);
+       vnode->status = *status;
 
-       switch (vnode->status.type) {
+       t = status->mtime_client;
+       inode->i_ctime = t;
+       inode->i_mtime = t;
+       inode->i_atime = t;
+       inode->i_uid = make_kuid(&init_user_ns, status->owner);
+       inode->i_gid = make_kgid(&init_user_ns, status->group);
+       set_nlink(&vnode->vfs_inode, status->nlink);
+
+       switch (status->type) {
        case AFS_FTYPE_FILE:
-               inode->i_mode   = S_IFREG | vnode->status.mode;
+               inode->i_mode   = S_IFREG | status->mode;
                inode->i_op     = &afs_file_inode_operations;
                inode->i_fop    = &afs_file_operations;
                inode->i_mapping->a_ops = &afs_fs_aops;
                break;
        case AFS_FTYPE_DIR:
-               inode->i_mode   = S_IFDIR | vnode->status.mode;
+               inode->i_mode   = S_IFDIR | status->mode;
                inode->i_op     = &afs_dir_inode_operations;
                inode->i_fop    = &afs_dir_file_operations;
                inode->i_mapping->a_ops = &afs_dir_aops;
                break;
        case AFS_FTYPE_SYMLINK:
                /* Symlinks with a mode of 0644 are actually mountpoints. */
-               if ((vnode->status.mode & 0777) == 0644) {
+               if ((status->mode & 0777) == 0644) {
                        inode->i_flags |= S_AUTOMOUNT;
 
                        set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags);
@@ -99,7 +112,7 @@ static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key,
                        inode->i_fop    = &afs_mntpt_file_operations;
                        inode->i_mapping->a_ops = &afs_fs_aops;
                } else {
-                       inode->i_mode   = S_IFLNK | vnode->status.mode;
+                       inode->i_mode   = S_IFLNK | status->mode;
                        inode->i_op     = &afs_symlink_inode_operations;
                        inode->i_mapping->a_ops = &afs_fs_aops;
                }
@@ -107,7 +120,7 @@ static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key,
                break;
        default:
                dump_vnode(vnode, parent_vnode);
-               read_sequnlock_excl(&vnode->cb_lock);
+               write_sequnlock(&vnode->cb_lock);
                return afs_protocol_error(NULL, -EBADMSG, afs_eproto_file_type);
        }
 
@@ -116,17 +129,175 @@ static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key,
         * for consistency with other AFS clients.
         */
        inode->i_blocks         = ((i_size_read(inode) + 1023) >> 10) << 1;
-       vnode->invalid_before   = vnode->status.data_version;
+       i_size_write(&vnode->vfs_inode, status->size);
+
+       vnode->invalid_before   = status->data_version;
+       inode_set_iversion_raw(&vnode->vfs_inode, status->data_version);
+
+       if (!scb->have_cb) {
+               /* it's a symlink we just created (the fileserver
+                * didn't give us a callback) */
+               vnode->cb_expires_at = ktime_get_real_seconds();
+       } else {
+               vnode->cb_expires_at = scb->callback.expires_at;
+               old_cbi = rcu_dereference_protected(vnode->cb_interest,
+                                                   lockdep_is_held(&vnode->cb_lock.lock));
+               if (cbi != old_cbi)
+                       rcu_assign_pointer(vnode->cb_interest, afs_get_cb_interest(cbi));
+               else
+                       old_cbi = NULL;
+               set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
+       }
 
-       read_sequnlock_excl(&vnode->cb_lock);
+       write_sequnlock(&vnode->cb_lock);
+       afs_put_cb_interest(afs_v2net(vnode), old_cbi);
        return 0;
 }
 
+/*
+ * Update the core inode struct from a returned status record.
+ */
+static void afs_apply_status(struct afs_fs_cursor *fc,
+                            struct afs_vnode *vnode,
+                            struct afs_status_cb *scb,
+                            const afs_dataversion_t *expected_version)
+{
+       struct afs_file_status *status = &scb->status;
+       struct timespec64 t;
+       umode_t mode;
+       bool data_changed = false;
+
+       BUG_ON(test_bit(AFS_VNODE_UNSET, &vnode->flags));
+
+       if (status->type != vnode->status.type) {
+               pr_warning("Vnode %llx:%llx:%x changed type %u to %u\n",
+                          vnode->fid.vid,
+                          vnode->fid.vnode,
+                          vnode->fid.unique,
+                          status->type, vnode->status.type);
+               afs_protocol_error(NULL, -EBADMSG, afs_eproto_bad_status);
+               return;
+       }
+
+       if (status->nlink != vnode->status.nlink)
+               set_nlink(&vnode->vfs_inode, status->nlink);
+
+       if (status->owner != vnode->status.owner)
+               vnode->vfs_inode.i_uid = make_kuid(&init_user_ns, status->owner);
+
+       if (status->group != vnode->status.group)
+               vnode->vfs_inode.i_gid = make_kgid(&init_user_ns, status->group);
+
+       if (status->mode != vnode->status.mode) {
+               mode = vnode->vfs_inode.i_mode;
+               mode &= ~S_IALLUGO;
+               mode |= status->mode;
+               WRITE_ONCE(vnode->vfs_inode.i_mode, mode);
+       }
+
+       t = status->mtime_client;
+       vnode->vfs_inode.i_ctime = t;
+       vnode->vfs_inode.i_mtime = t;
+       vnode->vfs_inode.i_atime = t;
+
+       if (vnode->status.data_version != status->data_version)
+               data_changed = true;
+
+       vnode->status = *status;
+
+       if (expected_version &&
+           *expected_version != status->data_version) {
+               kdebug("vnode modified %llx on {%llx:%llu} [exp %llx] %s",
+                      (unsigned long long) status->data_version,
+                      vnode->fid.vid, vnode->fid.vnode,
+                      (unsigned long long) *expected_version,
+                      fc->type ? fc->type->name : "???");
+               vnode->invalid_before = status->data_version;
+               if (vnode->status.type == AFS_FTYPE_DIR) {
+                       if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
+                               afs_stat_v(vnode, n_inval);
+               } else {
+                       set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
+               }
+       } else if (vnode->status.type == AFS_FTYPE_DIR) {
+               /* Expected directory change is handled elsewhere so
+                * that we can locally edit the directory and save on a
+                * download.
+                */
+               if (test_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
+                       data_changed = false;
+       }
+
+       if (data_changed) {
+               inode_set_iversion_raw(&vnode->vfs_inode, status->data_version);
+               i_size_write(&vnode->vfs_inode, status->size);
+       }
+}
+
+/*
+ * Apply a callback to a vnode.
+ */
+static void afs_apply_callback(struct afs_fs_cursor *fc,
+                              struct afs_vnode *vnode,
+                              struct afs_status_cb *scb,
+                              unsigned int cb_break)
+{
+       struct afs_cb_interest *old;
+       struct afs_callback *cb = &scb->callback;
+
+       if (!afs_cb_is_broken(cb_break, vnode, fc->cbi)) {
+               vnode->cb_expires_at    = cb->expires_at;
+               old = rcu_dereference_protected(vnode->cb_interest,
+                                               lockdep_is_held(&vnode->cb_lock.lock));
+               if (old != fc->cbi) {
+                       rcu_assign_pointer(vnode->cb_interest, afs_get_cb_interest(fc->cbi));
+                       afs_put_cb_interest(afs_v2net(vnode), old);
+               }
+               set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
+       }
+}
+
+/*
+ * Apply the received status and callback to an inode all in the same critical
+ * section to avoid races with afs_validate().
+ */
+void afs_vnode_commit_status(struct afs_fs_cursor *fc,
+                            struct afs_vnode *vnode,
+                            unsigned int cb_break,
+                            const afs_dataversion_t *expected_version,
+                            struct afs_status_cb *scb)
+{
+       if (fc->ac.error != 0)
+               return;
+
+       write_seqlock(&vnode->cb_lock);
+
+       if (scb->have_error) {
+               if (scb->status.abort_code == VNOVNODE) {
+                       set_bit(AFS_VNODE_DELETED, &vnode->flags);
+                       clear_nlink(&vnode->vfs_inode);
+                       __afs_break_callback(vnode);
+               }
+       } else {
+               if (scb->have_status)
+                       afs_apply_status(fc, vnode, scb, expected_version);
+               if (scb->have_cb)
+                       afs_apply_callback(fc, vnode, scb, cb_break);
+       }
+
+       write_sequnlock(&vnode->cb_lock);
+
+       if (fc->ac.error == 0 && scb->have_status)
+               afs_cache_permit(vnode, fc->key, cb_break, scb);
+}
+
 /*
  * Fetch file status from the volume.
  */
-int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode)
+int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool is_new,
+                    afs_access_t *_caller_access)
 {
+       struct afs_status_cb *scb;
        struct afs_fs_cursor fc;
        int ret;
 
@@ -135,18 +306,38 @@ int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode)
               vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique,
               vnode->flags);
 
+       scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               return -ENOMEM;
+
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
+               afs_dataversion_t data_version = vnode->status.data_version;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
-                       afs_fs_fetch_file_status(&fc, NULL, new_inode);
+                       afs_fs_fetch_file_status(&fc, scb, NULL);
                }
 
-               afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, vnode, fc.cb_break);
+               if (fc.error) {
+                       /* Do nothing. */
+               } else if (is_new) {
+                       ret = afs_inode_init_from_status(vnode, key, fc.cbi,
+                                                        NULL, scb);
+                       fc.error = ret;
+                       if (ret == 0)
+                               afs_cache_permit(vnode, key, fc.cb_break, scb);
+               } else {
+                       afs_vnode_commit_status(&fc, vnode, fc.cb_break,
+                                               &data_version, scb);
+               }
+               afs_check_for_remote_deletion(&fc, vnode);
                ret = afs_end_vnode_operation(&fc);
        }
 
+       if (ret == 0 && _caller_access)
+               *_caller_access = scb->status.caller_access;
+       kfree(scb);
        _leave(" = %d", ret);
        return ret;
 }
@@ -156,10 +347,10 @@ int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode)
  */
 int afs_iget5_test(struct inode *inode, void *opaque)
 {
-       struct afs_iget_data *data = opaque;
+       struct afs_iget_data *iget_data = opaque;
        struct afs_vnode *vnode = AFS_FS_I(inode);
 
-       return memcmp(&vnode->fid, &data->fid, sizeof(data->fid)) == 0;
+       return memcmp(&vnode->fid, &iget_data->fid, sizeof(iget_data->fid)) == 0;
 }
 
 /*
@@ -177,17 +368,19 @@ static int afs_iget5_pseudo_dir_test(struct inode *inode, void *opaque)
  */
 static int afs_iget5_set(struct inode *inode, void *opaque)
 {
-       struct afs_iget_data *data = opaque;
+       struct afs_iget_data *iget_data = opaque;
        struct afs_vnode *vnode = AFS_FS_I(inode);
 
-       vnode->fid = data->fid;
-       vnode->volume = data->volume;
+       vnode->fid              = iget_data->fid;
+       vnode->volume           = iget_data->volume;
+       vnode->cb_v_break       = iget_data->cb_v_break;
+       vnode->cb_s_break       = iget_data->cb_s_break;
 
        /* YFS supports 96-bit vnode IDs, but Linux only supports
         * 64-bit inode numbers.
         */
-       inode->i_ino data->fid.vnode;
-       inode->i_generation data->fid.unique;
+       inode->i_ino            = iget_data->fid.vnode;
+       inode->i_generation     = iget_data->fid.unique;
        return 0;
 }
 
@@ -197,38 +390,42 @@ static int afs_iget5_set(struct inode *inode, void *opaque)
  */
 struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root)
 {
-       struct afs_iget_data data;
        struct afs_super_info *as;
        struct afs_vnode *vnode;
        struct inode *inode;
        static atomic_t afs_autocell_ino;
 
+       struct afs_iget_data iget_data = {
+               .cb_v_break = 0,
+               .cb_s_break = 0,
+       };
+
        _enter("");
 
        as = sb->s_fs_info;
        if (as->volume) {
-               data.volume = as->volume;
-               data.fid.vid = as->volume->vid;
+               iget_data.volume = as->volume;
+               iget_data.fid.vid = as->volume->vid;
        }
        if (root) {
-               data.fid.vnode = 1;
-               data.fid.unique = 1;
+               iget_data.fid.vnode = 1;
+               iget_data.fid.unique = 1;
        } else {
-               data.fid.vnode = atomic_inc_return(&afs_autocell_ino);
-               data.fid.unique = 0;
+               iget_data.fid.vnode = atomic_inc_return(&afs_autocell_ino);
+               iget_data.fid.unique = 0;
        }
 
-       inode = iget5_locked(sb, data.fid.vnode,
+       inode = iget5_locked(sb, iget_data.fid.vnode,
                             afs_iget5_pseudo_dir_test, afs_iget5_set,
-                            &data);
+                            &iget_data);
        if (!inode) {
                _leave(" = -ENOMEM");
                return ERR_PTR(-ENOMEM);
        }
 
        _debug("GOT INODE %p { ino=%lu, vl=%llx, vn=%llx, u=%x }",
-              inode, inode->i_ino, data.fid.vid, data.fid.vnode,
-              data.fid.unique);
+              inode, inode->i_ino, iget_data.fid.vid, iget_data.fid.vnode,
+              iget_data.fid.unique);
 
        vnode = AFS_FS_I(inode);
 
@@ -299,23 +496,24 @@ static void afs_get_inode_cache(struct afs_vnode *vnode)
  * inode retrieval
  */
 struct inode *afs_iget(struct super_block *sb, struct key *key,
-                      struct afs_fid *fid, struct afs_file_status *status,
-                      struct afs_callback *cb, struct afs_cb_interest *cbi,
+                      struct afs_iget_data *iget_data,
+                      struct afs_status_cb *scb,
+                      struct afs_cb_interest *cbi,
                       struct afs_vnode *parent_vnode)
 {
-       struct afs_iget_data data = { .fid = *fid };
        struct afs_super_info *as;
        struct afs_vnode *vnode;
+       struct afs_fid *fid = &iget_data->fid;
        struct inode *inode;
        int ret;
 
        _enter(",{%llx:%llu.%u},,", fid->vid, fid->vnode, fid->unique);
 
        as = sb->s_fs_info;
-       data.volume = as->volume;
+       iget_data->volume = as->volume;
 
        inode = iget5_locked(sb, fid->vnode, afs_iget5_test, afs_iget5_set,
-                            &data);
+                            iget_data);
        if (!inode) {
                _leave(" = -ENOMEM");
                return ERR_PTR(-ENOMEM);
@@ -332,43 +530,25 @@ struct inode *afs_iget(struct super_block *sb, struct key *key,
                return inode;
        }
 
-       if (!status) {
+       if (!scb) {
                /* it's a remotely extant inode */
-               ret = afs_fetch_status(vnode, key, true);
+               ret = afs_fetch_status(vnode, key, true, NULL);
                if (ret < 0)
                        goto bad_inode;
        } else {
-               /* it's an inode we just created */
-               memcpy(&vnode->status, status, sizeof(vnode->status));
-
-               if (!cb) {
-                       /* it's a symlink we just created (the fileserver
-                        * didn't give us a callback) */
-                       vnode->cb_version = 0;
-                       vnode->cb_type = 0;
-                       vnode->cb_expires_at = ktime_get();
-               } else {
-                       vnode->cb_version = cb->version;
-                       vnode->cb_type = cb->type;
-                       vnode->cb_expires_at = cb->expires_at;
-                       vnode->cb_interest = afs_get_cb_interest(cbi);
-                       set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
-               }
-
-               vnode->cb_expires_at += ktime_get_real_seconds();
+               ret = afs_inode_init_from_status(vnode, key, cbi, parent_vnode,
+                                                scb);
+               if (ret < 0)
+                       goto bad_inode;
        }
 
-       ret = afs_inode_init_from_status(vnode, key, parent_vnode);
-       if (ret < 0)
-               goto bad_inode;
-
        afs_get_inode_cache(vnode);
 
        /* success */
        clear_bit(AFS_VNODE_UNSET, &vnode->flags);
        inode->i_flags |= S_NOATIME;
        unlock_new_inode(inode);
-       _leave(" = %p [CB { v=%u t=%u }]", inode, vnode->cb_version, vnode->cb_type);
+       _leave(" = %p", inode);
        return inode;
 
        /* failure */
@@ -399,6 +579,66 @@ void afs_zap_data(struct afs_vnode *vnode)
                invalidate_inode_pages2(vnode->vfs_inode.i_mapping);
 }
 
+/*
+ * Check the validity of a vnode/inode.
+ */
+bool afs_check_validity(struct afs_vnode *vnode)
+{
+       struct afs_cb_interest *cbi;
+       struct afs_server *server;
+       struct afs_volume *volume = vnode->volume;
+       time64_t now = ktime_get_real_seconds();
+       bool valid, need_clear = false;
+       unsigned int cb_break, cb_s_break, cb_v_break;
+       int seq = 0;
+
+       do {
+               read_seqbegin_or_lock(&vnode->cb_lock, &seq);
+               cb_v_break = READ_ONCE(volume->cb_v_break);
+               cb_break = vnode->cb_break;
+
+               if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
+                       cbi = rcu_dereference(vnode->cb_interest);
+                       server = rcu_dereference(cbi->server);
+                       cb_s_break = READ_ONCE(server->cb_s_break);
+
+                       if (vnode->cb_s_break != cb_s_break ||
+                           vnode->cb_v_break != cb_v_break) {
+                               vnode->cb_s_break = cb_s_break;
+                               vnode->cb_v_break = cb_v_break;
+                               need_clear = true;
+                               valid = false;
+                       } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
+                               need_clear = true;
+                               valid = false;
+                       } else if (vnode->cb_expires_at - 10 <= now) {
+                               need_clear = true;
+                               valid = false;
+                       } else {
+                               valid = true;
+                       }
+               } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
+                       valid = true;
+               } else {
+                       vnode->cb_v_break = cb_v_break;
+                       valid = false;
+               }
+
+       } while (need_seqretry(&vnode->cb_lock, seq));
+
+       done_seqretry(&vnode->cb_lock, seq);
+
+       if (need_clear) {
+               write_seqlock(&vnode->cb_lock);
+               if (cb_break == vnode->cb_break)
+                       __afs_break_callback(vnode);
+               write_sequnlock(&vnode->cb_lock);
+               valid = false;
+       }
+
+       return valid;
+}
+
 /*
  * validate a vnode/inode
  * - there are several things we need to check
@@ -410,7 +650,6 @@ void afs_zap_data(struct afs_vnode *vnode)
  */
 int afs_validate(struct afs_vnode *vnode, struct key *key)
 {
-       time64_t now = ktime_get_real_seconds();
        bool valid;
        int ret;
 
@@ -418,36 +657,9 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
               vnode->fid.vid, vnode->fid.vnode, vnode->flags,
               key_serial(key));
 
-       /* Quickly check the callback state.  Ideally, we'd use read_seqbegin
-        * here, but we have no way to pass the net namespace to the RCU
-        * cleanup for the server record.
-        */
-       read_seqlock_excl(&vnode->cb_lock);
-
-       if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
-               if (vnode->cb_s_break != vnode->cb_interest->server->cb_s_break ||
-                   vnode->cb_v_break != vnode->volume->cb_v_break) {
-                       vnode->cb_s_break = vnode->cb_interest->server->cb_s_break;
-                       vnode->cb_v_break = vnode->volume->cb_v_break;
-                       valid = false;
-               } else if (vnode->status.type == AFS_FTYPE_DIR &&
-                          (!test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) ||
-                           vnode->cb_expires_at - 10 <= now)) {
-                       valid = false;
-               } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) ||
-                          vnode->cb_expires_at - 10 <= now) {
-                       valid = false;
-               } else {
-                       valid = true;
-               }
-       } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
-               valid = true;
-       } else {
-               vnode->cb_v_break = vnode->volume->cb_v_break;
-               valid = false;
-       }
-
-       read_sequnlock_excl(&vnode->cb_lock);
+       rcu_read_lock();
+       valid = afs_check_validity(vnode);
+       rcu_read_unlock();
 
        if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
                clear_nlink(&vnode->vfs_inode);
@@ -463,7 +675,7 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
         * access */
        if (!test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
                _debug("not promised");
-               ret = afs_fetch_status(vnode, key, false);
+               ret = afs_fetch_status(vnode, key, false, NULL);
                if (ret < 0) {
                        if (ret == -ENOENT) {
                                set_bit(AFS_VNODE_DELETED, &vnode->flags);
@@ -534,6 +746,7 @@ int afs_drop_inode(struct inode *inode)
  */
 void afs_evict_inode(struct inode *inode)
 {
+       struct afs_cb_interest *cbi;
        struct afs_vnode *vnode;
 
        vnode = AFS_FS_I(inode);
@@ -550,10 +763,14 @@ void afs_evict_inode(struct inode *inode)
        truncate_inode_pages_final(&inode->i_data);
        clear_inode(inode);
 
-       if (vnode->cb_interest) {
-               afs_put_cb_interest(afs_i2net(inode), vnode->cb_interest);
-               vnode->cb_interest = NULL;
+       write_seqlock(&vnode->cb_lock);
+       cbi = rcu_dereference_protected(vnode->cb_interest,
+                                       lockdep_is_held(&vnode->cb_lock.lock));
+       if (cbi) {
+               afs_put_cb_interest(afs_i2net(inode), cbi);
+               rcu_assign_pointer(vnode->cb_interest, NULL);
        }
+       write_sequnlock(&vnode->cb_lock);
 
        while (!list_empty(&vnode->wb_keys)) {
                struct afs_wb_key *wbk = list_entry(vnode->wb_keys.next,
@@ -573,6 +790,7 @@ void afs_evict_inode(struct inode *inode)
        }
 #endif
 
+       afs_prune_wb_keys(vnode);
        afs_put_permits(rcu_access_pointer(vnode->permit_cache));
        key_put(vnode->silly_key);
        vnode->silly_key = NULL;
@@ -587,9 +805,10 @@ void afs_evict_inode(struct inode *inode)
 int afs_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct afs_fs_cursor fc;
+       struct afs_status_cb *scb;
        struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
        struct key *key;
-       int ret;
+       int ret = -ENOMEM;
 
        _enter("{%llx:%llu},{n=%pd},%x",
               vnode->fid.vid, vnode->fid.vnode, dentry,
@@ -601,6 +820,10 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
                return 0;
        }
 
+       scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL);
+       if (!scb)
+               goto error;
+
        /* flush any dirty data outstanding on a regular file */
        if (S_ISREG(vnode->vfs_inode.i_mode))
                filemap_write_and_wait(vnode->vfs_inode.i_mapping);
@@ -611,25 +834,33 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
                key = afs_request_key(vnode->volume->cell);
                if (IS_ERR(key)) {
                        ret = PTR_ERR(key);
-                       goto error;
+                       goto error_scb;
                }
        }
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, key, false)) {
+               afs_dataversion_t data_version = vnode->status.data_version;
+
+               if (attr->ia_valid & ATTR_SIZE)
+                       data_version++;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
-                       afs_fs_setattr(&fc, attr);
+                       afs_fs_setattr(&fc, attr, scb);
                }
 
-               afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, vnode, fc.cb_break);
+               afs_check_for_remote_deletion(&fc, vnode);
+               afs_vnode_commit_status(&fc, vnode, fc.cb_break,
+                                       &data_version, scb);
                ret = afs_end_vnode_operation(&fc);
        }
 
        if (!(attr->ia_valid & ATTR_FILE))
                key_put(key);
 
+error_scb:
+       kfree(scb);
 error:
        _leave(" = %d", ret);
        return ret;
index b3cd6e8..2073c1a 100644 (file)
@@ -66,6 +66,8 @@ struct afs_fs_context {
 struct afs_iget_data {
        struct afs_fid          fid;
        struct afs_volume       *volume;        /* volume on which resides */
+       unsigned int            cb_v_break;     /* Pre-fetch volume break count */
+       unsigned int            cb_s_break;     /* Pre-fetch server break count */
 };
 
 enum afs_call_state {
@@ -111,8 +113,12 @@ struct afs_call {
        struct rxrpc_call       *rxcall;        /* RxRPC call handle */
        struct key              *key;           /* security for this call */
        struct afs_net          *net;           /* The network namespace */
-       struct afs_server       *cm_server;     /* Server affected by incoming CM call */
+       union {
+               struct afs_server       *server;
+               struct afs_vlserver     *vlserver;
+       };
        struct afs_cb_interest  *cbi;           /* Callback interest for server used */
+       struct afs_vnode        *lvnode;        /* vnode being locked */
        void                    *request;       /* request data (first part) */
        struct address_space    *mapping;       /* Pages being written from */
        struct iov_iter         iter;           /* Buffer iterator */
@@ -122,7 +128,20 @@ struct afs_call {
                struct bio_vec  bvec[1];
        };
        void                    *buffer;        /* reply receive buffer */
-       void                    *reply[4];      /* Where to put the reply */
+       union {
+               long                    ret0;   /* Value to reply with instead of 0 */
+               struct afs_addr_list    *ret_alist;
+               struct afs_vldb_entry   *ret_vldb;
+               struct afs_acl          *ret_acl;
+       };
+       struct afs_fid          *out_fid;
+       struct afs_status_cb    *out_dir_scb;
+       struct afs_status_cb    *out_scb;
+       struct yfs_acl          *out_yacl;
+       struct afs_volsync      *out_volsync;
+       struct afs_volume_status *out_volstatus;
+       struct afs_read         *read_request;
+       unsigned int            server_index;
        pgoff_t                 first;          /* first page in mapping to deal with */
        pgoff_t                 last;           /* last page in mapping to deal with */
        atomic_t                usage;
@@ -131,10 +150,10 @@ struct afs_call {
        int                     error;          /* error code */
        u32                     abort_code;     /* Remote abort ID or 0 */
        u32                     epoch;
+       unsigned int            max_lifespan;   /* Maximum lifespan to set if not 0 */
        unsigned                request_size;   /* size of request data */
        unsigned                reply_max;      /* maximum size of reply */
        unsigned                first_offset;   /* offset into mapping[first] */
-       unsigned int            cb_break;       /* cb_break + cb_s_break before the call */
        union {
                unsigned        last_to;        /* amount of mapping[last] */
                unsigned        count2;         /* count used in unmarshalling */
@@ -145,9 +164,9 @@ struct afs_call {
        bool                    send_pages;     /* T if data from mapping should be sent */
        bool                    need_attention; /* T if RxRPC poked us */
        bool                    async;          /* T if asynchronous */
-       bool                    ret_reply0;     /* T if should return reply[0] on success */
        bool                    upgrade;        /* T to request service upgrade */
-       bool                    want_reply_time; /* T if want reply_time */
+       bool                    have_reply_time; /* T if have got reply_time */
+       bool                    intr;           /* T if interruptible */
        u16                     service_id;     /* Actual service ID (after upgrade) */
        unsigned int            debug_id;       /* Trace ID */
        u32                     operation_ID;   /* operation ID for an incoming call */
@@ -159,8 +178,6 @@ struct afs_call {
                } __attribute__((packed));
                __be64          tmp64;
        };
-       afs_dataversion_t       expected_version; /* Updated version expected from store */
-       afs_dataversion_t       expected_version_2; /* 2nd updated version expected from store */
        ktime_t                 reply_time;     /* Time of first reply packet */
 };
 
@@ -221,7 +238,8 @@ struct afs_read {
        unsigned int            index;          /* Which page we're reading into */
        unsigned int            nr_pages;
        unsigned int            offset;         /* offset into current page */
-       void (*page_done)(struct afs_call *, struct afs_read *);
+       struct afs_vnode        *vnode;
+       void (*page_done)(struct afs_read *);
        struct page             **pages;
        struct page             *array[];
 };
@@ -367,13 +385,13 @@ struct afs_cell {
        time64_t                last_inactive;  /* Time of last drop of usage count */
        atomic_t                usage;
        unsigned long           flags;
-#define AFS_CELL_FL_NOT_READY  0               /* The cell record is not ready for use */
-#define AFS_CELL_FL_NO_GC      1               /* The cell was added manually, don't auto-gc */
-#define AFS_CELL_FL_NOT_FOUND  2               /* Permanent DNS error */
-#define AFS_CELL_FL_DNS_FAIL   3               /* Failed to access DNS */
-#define AFS_CELL_FL_NO_LOOKUP_YET 4            /* Not completed first DNS lookup yet */
+#define AFS_CELL_FL_NO_GC      0               /* The cell was added manually, don't auto-gc */
+#define AFS_CELL_FL_DO_LOOKUP  1               /* DNS lookup requested */
        enum afs_cell_state     state;
        short                   error;
+       enum dns_record_source  dns_source:8;   /* Latest source of data from lookup */
+       enum dns_lookup_status  dns_status:8;   /* Latest status of data from lookup */
+       unsigned int            dns_lookup_count; /* Counter of DNS lookups */
 
        /* Active fileserver interaction state. */
        struct list_head        proc_volumes;   /* procfs volume list */
@@ -538,7 +556,10 @@ struct afs_server {
 struct afs_vol_interest {
        struct hlist_node       srv_link;       /* Link in server->cb_volumes */
        struct hlist_head       cb_interests;   /* List of callback interests on the server */
-       afs_volid_t             vid;            /* Volume ID to match */
+       union {
+               struct rcu_head rcu;
+               afs_volid_t     vid;            /* Volume ID to match */
+       };
        unsigned int            usage;
 };
 
@@ -550,7 +571,10 @@ struct afs_cb_interest {
        struct afs_vol_interest *vol_interest;
        struct afs_server       *server;        /* Server on which this interest resides */
        struct super_block      *sb;            /* Superblock on which inodes reside */
-       afs_volid_t             vid;            /* Volume ID to match */
+       union {
+               struct rcu_head rcu;
+               afs_volid_t     vid;            /* Volume ID to match */
+       };
        refcount_t              usage;
 };
 
@@ -660,15 +684,13 @@ struct afs_vnode {
        afs_lock_type_t         lock_type : 8;
 
        /* outstanding callback notification on this file */
-       struct afs_cb_interest  *cb_interest;   /* Server on which this resides */
+       struct afs_cb_interest __rcu *cb_interest; /* Server on which this resides */
        unsigned int            cb_s_break;     /* Mass break counter on ->server */
        unsigned int            cb_v_break;     /* Mass break counter on ->volume */
        unsigned int            cb_break;       /* Break counter on vnode */
        seqlock_t               cb_lock;        /* Lock for ->cb_interest, ->status, ->cb_*break */
 
        time64_t                cb_expires_at;  /* time at which callback expires */
-       unsigned                cb_version;     /* callback version */
-       afs_callback_type_t     cb_type;        /* type of callback */
 };
 
 static inline struct fscache_cookie *afs_vnode_cache(struct afs_vnode *vnode)
@@ -755,6 +777,7 @@ struct afs_vl_cursor {
  * Cursor for iterating over a set of fileservers.
  */
 struct afs_fs_cursor {
+       const struct afs_call_type *type;       /* Type of call done */
        struct afs_addr_cursor  ac;
        struct afs_vnode        *vnode;
        struct afs_server_list  *server_list;   /* Current server list (pins ref) */
@@ -772,6 +795,7 @@ struct afs_fs_cursor {
 #define AFS_FS_CURSOR_VNOVOL   0x0008          /* Set if seen VNOVOL */
 #define AFS_FS_CURSOR_CUR_ONLY 0x0010          /* Set if current server only (file lock held) */
 #define AFS_FS_CURSOR_NO_VSLEEP        0x0020          /* Set to prevent sleep on VBUSY, VOFFLINE, ... */
+#define AFS_FS_CURSOR_INTR     0x0040          /* Set if op is interruptible */
        unsigned short          nr_iterations;  /* Number of server iterations */
 };
 
@@ -882,7 +906,6 @@ extern const struct address_space_operations afs_dir_aops;
 extern const struct dentry_operations afs_fs_dentry_operations;
 
 extern void afs_d_release(struct dentry *);
-extern int afs_dir_remove_link(struct dentry *, struct key *, unsigned long, unsigned long);
 
 /*
  * dir_edit.c
@@ -940,50 +963,48 @@ extern int afs_flock(struct file *, int, struct file_lock *);
 /*
  * fsclient.c
  */
-#define AFS_VNODE_NOT_YET_SET  0x01
-#define AFS_VNODE_META_CHANGED 0x02
-#define AFS_VNODE_DATA_CHANGED 0x04
-extern void afs_update_inode_from_status(struct afs_vnode *, struct afs_file_status *,
-                                        const afs_dataversion_t *, u8);
-
-extern int afs_fs_fetch_file_status(struct afs_fs_cursor *, struct afs_volsync *, bool);
+extern int afs_fs_fetch_file_status(struct afs_fs_cursor *, struct afs_status_cb *,
+                                   struct afs_volsync *);
 extern int afs_fs_give_up_callbacks(struct afs_net *, struct afs_server *);
-extern int afs_fs_fetch_data(struct afs_fs_cursor *, struct afs_read *);
-extern int afs_fs_create(struct afs_fs_cursor *, const char *, umode_t, u64,
-                        struct afs_fid *, struct afs_file_status *, struct afs_callback *);
-extern int afs_fs_remove(struct afs_fs_cursor *, struct afs_vnode *, const char *, bool, u64);
-extern int afs_fs_link(struct afs_fs_cursor *, struct afs_vnode *, const char *, u64);
-extern int afs_fs_symlink(struct afs_fs_cursor *, const char *, const char *, u64,
-                         struct afs_fid *, struct afs_file_status *);
+extern int afs_fs_fetch_data(struct afs_fs_cursor *, struct afs_status_cb *, struct afs_read *);
+extern int afs_fs_create(struct afs_fs_cursor *, const char *, umode_t,
+                        struct afs_status_cb *, struct afs_fid *, struct afs_status_cb *);
+extern int afs_fs_remove(struct afs_fs_cursor *, struct afs_vnode *, const char *, bool,
+                        struct afs_status_cb *);
+extern int afs_fs_link(struct afs_fs_cursor *, struct afs_vnode *, const char *,
+                      struct afs_status_cb *, struct afs_status_cb *);
+extern int afs_fs_symlink(struct afs_fs_cursor *, const char *, const char *,
+                         struct afs_status_cb *, struct afs_fid *, struct afs_status_cb *);
 extern int afs_fs_rename(struct afs_fs_cursor *, const char *,
-                        struct afs_vnode *, const char *, u64, u64);
+                        struct afs_vnode *, const char *,
+                        struct afs_status_cb *, struct afs_status_cb *);
 extern int afs_fs_store_data(struct afs_fs_cursor *, struct address_space *,
-                            pgoff_t, pgoff_t, unsigned, unsigned);
-extern int afs_fs_setattr(struct afs_fs_cursor *, struct iattr *);
+                            pgoff_t, pgoff_t, unsigned, unsigned, struct afs_status_cb *);
+extern int afs_fs_setattr(struct afs_fs_cursor *, struct iattr *, struct afs_status_cb *);
 extern int afs_fs_get_volume_status(struct afs_fs_cursor *, struct afs_volume_status *);
-extern int afs_fs_set_lock(struct afs_fs_cursor *, afs_lock_type_t);
-extern int afs_fs_extend_lock(struct afs_fs_cursor *);
-extern int afs_fs_release_lock(struct afs_fs_cursor *);
+extern int afs_fs_set_lock(struct afs_fs_cursor *, afs_lock_type_t, struct afs_status_cb *);
+extern int afs_fs_extend_lock(struct afs_fs_cursor *, struct afs_status_cb *);
+extern int afs_fs_release_lock(struct afs_fs_cursor *, struct afs_status_cb *);
 extern int afs_fs_give_up_all_callbacks(struct afs_net *, struct afs_server *,
                                        struct afs_addr_cursor *, struct key *);
 extern struct afs_call *afs_fs_get_capabilities(struct afs_net *, struct afs_server *,
                                                struct afs_addr_cursor *, struct key *,
                                                unsigned int);
 extern int afs_fs_inline_bulk_status(struct afs_fs_cursor *, struct afs_net *,
-                                    struct afs_fid *, struct afs_file_status *,
-                                    struct afs_callback *, unsigned int,
-                                    struct afs_volsync *);
+                                    struct afs_fid *, struct afs_status_cb *,
+                                    unsigned int, struct afs_volsync *);
 extern int afs_fs_fetch_status(struct afs_fs_cursor *, struct afs_net *,
-                              struct afs_fid *, struct afs_file_status *,
-                              struct afs_callback *, struct afs_volsync *);
+                              struct afs_fid *, struct afs_status_cb *,
+                              struct afs_volsync *);
 
 struct afs_acl {
        u32     size;
        u8      data[];
 };
 
-extern struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *);
-extern int afs_fs_store_acl(struct afs_fs_cursor *, const struct afs_acl *);
+extern struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *, struct afs_status_cb *);
+extern int afs_fs_store_acl(struct afs_fs_cursor *, const struct afs_acl *,
+                           struct afs_status_cb *);
 
 /*
  * fs_probe.c
@@ -995,15 +1016,20 @@ extern int afs_wait_for_fs_probes(struct afs_server_list *, unsigned long);
 /*
  * inode.c
  */
-extern int afs_fetch_status(struct afs_vnode *, struct key *, bool);
+extern void afs_vnode_commit_status(struct afs_fs_cursor *,
+                                   struct afs_vnode *,
+                                   unsigned int,
+                                   const afs_dataversion_t *,
+                                   struct afs_status_cb *);
+extern int afs_fetch_status(struct afs_vnode *, struct key *, bool, afs_access_t *);
 extern int afs_iget5_test(struct inode *, void *);
 extern struct inode *afs_iget_pseudo_dir(struct super_block *, bool);
 extern struct inode *afs_iget(struct super_block *, struct key *,
-                             struct afs_fid *, struct afs_file_status *,
-                             struct afs_callback *,
+                             struct afs_iget_data *, struct afs_status_cb *,
                              struct afs_cb_interest *,
                              struct afs_vnode *);
 extern void afs_zap_data(struct afs_vnode *);
+extern bool afs_check_validity(struct afs_vnode *);
 extern int afs_validate(struct afs_vnode *, struct key *);
 extern int afs_getattr(const struct path *, struct kstat *, u32, unsigned int);
 extern int afs_setattr(struct dentry *, struct iattr *);
@@ -1096,7 +1122,7 @@ static inline void afs_put_sysnames(struct afs_sysnames *sysnames) {}
  * rotate.c
  */
 extern bool afs_begin_vnode_operation(struct afs_fs_cursor *, struct afs_vnode *,
-                                     struct key *);
+                                     struct key *, bool);
 extern bool afs_select_fileserver(struct afs_fs_cursor *);
 extern bool afs_select_current_fileserver(struct afs_fs_cursor *);
 extern int afs_end_vnode_operation(struct afs_fs_cursor *);
@@ -1121,6 +1147,12 @@ extern void afs_send_simple_reply(struct afs_call *, const void *, size_t);
 extern int afs_extract_data(struct afs_call *, bool);
 extern int afs_protocol_error(struct afs_call *, int, enum afs_eproto_cause);
 
+static inline void afs_set_fc_call(struct afs_call *call, struct afs_fs_cursor *fc)
+{
+       call->intr = fc->flags & AFS_FS_CURSOR_INTR;
+       fc->type = call->type;
+}
+
 static inline void afs_extract_begin(struct afs_call *call, void *buf, size_t size)
 {
        call->kvec[0].iov_base = buf;
@@ -1201,7 +1233,8 @@ static inline void afs_set_call_complete(struct afs_call *call,
  */
 extern void afs_put_permits(struct afs_permits *);
 extern void afs_clear_permits(struct afs_vnode *);
-extern void afs_cache_permit(struct afs_vnode *, struct key *, unsigned int);
+extern void afs_cache_permit(struct afs_vnode *, struct key *, unsigned int,
+                            struct afs_status_cb *);
 extern void afs_zap_permits(struct rcu_head *);
 extern struct key *afs_request_key(struct afs_cell *);
 extern int afs_check_permit(struct afs_vnode *, struct key *, afs_access_t *);
@@ -1327,7 +1360,6 @@ extern int afs_write_end(struct file *file, struct address_space *mapping,
                        struct page *page, void *fsdata);
 extern int afs_writepage(struct page *, struct writeback_control *);
 extern int afs_writepages(struct address_space *, struct writeback_control *);
-extern void afs_pages_written_back(struct afs_vnode *, struct afs_call *);
 extern ssize_t afs_file_write(struct kiocb *, struct iov_iter *);
 extern int afs_fsync(struct file *, loff_t, loff_t, int);
 extern vm_fault_t afs_page_mkwrite(struct vm_fault *vmf);
@@ -1343,33 +1375,36 @@ extern ssize_t afs_listxattr(struct dentry *, char *, size_t);
 /*
  * yfsclient.c
  */
-extern int yfs_fs_fetch_file_status(struct afs_fs_cursor *, struct afs_volsync *, bool);
-extern int yfs_fs_fetch_data(struct afs_fs_cursor *, struct afs_read *);
-extern int yfs_fs_create_file(struct afs_fs_cursor *, const char *, umode_t, u64,
-                             struct afs_fid *, struct afs_file_status *, struct afs_callback *);
-extern int yfs_fs_make_dir(struct afs_fs_cursor *, const char *, umode_t, u64,
-                        struct afs_fid *, struct afs_file_status *, struct afs_callback *);
-extern int yfs_fs_remove_file2(struct afs_fs_cursor *, struct afs_vnode *, const char *, u64);
-extern int yfs_fs_remove(struct afs_fs_cursor *, struct afs_vnode *, const char *, bool, u64);
-extern int yfs_fs_link(struct afs_fs_cursor *, struct afs_vnode *, const char *, u64);
-extern int yfs_fs_symlink(struct afs_fs_cursor *, const char *, const char *, u64,
-                         struct afs_fid *, struct afs_file_status *);
-extern int yfs_fs_rename(struct afs_fs_cursor *, const char *,
-                        struct afs_vnode *, const char *, u64, u64);
+extern int yfs_fs_fetch_file_status(struct afs_fs_cursor *, struct afs_status_cb *,
+                                   struct afs_volsync *);
+extern int yfs_fs_fetch_data(struct afs_fs_cursor *, struct afs_status_cb *, struct afs_read *);
+extern int yfs_fs_create_file(struct afs_fs_cursor *, const char *, umode_t, struct afs_status_cb *,
+                             struct afs_fid *, struct afs_status_cb *);
+extern int yfs_fs_make_dir(struct afs_fs_cursor *, const char *, umode_t, struct afs_status_cb *,
+                          struct afs_fid *, struct afs_status_cb *);
+extern int yfs_fs_remove_file2(struct afs_fs_cursor *, struct afs_vnode *, const char *,
+                              struct afs_status_cb *, struct afs_status_cb *);
+extern int yfs_fs_remove(struct afs_fs_cursor *, struct afs_vnode *, const char *, bool,
+                        struct afs_status_cb *);
+extern int yfs_fs_link(struct afs_fs_cursor *, struct afs_vnode *, const char *,
+                      struct afs_status_cb *, struct afs_status_cb *);
+extern int yfs_fs_symlink(struct afs_fs_cursor *, const char *, const char *,
+                         struct afs_status_cb *, struct afs_fid *, struct afs_status_cb *);
+extern int yfs_fs_rename(struct afs_fs_cursor *, const char *, struct afs_vnode *, const char *,
+                        struct afs_status_cb *, struct afs_status_cb *);
 extern int yfs_fs_store_data(struct afs_fs_cursor *, struct address_space *,
-                            pgoff_t, pgoff_t, unsigned, unsigned);
-extern int yfs_fs_setattr(struct afs_fs_cursor *, struct iattr *);
+                            pgoff_t, pgoff_t, unsigned, unsigned, struct afs_status_cb *);
+extern int yfs_fs_setattr(struct afs_fs_cursor *, struct iattr *, struct afs_status_cb *);
 extern int yfs_fs_get_volume_status(struct afs_fs_cursor *, struct afs_volume_status *);
-extern int yfs_fs_set_lock(struct afs_fs_cursor *, afs_lock_type_t);
-extern int yfs_fs_extend_lock(struct afs_fs_cursor *);
-extern int yfs_fs_release_lock(struct afs_fs_cursor *);
+extern int yfs_fs_set_lock(struct afs_fs_cursor *, afs_lock_type_t, struct afs_status_cb *);
+extern int yfs_fs_extend_lock(struct afs_fs_cursor *, struct afs_status_cb *);
+extern int yfs_fs_release_lock(struct afs_fs_cursor *, struct afs_status_cb *);
 extern int yfs_fs_fetch_status(struct afs_fs_cursor *, struct afs_net *,
-                              struct afs_fid *, struct afs_file_status *,
-                              struct afs_callback *, struct afs_volsync *);
+                              struct afs_fid *, struct afs_status_cb *,
+                              struct afs_volsync *);
 extern int yfs_fs_inline_bulk_status(struct afs_fs_cursor *, struct afs_net *,
-                                    struct afs_fid *, struct afs_file_status *,
-                                    struct afs_callback *, unsigned int,
-                                    struct afs_volsync *);
+                                    struct afs_fid *, struct afs_status_cb *,
+                                    unsigned int, struct afs_volsync *);
 
 struct yfs_acl {
        struct afs_acl  *acl;           /* Dir/file/symlink ACL */
@@ -1382,8 +1417,10 @@ struct yfs_acl {
 };
 
 extern void yfs_free_opaque_acl(struct yfs_acl *);
-extern struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *, unsigned int);
-extern int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *, const struct afs_acl *);
+extern struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *, struct yfs_acl *,
+                                              struct afs_status_cb *);
+extern int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *, const struct afs_acl *,
+                                   struct afs_status_cb *);
 
 /*
  * Miscellaneous inline functions.
@@ -1398,14 +1435,6 @@ static inline struct inode *AFS_VNODE_TO_I(struct afs_vnode *vnode)
        return &vnode->vfs_inode;
 }
 
-static inline void afs_vnode_commit_status(struct afs_fs_cursor *fc,
-                                          struct afs_vnode *vnode,
-                                          unsigned int cb_break)
-{
-       if (fc->ac.error == 0)
-               afs_cache_permit(vnode, fc->key, cb_break);
-}
-
 static inline void afs_check_for_remote_deletion(struct afs_fs_cursor *fc,
                                                 struct afs_vnode *vnode)
 {
index be2ee3b..371501d 100644 (file)
@@ -53,7 +53,7 @@ static int afs_proc_cells_show(struct seq_file *m, void *v)
        seq_printf(m, "%3u %6lld %2u %s\n",
                   atomic_read(&cell->usage),
                   cell->dns_expiry - ktime_get_real_seconds(),
-                  vllist ? vllist->nr_servers : 0,
+                  vllist->nr_servers,
                   cell->name);
        return 0;
 }
@@ -296,8 +296,8 @@ static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v)
 
        if (v == SEQ_START_TOKEN) {
                seq_printf(m, "# source %s, status %s\n",
-                          dns_record_sources[vllist->source],
-                          dns_lookup_statuses[vllist->status]);
+                          dns_record_sources[vllist ? vllist->source : 0],
+                          dns_lookup_statuses[vllist ? vllist->status : 0]);
                return 0;
        }
 
@@ -336,7 +336,7 @@ static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos)
        if (pos == 0)
                return SEQ_START_TOKEN;
 
-       if (!vllist || pos - 1 >= vllist->nr_servers)
+       if (pos - 1 >= vllist->nr_servers)
                return NULL;
 
        return &vllist->servers[pos - 1];
index c3ae324..b00c739 100644 (file)
@@ -25,7 +25,7 @@
  * them here also using the io_lock.
  */
 bool afs_begin_vnode_operation(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
-                              struct key *key)
+                              struct key *key, bool intr)
 {
        memset(fc, 0, sizeof(*fc));
        fc->vnode = vnode;
@@ -33,10 +33,15 @@ bool afs_begin_vnode_operation(struct afs_fs_cursor *fc, struct afs_vnode *vnode
        fc->ac.error = SHRT_MAX;
        fc->error = -EDESTADDRREQ;
 
-       if (mutex_lock_interruptible(&vnode->io_lock) < 0) {
-               fc->error = -EINTR;
-               fc->flags |= AFS_FS_CURSOR_STOP;
-               return false;
+       if (intr) {
+               fc->flags |= AFS_FS_CURSOR_INTR;
+               if (mutex_lock_interruptible(&vnode->io_lock) < 0) {
+                       fc->error = -EINTR;
+                       fc->flags |= AFS_FS_CURSOR_STOP;
+                       return false;
+               }
+       } else {
+               mutex_lock(&vnode->io_lock);
        }
 
        if (vnode->lock_state != AFS_VNODE_LOCK_NONE)
@@ -61,7 +66,8 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc,
        fc->untried = (1UL << fc->server_list->nr_servers) - 1;
        fc->index = READ_ONCE(fc->server_list->preferred);
 
-       cbi = vnode->cb_interest;
+       cbi = rcu_dereference_protected(vnode->cb_interest,
+                                       lockdep_is_held(&vnode->io_lock));
        if (cbi) {
                /* See if the vnode's preferred record is still available */
                for (i = 0; i < fc->server_list->nr_servers; i++) {
@@ -82,8 +88,8 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc,
 
                /* Note that the callback promise is effectively broken */
                write_seqlock(&vnode->cb_lock);
-               ASSERTCMP(cbi, ==, vnode->cb_interest);
-               vnode->cb_interest = NULL;
+               ASSERTCMP(cbi, ==, rcu_access_pointer(vnode->cb_interest));
+               rcu_assign_pointer(vnode->cb_interest, NULL);
                if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags))
                        vnode->cb_break++;
                write_sequnlock(&vnode->cb_lock);
@@ -118,10 +124,14 @@ static void afs_busy(struct afs_volume *volume, u32 abort_code)
  */
 static bool afs_sleep_and_retry(struct afs_fs_cursor *fc)
 {
-       msleep_interruptible(1000);
-       if (signal_pending(current)) {
-               fc->error = -ERESTARTSYS;
-               return false;
+       if (fc->flags & AFS_FS_CURSOR_INTR) {
+               msleep_interruptible(1000);
+               if (signal_pending(current)) {
+                       fc->error = -ERESTARTSYS;
+                       return false;
+               }
+       } else {
+               msleep(1000);
        }
 
        return true;
@@ -408,7 +418,9 @@ selected_server:
        if (error < 0)
                goto failed_set_error;
 
-       fc->cbi = afs_get_cb_interest(vnode->cb_interest);
+       fc->cbi = afs_get_cb_interest(
+               rcu_dereference_protected(vnode->cb_interest,
+                                         lockdep_is_held(&vnode->io_lock)));
 
        read_lock(&server->fs_lock);
        alist = rcu_dereference_protected(server->addresses,
@@ -459,6 +471,8 @@ no_more_servers:
                                     s->probe.abort_code);
        }
 
+       error = e.error;
+
 failed_set_error:
        fc->error = error;
 failed:
@@ -476,12 +490,15 @@ failed:
 bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
 {
        struct afs_vnode *vnode = fc->vnode;
-       struct afs_cb_interest *cbi = vnode->cb_interest;
+       struct afs_cb_interest *cbi;
        struct afs_addr_list *alist;
        int error = fc->ac.error;
 
        _enter("");
 
+       cbi = rcu_dereference_protected(vnode->cb_interest,
+                                       lockdep_is_held(&vnode->io_lock));
+
        switch (error) {
        case SHRT_MAX:
                if (!cbi) {
@@ -490,7 +507,7 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
                        return false;
                }
 
-               fc->cbi = afs_get_cb_interest(vnode->cb_interest);
+               fc->cbi = afs_get_cb_interest(cbi);
 
                read_lock(&cbi->server->fs_lock);
                alist = rcu_dereference_protected(cbi->server->addresses,
index a34a89c..4fa5ce9 100644 (file)
@@ -188,7 +188,7 @@ void afs_put_call(struct afs_call *call)
                if (call->type->destructor)
                        call->type->destructor(call);
 
-               afs_put_server(call->net, call->cm_server);
+               afs_put_server(call->net, call->server);
                afs_put_cb_interest(call->net, call->cbi);
                afs_put_addrlist(call->alist);
                kfree(call->request);
@@ -417,6 +417,7 @@ void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp)
                                          afs_wake_up_async_call :
                                          afs_wake_up_call_waiter),
                                         call->upgrade,
+                                        call->intr,
                                         call->debug_id);
        if (IS_ERR(rxcall)) {
                ret = PTR_ERR(rxcall);
@@ -426,6 +427,10 @@ void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp)
 
        call->rxcall = rxcall;
 
+       if (call->max_lifespan)
+               rxrpc_kernel_set_max_life(call->net->socket, rxcall,
+                                         call->max_lifespan);
+
        /* send the request */
        iov[0].iov_base = call->request;
        iov[0].iov_len  = call->request_size;
@@ -529,11 +534,11 @@ static void afs_deliver_to_call(struct afs_call *call)
                        return;
                }
 
-               if (call->want_reply_time &&
+               if (!call->have_reply_time &&
                    rxrpc_kernel_get_reply_time(call->net->socket,
                                                call->rxcall,
                                                &call->reply_time))
-                       call->want_reply_time = false;
+                       call->have_reply_time = true;
 
                ret = call->type->deliver(call);
                state = READ_ONCE(call->state);
@@ -648,7 +653,7 @@ long afs_wait_for_call_to_complete(struct afs_call *call,
                        break;
                }
 
-               if (timeout == 0 &&
+               if (call->intr && timeout == 0 &&
                    life == last_life && signal_pending(current)) {
                        if (stalled)
                                break;
@@ -691,10 +696,9 @@ long afs_wait_for_call_to_complete(struct afs_call *call,
        ret = ac->error;
        switch (ret) {
        case 0:
-               if (call->ret_reply0) {
-                       ret = (long)call->reply[0];
-                       call->reply[0] = NULL;
-               }
+               ret = call->ret0;
+               call->ret0 = 0;
+
                /* Fall through */
        case -ECONNABORTED:
                ac->responded = true;
index 5f58a9a..5d8ece9 100644 (file)
@@ -87,11 +87,9 @@ void afs_clear_permits(struct afs_vnode *vnode)
        permits = rcu_dereference_protected(vnode->permit_cache,
                                            lockdep_is_held(&vnode->lock));
        RCU_INIT_POINTER(vnode->permit_cache, NULL);
-       vnode->cb_break++;
        spin_unlock(&vnode->lock);
 
-       if (permits)
-               afs_put_permits(permits);
+       afs_put_permits(permits);
 }
 
 /*
@@ -118,10 +116,10 @@ static void afs_hash_permits(struct afs_permits *permits)
  * as the ACL *may* have changed.
  */
 void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
-                     unsigned int cb_break)
+                     unsigned int cb_break, struct afs_status_cb *scb)
 {
        struct afs_permits *permits, *xpermits, *replacement, *zap, *new = NULL;
-       afs_access_t caller_access = READ_ONCE(vnode->status.caller_access);
+       afs_access_t caller_access = scb->status.caller_access;
        size_t size = 0;
        bool changed = false;
        int i, j;
@@ -148,7 +146,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
                                }
 
                                if (afs_cb_is_broken(cb_break, vnode,
-                                                    vnode->cb_interest)) {
+                                                    rcu_dereference(vnode->cb_interest))) {
                                        changed = true;
                                        break;
                                }
@@ -178,7 +176,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
                }
        }
 
-       if (afs_cb_is_broken(cb_break, vnode, vnode->cb_interest))
+       if (afs_cb_is_broken(cb_break, vnode, rcu_dereference(vnode->cb_interest)))
                goto someone_else_changed_it;
 
        /* We need a ref on any permits list we want to copy as we'll have to
@@ -255,14 +253,16 @@ found:
 
        kfree(new);
 
+       rcu_read_lock();
        spin_lock(&vnode->lock);
        zap = rcu_access_pointer(vnode->permit_cache);
-       if (!afs_cb_is_broken(cb_break, vnode, vnode->cb_interest) &&
+       if (!afs_cb_is_broken(cb_break, vnode, rcu_dereference(vnode->cb_interest)) &&
            zap == permits)
                rcu_assign_pointer(vnode->permit_cache, replacement);
        else
                zap = replacement;
        spin_unlock(&vnode->lock);
+       rcu_read_unlock();
        afs_put_permits(zap);
 out_put:
        afs_put_permits(permits);
@@ -322,13 +322,12 @@ int afs_check_permit(struct afs_vnode *vnode, struct key *key,
                 */
                _debug("no valid permit");
 
-               ret = afs_fetch_status(vnode, key, false);
+               ret = afs_fetch_status(vnode, key, false, _access);
                if (ret < 0) {
                        *_access = 0;
                        _leave(" = %d", ret);
                        return ret;
                }
-               *_access = vnode->status.caller_access;
        }
 
        _leave(" = 0 [access %x]", *_access);
index 65b33b6..52c170b 100644 (file)
@@ -521,8 +521,15 @@ static noinline bool afs_update_server_record(struct afs_fs_cursor *fc, struct a
        alist = afs_vl_lookup_addrs(fc->vnode->volume->cell, fc->key,
                                    &server->uuid);
        if (IS_ERR(alist)) {
-               fc->ac.error = PTR_ERR(alist);
-               _leave(" = f [%d]", fc->ac.error);
+               if ((PTR_ERR(alist) == -ERESTARTSYS ||
+                    PTR_ERR(alist) == -EINTR) &&
+                   !(fc->flags & AFS_FS_CURSOR_INTR) &&
+                   server->addresses) {
+                       _leave(" = t [intr]");
+                       return true;
+               }
+               fc->error = PTR_ERR(alist);
+               _leave(" = f [%d]", fc->error);
                return false;
        }
 
@@ -574,7 +581,11 @@ retry:
        ret = wait_on_bit(&server->flags, AFS_SERVER_FL_UPDATING,
                          TASK_INTERRUPTIBLE);
        if (ret == -ERESTARTSYS) {
-               fc->ac.error = ret;
+               if (!(fc->flags & AFS_FS_CURSOR_INTR) && server->addresses) {
+                       _leave(" = t [intr]");
+                       return true;
+               }
+               fc->error = ret;
                _leave(" = f [intr]");
                return false;
        }
index 783c68c..f18911e 100644 (file)
@@ -426,7 +426,7 @@ static int afs_set_super(struct super_block *sb, struct fs_context *fc)
 static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
 {
        struct afs_super_info *as = AFS_FS_S(sb);
-       struct afs_fid fid;
+       struct afs_iget_data iget_data;
        struct inode *inode = NULL;
        int ret;
 
@@ -451,11 +451,13 @@ static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
        } else {
                sprintf(sb->s_id, "%llu", as->volume->vid);
                afs_activate_volume(as->volume);
-               fid.vid         = as->volume->vid;
-               fid.vnode       = 1;
-               fid.vnode_hi    = 0;
-               fid.unique      = 1;
-               inode = afs_iget(sb, ctx->key, &fid, NULL, NULL, NULL, NULL);
+               iget_data.fid.vid       = as->volume->vid;
+               iget_data.fid.vnode     = 1;
+               iget_data.fid.vnode_hi  = 0;
+               iget_data.fid.unique    = 1;
+               iget_data.cb_v_break    = as->volume->cb_v_break;
+               iget_data.cb_s_break    = 0;
+               inode = afs_iget(sb, ctx->key, &iget_data, NULL, NULL, NULL);
        }
 
        if (IS_ERR(inode))
@@ -677,13 +679,12 @@ static struct inode *afs_alloc_inode(struct super_block *sb)
        vnode->volume           = NULL;
        vnode->lock_key         = NULL;
        vnode->permit_cache     = NULL;
-       vnode->cb_interest      = NULL;
+       RCU_INIT_POINTER(vnode->cb_interest, NULL);
 #ifdef CONFIG_AFS_FSCACHE
        vnode->cache            = NULL;
 #endif
 
        vnode->flags            = 1 << AFS_VNODE_UNSET;
-       vnode->cb_type          = 0;
        vnode->lock_state       = AFS_VNODE_LOCK_NONE;
 
        init_rwsem(&vnode->rmdir_lock);
@@ -708,7 +709,7 @@ static void afs_destroy_inode(struct inode *inode)
 
        _debug("DESTROY INODE %p", inode);
 
-       ASSERTCMP(vnode->cb_interest, ==, NULL);
+       ASSERTCMP(rcu_access_pointer(vnode->cb_interest), ==, NULL);
 
        atomic_dec(&afs_count_active_inodes);
 }
@@ -741,7 +742,7 @@ static int afs_statfs(struct dentry *dentry, struct kstatfs *buf)
                return PTR_ERR(key);
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
                fc.flags |= AFS_FS_CURSOR_NO_VSLEEP;
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
@@ -749,7 +750,6 @@ static int afs_statfs(struct dentry *dentry, struct kstatfs *buf)
                }
 
                afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, vnode, fc.cb_break);
                ret = afs_end_vnode_operation(&fc);
        }
 
index b4f1a84..61e2501 100644 (file)
@@ -232,18 +232,16 @@ struct afs_vlserver_list *afs_extract_vlserver_list(struct afs_cell *cell,
                if (bs.status > NR__dns_lookup_status)
                        bs.status = NR__dns_lookup_status;
 
+               /* See if we can update an old server record */
                server = NULL;
-               if (previous) {
-                       /* See if we can update an old server record */
-                       for (i = 0; i < previous->nr_servers; i++) {
-                               struct afs_vlserver *p = previous->servers[i].server;
-
-                               if (p->name_len == bs.name_len &&
-                                   p->port == bs.port &&
-                                   strncasecmp(b, p->name, bs.name_len) == 0) {
-                                       server = afs_get_vlserver(p);
-                                       break;
-                               }
+               for (i = 0; i < previous->nr_servers; i++) {
+                       struct afs_vlserver *p = previous->servers[i].server;
+
+                       if (p->name_len == bs.name_len &&
+                           p->port == bs.port &&
+                           strncasecmp(b, p->name, bs.name_len) == 0) {
+                               server = afs_get_vlserver(p);
+                               break;
                        }
                }
 
index b05e0de..beb9915 100644 (file)
@@ -33,8 +33,8 @@ static bool afs_vl_probe_done(struct afs_vlserver *server)
 void afs_vlserver_probe_result(struct afs_call *call)
 {
        struct afs_addr_list *alist = call->alist;
-       struct afs_vlserver *server = call->reply[0];
-       unsigned int server_index = (long)call->reply[1];
+       struct afs_vlserver *server = call->vlserver;
+       unsigned int server_index = call->server_index;
        unsigned int index = call->addr_ix;
        unsigned int rtt = UINT_MAX;
        bool have_result = false;
index 7adde83..3f84548 100644 (file)
@@ -43,11 +43,29 @@ bool afs_begin_vlserver_operation(struct afs_vl_cursor *vc, struct afs_cell *cel
 static bool afs_start_vl_iteration(struct afs_vl_cursor *vc)
 {
        struct afs_cell *cell = vc->cell;
+       unsigned int dns_lookup_count;
+
+       if (cell->dns_source == DNS_RECORD_UNAVAILABLE ||
+           cell->dns_expiry <= ktime_get_real_seconds()) {
+               dns_lookup_count = smp_load_acquire(&cell->dns_lookup_count);
+               set_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags);
+               queue_work(afs_wq, &cell->manager);
+
+               if (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
+                       if (wait_var_event_interruptible(
+                                   &cell->dns_lookup_count,
+                                   smp_load_acquire(&cell->dns_lookup_count)
+                                   != dns_lookup_count) < 0) {
+                               vc->error = -ERESTARTSYS;
+                               return false;
+                       }
+               }
 
-       if (wait_on_bit(&cell->flags, AFS_CELL_FL_NO_LOOKUP_YET,
-                       TASK_INTERRUPTIBLE)) {
-               vc->error = -ERESTARTSYS;
-               return false;
+               /* Status load is ordered after lookup counter load */
+               if (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
+                       vc->error = -EDESTADDRREQ;
+                       return false;
+               }
        }
 
        read_lock(&cell->vl_servers_lock);
@@ -55,7 +73,7 @@ static bool afs_start_vl_iteration(struct afs_vl_cursor *vc)
                rcu_dereference_protected(cell->vl_servers,
                                          lockdep_is_held(&cell->vl_servers_lock)));
        read_unlock(&cell->vl_servers_lock);
-       if (!vc->server_list || !vc->server_list->nr_servers)
+       if (!vc->server_list->nr_servers)
                return false;
 
        vc->untried = (1UL << vc->server_list->nr_servers) - 1;
index dd9ba4e..3d4b983 100644 (file)
@@ -34,7 +34,7 @@ static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call)
 
        /* unmarshall the reply once we've received all of it */
        uvldb = call->buffer;
-       entry = call->reply[0];
+       entry = call->ret_vldb;
 
        nr_servers = ntohl(uvldb->nServers);
        if (nr_servers > AFS_NMAXNSERVERS)
@@ -110,7 +110,7 @@ static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call)
 
 static void afs_destroy_vl_get_entry_by_name_u(struct afs_call *call)
 {
-       kfree(call->reply[0]);
+       kfree(call->ret_vldb);
        afs_flat_call_destructor(call);
 }
 
@@ -155,8 +155,8 @@ struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_vl_cursor *vc,
        }
 
        call->key = vc->key;
-       call->reply[0] = entry;
-       call->ret_reply0 = true;
+       call->ret_vldb = entry;
+       call->max_lifespan = AFS_VL_MAX_LIFESPAN;
 
        /* Marshall the parameters */
        bp = call->request;
@@ -214,7 +214,7 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *call)
                if (!alist)
                        return -ENOMEM;
                alist->version = uniquifier;
-               call->reply[0] = alist;
+               call->ret_alist = alist;
                call->count = count;
                call->count2 = nentries;
                call->unmarshall++;
@@ -229,7 +229,7 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *call)
                if (ret < 0)
                        return ret;
 
-               alist = call->reply[0];
+               alist = call->ret_alist;
                bp = call->buffer;
                count = min(call->count, 4U);
                for (i = 0; i < count; i++)
@@ -249,8 +249,7 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *call)
 
 static void afs_vl_get_addrs_u_destructor(struct afs_call *call)
 {
-       afs_put_server(call->net, (struct afs_server *)call->reply[0]);
-       kfree(call->reply[1]);
+       afs_put_addrlist(call->ret_alist);
        return afs_flat_call_destructor(call);
 }
 
@@ -287,8 +286,8 @@ struct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_cursor *vc,
                return ERR_PTR(-ENOMEM);
 
        call->key = vc->key;
-       call->reply[0] = NULL;
-       call->ret_reply0 = true;
+       call->ret_alist = NULL;
+       call->max_lifespan = AFS_VL_MAX_LIFESPAN;
 
        /* Marshall the parameters */
        bp = call->request;
@@ -358,9 +357,7 @@ static int afs_deliver_vl_get_capabilities(struct afs_call *call)
 
 static void afs_destroy_vl_get_capabilities(struct afs_call *call)
 {
-       struct afs_vlserver *server = call->reply[0];
-
-       afs_put_vlserver(call->net, server);
+       afs_put_vlserver(call->net, call->vlserver);
        afs_flat_call_destructor(call);
 }
 
@@ -398,11 +395,11 @@ struct afs_call *afs_vl_get_capabilities(struct afs_net *net,
                return ERR_PTR(-ENOMEM);
 
        call->key = key;
-       call->reply[0] = afs_get_vlserver(server);
-       call->reply[1] = (void *)(long)server_index;
+       call->vlserver = afs_get_vlserver(server);
+       call->server_index = server_index;
        call->upgrade = true;
-       call->want_reply_time = true;
        call->async = true;
+       call->max_lifespan = AFS_PROBE_MAX_LIFESPAN;
 
        /* marshall the parameters */
        bp = call->request;
@@ -460,7 +457,7 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
                if (!alist)
                        return -ENOMEM;
                alist->version = uniquifier;
-               call->reply[0] = alist;
+               call->ret_alist = alist;
 
                if (call->count == 0)
                        goto extract_volendpoints;
@@ -488,7 +485,7 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
                if (ret < 0)
                        return ret;
 
-               alist = call->reply[0];
+               alist = call->ret_alist;
                bp = call->buffer;
                switch (call->count2) {
                case YFS_ENDPOINT_IPV4:
@@ -609,7 +606,6 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
                break;
        }
 
-       alist = call->reply[0];
        _leave(" = 0 [done]");
        return 0;
 }
@@ -644,8 +640,8 @@ struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *vc,
                return ERR_PTR(-ENOMEM);
 
        call->key = vc->key;
-       call->reply[0] = NULL;
-       call->ret_reply0 = true;
+       call->ret_alist = NULL;
+       call->max_lifespan = AFS_VL_MAX_LIFESPAN;
 
        /* Marshall the parameters */
        bp = call->request;
index 0122d74..8bcab95 100644 (file)
@@ -313,6 +313,46 @@ static void afs_redirty_pages(struct writeback_control *wbc,
        _leave("");
 }
 
+/*
+ * completion of write to server
+ */
+static void afs_pages_written_back(struct afs_vnode *vnode,
+                                  pgoff_t first, pgoff_t last)
+{
+       struct pagevec pv;
+       unsigned long priv;
+       unsigned count, loop;
+
+       _enter("{%llx:%llu},{%lx-%lx}",
+              vnode->fid.vid, vnode->fid.vnode, first, last);
+
+       pagevec_init(&pv);
+
+       do {
+               _debug("done %lx-%lx", first, last);
+
+               count = last - first + 1;
+               if (count > PAGEVEC_SIZE)
+                       count = PAGEVEC_SIZE;
+               pv.nr = find_get_pages_contig(vnode->vfs_inode.i_mapping,
+                                             first, count, pv.pages);
+               ASSERTCMP(pv.nr, ==, count);
+
+               for (loop = 0; loop < count; loop++) {
+                       priv = page_private(pv.pages[loop]);
+                       trace_afs_page_dirty(vnode, tracepoint_string("clear"),
+                                            pv.pages[loop]->index, priv);
+                       set_page_private(pv.pages[loop], 0);
+                       end_page_writeback(pv.pages[loop]);
+               }
+               first += count;
+               __pagevec_release(&pv);
+       } while (first <= last);
+
+       afs_prune_wb_keys(vnode);
+       _leave("");
+}
+
 /*
  * write to a file
  */
@@ -322,6 +362,7 @@ static int afs_store_data(struct address_space *mapping,
 {
        struct afs_vnode *vnode = AFS_FS_I(mapping->host);
        struct afs_fs_cursor fc;
+       struct afs_status_cb *scb;
        struct afs_wb_key *wbk = NULL;
        struct list_head *p;
        int ret = -ENOKEY, ret2;
@@ -333,6 +374,10 @@ static int afs_store_data(struct address_space *mapping,
               vnode->fid.unique,
               first, last, offset, to);
 
+       scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
+       if (!scb)
+               return -ENOMEM;
+
        spin_lock(&vnode->wb_lock);
        p = vnode->wb_keys.next;
 
@@ -351,6 +396,7 @@ try_next_key:
 
        spin_unlock(&vnode->wb_lock);
        afs_put_wb_key(wbk);
+       kfree(scb);
        _leave(" = %d [no keys]", ret);
        return ret;
 
@@ -361,14 +407,19 @@ found_key:
        _debug("USE WB KEY %u", key_serial(wbk->key));
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, wbk->key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, wbk->key, false)) {
+               afs_dataversion_t data_version = vnode->status.data_version + 1;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
-                       afs_fs_store_data(&fc, mapping, first, last, offset, to);
+                       afs_fs_store_data(&fc, mapping, first, last, offset, to, scb);
                }
 
-               afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, vnode, fc.cb_break);
+               afs_check_for_remote_deletion(&fc, vnode);
+               afs_vnode_commit_status(&fc, vnode, fc.cb_break,
+                                       &data_version, scb);
+               if (fc.ac.error == 0)
+                       afs_pages_written_back(vnode, first, last);
                ret = afs_end_vnode_operation(&fc);
        }
 
@@ -393,6 +444,7 @@ found_key:
        }
 
        afs_put_wb_key(wbk);
+       kfree(scb);
        _leave(" = %d", ret);
        return ret;
 }
@@ -678,46 +730,6 @@ int afs_writepages(struct address_space *mapping,
        return ret;
 }
 
-/*
- * completion of write to server
- */
-void afs_pages_written_back(struct afs_vnode *vnode, struct afs_call *call)
-{
-       struct pagevec pv;
-       unsigned long priv;
-       unsigned count, loop;
-       pgoff_t first = call->first, last = call->last;
-
-       _enter("{%llx:%llu},{%lx-%lx}",
-              vnode->fid.vid, vnode->fid.vnode, first, last);
-
-       pagevec_init(&pv);
-
-       do {
-               _debug("done %lx-%lx", first, last);
-
-               count = last - first + 1;
-               if (count > PAGEVEC_SIZE)
-                       count = PAGEVEC_SIZE;
-               pv.nr = find_get_pages_contig(vnode->vfs_inode.i_mapping,
-                                             first, count, pv.pages);
-               ASSERTCMP(pv.nr, ==, count);
-
-               for (loop = 0; loop < count; loop++) {
-                       priv = page_private(pv.pages[loop]);
-                       trace_afs_page_dirty(vnode, tracepoint_string("clear"),
-                                            pv.pages[loop]->index, priv);
-                       set_page_private(pv.pages[loop], 0);
-                       end_page_writeback(pv.pages[loop]);
-               }
-               first += count;
-               __pagevec_release(&pv);
-       } while (first <= last);
-
-       afs_prune_wb_keys(vnode);
-       _leave("");
-}
-
 /*
  * write to an AFS file
  */
index c81f850..17f58fe 100644 (file)
@@ -47,40 +47,52 @@ static int afs_xattr_get_acl(const struct xattr_handler *handler,
                             void *buffer, size_t size)
 {
        struct afs_fs_cursor fc;
+       struct afs_status_cb *scb;
        struct afs_vnode *vnode = AFS_FS_I(inode);
        struct afs_acl *acl = NULL;
        struct key *key;
-       int ret;
+       int ret = -ENOMEM;
+
+       scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
+       if (!scb)
+               goto error;
 
        key = afs_request_key(vnode->volume->cell);
-       if (IS_ERR(key))
-               return PTR_ERR(key);
+       if (IS_ERR(key)) {
+               ret = PTR_ERR(key);
+               goto error_scb;
+       }
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
+               afs_dataversion_t data_version = vnode->status.data_version;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
-                       acl = afs_fs_fetch_acl(&fc);
+                       acl = afs_fs_fetch_acl(&fc, scb);
                }
 
                afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, vnode, fc.cb_break);
+               afs_vnode_commit_status(&fc, vnode, fc.cb_break,
+                                       &data_version, scb);
                ret = afs_end_vnode_operation(&fc);
        }
 
        if (ret == 0) {
                ret = acl->size;
                if (size > 0) {
-                       ret = -ERANGE;
-                       if (acl->size > size)
-                               return -ERANGE;
-                       memcpy(buffer, acl->data, acl->size);
-                       ret = acl->size;
+                       if (acl->size <= size)
+                               memcpy(buffer, acl->data, acl->size);
+                       else
+                               ret = -ERANGE;
                }
                kfree(acl);
        }
 
        key_put(key);
+error_scb:
+       kfree(scb);
+error:
        return ret;
 }
 
@@ -93,41 +105,53 @@ static int afs_xattr_set_acl(const struct xattr_handler *handler,
                              const void *buffer, size_t size, int flags)
 {
        struct afs_fs_cursor fc;
+       struct afs_status_cb *scb;
        struct afs_vnode *vnode = AFS_FS_I(inode);
        struct afs_acl *acl = NULL;
        struct key *key;
-       int ret;
+       int ret = -ENOMEM;
 
        if (flags == XATTR_CREATE)
                return -EINVAL;
 
-       key = afs_request_key(vnode->volume->cell);
-       if (IS_ERR(key))
-               return PTR_ERR(key);
+       scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
+       if (!scb)
+               goto error;
 
        acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
-       if (!acl) {
-               key_put(key);
-               return -ENOMEM;
+       if (!acl)
+               goto error_scb;
+
+       key = afs_request_key(vnode->volume->cell);
+       if (IS_ERR(key)) {
+               ret = PTR_ERR(key);
+               goto error_acl;
        }
 
        acl->size = size;
        memcpy(acl->data, buffer, size);
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
+               afs_dataversion_t data_version = vnode->status.data_version;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
-                       afs_fs_store_acl(&fc, acl);
+                       afs_fs_store_acl(&fc, acl, scb);
                }
 
                afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, vnode, fc.cb_break);
+               afs_vnode_commit_status(&fc, vnode, fc.cb_break,
+                                       &data_version, scb);
                ret = afs_end_vnode_operation(&fc);
        }
 
-       kfree(acl);
        key_put(key);
+error_acl:
+       kfree(acl);
+error_scb:
+       kfree(scb);
+error:
        return ret;
 }
 
@@ -146,12 +170,12 @@ static int afs_xattr_get_yfs(const struct xattr_handler *handler,
                             void *buffer, size_t size)
 {
        struct afs_fs_cursor fc;
+       struct afs_status_cb *scb;
        struct afs_vnode *vnode = AFS_FS_I(inode);
        struct yfs_acl *yacl = NULL;
        struct key *key;
-       unsigned int flags = 0;
        char buf[16], *data;
-       int which = 0, dsize, ret;
+       int which = 0, dsize, ret = -ENOMEM;
 
        if (strcmp(name, "acl") == 0)
                which = 0;
@@ -164,65 +188,81 @@ static int afs_xattr_get_yfs(const struct xattr_handler *handler,
        else
                return -EOPNOTSUPP;
 
+       yacl = kzalloc(sizeof(struct yfs_acl), GFP_KERNEL);
+       if (!yacl)
+               goto error;
+
        if (which == 0)
-               flags |= YFS_ACL_WANT_ACL;
+               yacl->flags |= YFS_ACL_WANT_ACL;
        else if (which == 3)
-               flags |= YFS_ACL_WANT_VOL_ACL;
+               yacl->flags |= YFS_ACL_WANT_VOL_ACL;
+
+       scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
+       if (!scb)
+               goto error_yacl;
 
        key = afs_request_key(vnode->volume->cell);
-       if (IS_ERR(key))
-               return PTR_ERR(key);
+       if (IS_ERR(key)) {
+               ret = PTR_ERR(key);
+               goto error_scb;
+       }
 
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
+               afs_dataversion_t data_version = vnode->status.data_version;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
-                       yacl = yfs_fs_fetch_opaque_acl(&fc, flags);
+                       yfs_fs_fetch_opaque_acl(&fc, yacl, scb);
                }
 
                afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, vnode, fc.cb_break);
+               afs_vnode_commit_status(&fc, vnode, fc.cb_break,
+                                       &data_version, scb);
                ret = afs_end_vnode_operation(&fc);
        }
 
-       if (ret == 0) {
-               switch (which) {
-               case 0:
-                       data = yacl->acl->data;
-                       dsize = yacl->acl->size;
-                       break;
-               case 1:
-                       data = buf;
-                       dsize = snprintf(buf, sizeof(buf), "%u",
-                                        yacl->inherit_flag);
-                       break;
-               case 2:
-                       data = buf;
-                       dsize = snprintf(buf, sizeof(buf), "%u",
-                                        yacl->num_cleaned);
-                       break;
-               case 3:
-                       data = yacl->vol_acl->data;
-                       dsize = yacl->vol_acl->size;
-                       break;
-               default:
-                       ret = -EOPNOTSUPP;
-                       goto out;
-               }
+       if (ret < 0)
+               goto error_key;
+
+       switch (which) {
+       case 0:
+               data = yacl->acl->data;
+               dsize = yacl->acl->size;
+               break;
+       case 1:
+               data = buf;
+               dsize = snprintf(buf, sizeof(buf), "%u", yacl->inherit_flag);
+               break;
+       case 2:
+               data = buf;
+               dsize = snprintf(buf, sizeof(buf), "%u", yacl->num_cleaned);
+               break;
+       case 3:
+               data = yacl->vol_acl->data;
+               dsize = yacl->vol_acl->size;
+               break;
+       default:
+               ret = -EOPNOTSUPP;
+               goto error_key;
+       }
 
-               ret = dsize;
-               if (size > 0) {
-                       if (dsize > size) {
-                               ret = -ERANGE;
-                               goto out;
-                       }
-                       memcpy(buffer, data, dsize);
+       ret = dsize;
+       if (size > 0) {
+               if (dsize > size) {
+                       ret = -ERANGE;
+                       goto error_key;
                }
+               memcpy(buffer, data, dsize);
        }
 
-out:
-       yfs_free_opaque_acl(yacl);
+error_key:
        key_put(key);
+error_scb:
+       kfree(scb);
+error_yacl:
+       yfs_free_opaque_acl(yacl);
+error:
        return ret;
 }
 
@@ -235,42 +275,54 @@ static int afs_xattr_set_yfs(const struct xattr_handler *handler,
                              const void *buffer, size_t size, int flags)
 {
        struct afs_fs_cursor fc;
+       struct afs_status_cb *scb;
        struct afs_vnode *vnode = AFS_FS_I(inode);
        struct afs_acl *acl = NULL;
        struct key *key;
-       int ret;
+       int ret = -ENOMEM;
 
        if (flags == XATTR_CREATE ||
            strcmp(name, "acl") != 0)
                return -EINVAL;
 
-       key = afs_request_key(vnode->volume->cell);
-       if (IS_ERR(key))
-               return PTR_ERR(key);
+       scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
+       if (!scb)
+               goto error;
 
        acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
-       if (!acl) {
-               key_put(key);
-               return -ENOMEM;
-       }
+       if (!acl)
+               goto error_scb;
 
        acl->size = size;
        memcpy(acl->data, buffer, size);
 
+       key = afs_request_key(vnode->volume->cell);
+       if (IS_ERR(key)) {
+               ret = PTR_ERR(key);
+               goto error_acl;
+       }
+
        ret = -ERESTARTSYS;
-       if (afs_begin_vnode_operation(&fc, vnode, key)) {
+       if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
+               afs_dataversion_t data_version = vnode->status.data_version;
+
                while (afs_select_fileserver(&fc)) {
                        fc.cb_break = afs_calc_vnode_cb_break(vnode);
-                       yfs_fs_store_opaque_acl2(&fc, acl);
+                       yfs_fs_store_opaque_acl2(&fc, acl, scb);
                }
 
                afs_check_for_remote_deletion(&fc, fc.vnode);
-               afs_vnode_commit_status(&fc, vnode, fc.cb_break);
+               afs_vnode_commit_status(&fc, vnode, fc.cb_break,
+                                       &data_version, scb);
                ret = afs_end_vnode_operation(&fc);
        }
 
+error_acl:
        kfree(acl);
        key_put(key);
+error_scb:
+       kfree(scb);
+error:
        return ret;
 }
 
index 6cf7d16..10de675 100644 (file)
@@ -183,24 +183,19 @@ static void xdr_dump_bad(const __be32 *bp)
 /*
  * Decode a YFSFetchStatus block
  */
-static int xdr_decode_YFSFetchStatus(struct afs_call *call,
-                                    const __be32 **_bp,
-                                    struct afs_file_status *status,
-                                    struct afs_vnode *vnode,
-                                    const afs_dataversion_t *expected_version,
-                                    struct afs_read *read_req)
+static int xdr_decode_YFSFetchStatus(const __be32 **_bp,
+                                    struct afs_call *call,
+                                    struct afs_status_cb *scb)
 {
        const struct yfs_xdr_YFSFetchStatus *xdr = (const void *)*_bp;
+       struct afs_file_status *status = &scb->status;
        u32 type;
-       u8 flags = 0;
 
        status->abort_code = ntohl(xdr->abort_code);
        if (status->abort_code != 0) {
-               if (vnode && status->abort_code == VNOVNODE) {
-                       set_bit(AFS_VNODE_DELETED, &vnode->flags);
+               if (status->abort_code == VNOVNODE)
                        status->nlink = 0;
-                       __afs_break_callback(vnode);
-               }
+               scb->have_error = true;
                return 0;
        }
 
@@ -209,77 +204,28 @@ static int xdr_decode_YFSFetchStatus(struct afs_call *call,
        case AFS_FTYPE_FILE:
        case AFS_FTYPE_DIR:
        case AFS_FTYPE_SYMLINK:
-               if (type != status->type &&
-                   vnode &&
-                   !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
-                       pr_warning("Vnode %llx:%llx:%x changed type %u to %u\n",
-                                  vnode->fid.vid,
-                                  vnode->fid.vnode,
-                                  vnode->fid.unique,
-                                  status->type, type);
-                       goto bad;
-               }
                status->type = type;
                break;
        default:
                goto bad;
        }
 
-#define EXTRACT_M4(FIELD)                                      \
-       do {                                                    \
-               u32 x = ntohl(xdr->FIELD);                      \
-               if (status->FIELD != x) {                       \
-                       flags |= AFS_VNODE_META_CHANGED;        \
-                       status->FIELD = x;                      \
-               }                                               \
-       } while (0)
-
-#define EXTRACT_M8(FIELD)                                      \
-       do {                                                    \
-               u64 x = xdr_to_u64(xdr->FIELD);                 \
-               if (status->FIELD != x) {                       \
-                       flags |= AFS_VNODE_META_CHANGED;        \
-                       status->FIELD = x;                      \
-               }                                               \
-       } while (0)
-
-#define EXTRACT_D8(FIELD)                                      \
-       do {                                                    \
-               u64 x = xdr_to_u64(xdr->FIELD);                 \
-               if (status->FIELD != x) {                       \
-                       flags |= AFS_VNODE_DATA_CHANGED;        \
-                       status->FIELD = x;                      \
-               }                                               \
-       } while (0)
-
-       EXTRACT_M4(nlink);
-       EXTRACT_D8(size);
-       EXTRACT_D8(data_version);
-       EXTRACT_M8(author);
-       EXTRACT_M8(owner);
-       EXTRACT_M8(group);
-       EXTRACT_M4(mode);
-       EXTRACT_M4(caller_access); /* call ticket dependent */
-       EXTRACT_M4(anon_access);
-
-       status->mtime_client = xdr_to_time(xdr->mtime_client);
-       status->mtime_server = xdr_to_time(xdr->mtime_server);
-       status->lock_count   = ntohl(xdr->lock_count);
-
-       if (read_req) {
-               read_req->data_version = status->data_version;
-               read_req->file_size = status->size;
-       }
+       status->nlink           = ntohl(xdr->nlink);
+       status->author          = xdr_to_u64(xdr->author);
+       status->owner           = xdr_to_u64(xdr->owner);
+       status->caller_access   = ntohl(xdr->caller_access); /* Ticket dependent */
+       status->anon_access     = ntohl(xdr->anon_access);
+       status->mode            = ntohl(xdr->mode) & S_IALLUGO;
+       status->group           = xdr_to_u64(xdr->group);
+       status->lock_count      = ntohl(xdr->lock_count);
+
+       status->mtime_client    = xdr_to_time(xdr->mtime_client);
+       status->mtime_server    = xdr_to_time(xdr->mtime_server);
+       status->size            = xdr_to_u64(xdr->size);
+       status->data_version    = xdr_to_u64(xdr->data_version);
+       scb->have_status        = true;
 
        *_bp += xdr_size(xdr);
-
-       if (vnode) {
-               if (test_bit(AFS_VNODE_UNSET, &vnode->flags))
-                       flags |= AFS_VNODE_NOT_YET_SET;
-               afs_update_inode_from_status(vnode, status, expected_version,
-                                            flags);
-       }
-
        return 0;
 
 bad:
@@ -287,74 +233,21 @@ bad:
        return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
 }
 
-/*
- * Decode the file status.  We need to lock the target vnode if we're going to
- * update its status so that stat() sees the attributes update atomically.
- */
-static int yfs_decode_status(struct afs_call *call,
-                            const __be32 **_bp,
-                            struct afs_file_status *status,
-                            struct afs_vnode *vnode,
-                            const afs_dataversion_t *expected_version,
-                            struct afs_read *read_req)
-{
-       int ret;
-
-       if (!vnode)
-               return xdr_decode_YFSFetchStatus(call, _bp, status, vnode,
-                                                expected_version, read_req);
-
-       write_seqlock(&vnode->cb_lock);
-       ret = xdr_decode_YFSFetchStatus(call, _bp, status, vnode,
-                                       expected_version, read_req);
-       write_sequnlock(&vnode->cb_lock);
-       return ret;
-}
-
 /*
  * Decode a YFSCallBack block
  */
-static void xdr_decode_YFSCallBack(struct afs_call *call,
-                                  struct afs_vnode *vnode,
-                                  const __be32 **_bp)
-{
-       struct yfs_xdr_YFSCallBack *xdr = (void *)*_bp;
-       struct afs_cb_interest *old, *cbi = call->cbi;
-       u64 cb_expiry;
-
-       write_seqlock(&vnode->cb_lock);
-
-       if (!afs_cb_is_broken(call->cb_break, vnode, cbi)) {
-               cb_expiry = xdr_to_u64(xdr->expiration_time);
-               do_div(cb_expiry, 10 * 1000 * 1000);
-               vnode->cb_version       = ntohl(xdr->version);
-               vnode->cb_type          = ntohl(xdr->type);
-               vnode->cb_expires_at    = cb_expiry + ktime_get_real_seconds();
-               old = vnode->cb_interest;
-               if (old != call->cbi) {
-                       vnode->cb_interest = cbi;
-                       cbi = old;
-               }
-               set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
-       }
-
-       write_sequnlock(&vnode->cb_lock);
-       call->cbi = cbi;
-       *_bp += xdr_size(xdr);
-}
-
-static void xdr_decode_YFSCallBack_raw(const __be32 **_bp,
-                                      struct afs_callback *cb)
+static void xdr_decode_YFSCallBack(const __be32 **_bp,
+                                  struct afs_call *call,
+                                  struct afs_status_cb *scb)
 {
        struct yfs_xdr_YFSCallBack *x = (void *)*_bp;
-       u64 cb_expiry;
-
-       cb_expiry = xdr_to_u64(x->expiration_time);
-       do_div(cb_expiry, 10 * 1000 * 1000);
-       cb->version     = ntohl(x->version);
-       cb->type        = ntohl(x->type);
-       cb->expires_at  = cb_expiry + ktime_get_real_seconds();
+       struct afs_callback *cb = &scb->callback;
+       ktime_t cb_expiry;
 
+       cb_expiry = call->reply_time;
+       cb_expiry = ktime_add(cb_expiry, xdr_to_u64(x->expiration_time) * 100);
+       cb->expires_at  = ktime_divns(cb_expiry, NSEC_PER_SEC);
+       scb->have_cb    = true;
        *_bp += xdr_size(x);
 }
 
@@ -442,11 +335,10 @@ static void xdr_decode_YFSFetchVolumeStatus(const __be32 **_bp,
 }
 
 /*
- * deliver reply data to an FS.FetchStatus
+ * Deliver a reply that's a status, callback and volsync.
  */
-static int yfs_deliver_fs_fetch_status_vnode(struct afs_call *call)
+static int yfs_deliver_fs_status_cb_and_volsync(struct afs_call *call)
 {
-       struct afs_vnode *vnode = call->reply[0];
        const __be32 *bp;
        int ret;
 
@@ -454,16 +346,36 @@ static int yfs_deliver_fs_fetch_status_vnode(struct afs_call *call)
        if (ret < 0)
                return ret;
 
-       _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
-
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
        if (ret < 0)
                return ret;
-       xdr_decode_YFSCallBack(call, vnode, &bp);
-       xdr_decode_YFSVolSync(&bp, call->reply[1]);
+       xdr_decode_YFSCallBack(&bp, call, call->out_scb);
+       xdr_decode_YFSVolSync(&bp, call->out_volsync);
+
+       _leave(" = 0 [done]");
+       return 0;
+}
+
+/*
+ * Deliver reply data to operations that just return a file status and a volume
+ * sync record.
+ */
+static int yfs_deliver_status_and_volsync(struct afs_call *call)
+{
+       const __be32 *bp;
+       int ret;
+
+       ret = afs_transfer_reply(call);
+       if (ret < 0)
+               return ret;
+
+       bp = call->buffer;
+       ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
+       if (ret < 0)
+               return ret;
+       xdr_decode_YFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
        return 0;
@@ -475,15 +387,15 @@ static int yfs_deliver_fs_fetch_status_vnode(struct afs_call *call)
 static const struct afs_call_type yfs_RXYFSFetchStatus_vnode = {
        .name           = "YFS.FetchStatus(vnode)",
        .op             = yfs_FS_FetchStatus,
-       .deliver        = yfs_deliver_fs_fetch_status_vnode,
+       .deliver        = yfs_deliver_fs_status_cb_and_volsync,
        .destructor     = afs_flat_call_destructor,
 };
 
 /*
  * Fetch the status information for a file.
  */
-int yfs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync,
-                            bool new_inode)
+int yfs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_status_cb *scb,
+                            struct afs_volsync *volsync)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -505,9 +417,8 @@ int yfs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy
        }
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->reply[1] = volsync;
-       call->expected_version = new_inode ? 1 : vnode->status.data_version;
+       call->out_scb = scb;
+       call->out_volsync = volsync;
 
        /* marshall the parameters */
        bp = call->request;
@@ -516,9 +427,9 @@ int yfs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy
        bp = xdr_encode_YFSFid(bp, &vnode->fid);
        yfs_check_req(call, bp);
 
-       call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -528,8 +439,7 @@ int yfs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy
  */
 static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
 {
-       struct afs_vnode *vnode = call->reply[0];
-       struct afs_read *req = call->reply[2];
+       struct afs_read *req = call->read_request;
        const __be32 *bp;
        unsigned int size;
        int ret;
@@ -586,7 +496,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
                if (req->offset == PAGE_SIZE) {
                        req->offset = 0;
                        if (req->page_done)
-                               req->page_done(call, req);
+                               req->page_done(req);
                        req->index++;
                        if (req->remain > 0)
                                goto begin_page;
@@ -623,12 +533,14 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
                        return ret;
 
                bp = call->buffer;
-               ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
-                                       &vnode->status.data_version, req);
+               ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
                if (ret < 0)
                        return ret;
-               xdr_decode_YFSCallBack(call, vnode, &bp);
-               xdr_decode_YFSVolSync(&bp, call->reply[1]);
+               xdr_decode_YFSCallBack(&bp, call, call->out_scb);
+               xdr_decode_YFSVolSync(&bp, call->out_volsync);
+
+               req->data_version = call->out_scb->status.data_version;
+               req->file_size = call->out_scb->status.size;
 
                call->unmarshall++;
 
@@ -642,7 +554,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
                        zero_user_segment(req->pages[req->index],
                                          req->offset, PAGE_SIZE);
                if (req->page_done)
-                       req->page_done(call, req);
+                       req->page_done(req);
                req->offset = 0;
        }
 
@@ -652,9 +564,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
 
 static void yfs_fetch_data_destructor(struct afs_call *call)
 {
-       struct afs_read *req = call->reply[2];
-
-       afs_put_read(req);
+       afs_put_read(call->read_request);
        afs_flat_call_destructor(call);
 }
 
@@ -671,7 +581,8 @@ static const struct afs_call_type yfs_RXYFSFetchData64 = {
 /*
  * Fetch data from a file.
  */
-int yfs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
+int yfs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_status_cb *scb,
+                     struct afs_read *req)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -693,11 +604,9 @@ int yfs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->reply[1] = NULL; /* volsync */
-       call->reply[2] = req;
-       call->expected_version = vnode->status.data_version;
-       call->want_reply_time = true;
+       call->out_scb = scb;
+       call->out_volsync = NULL;
+       call->read_request = req;
 
        /* marshall the parameters */
        bp = call->request;
@@ -709,9 +618,9 @@ int yfs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
        yfs_check_req(call, bp);
 
        refcount_inc(&req->usage);
-       call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -721,7 +630,6 @@ int yfs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
  */
 static int yfs_deliver_fs_create_vnode(struct afs_call *call)
 {
-       struct afs_vnode *vnode = call->reply[0];
        const __be32 *bp;
        int ret;
 
@@ -733,16 +641,15 @@ static int yfs_deliver_fs_create_vnode(struct afs_call *call)
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       xdr_decode_YFSFid(&bp, call->reply[1]);
-       ret = yfs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
+       xdr_decode_YFSFid(&bp, call->out_fid);
+       ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
        if (ret < 0)
                return ret;
-       ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
        if (ret < 0)
                return ret;
-       xdr_decode_YFSCallBack_raw(&bp, call->reply[3]);
-       xdr_decode_YFSVolSync(&bp, NULL);
+       xdr_decode_YFSCallBack(&bp, call, call->out_scb);
+       xdr_decode_YFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
        return 0;
@@ -764,14 +671,13 @@ static const struct afs_call_type afs_RXFSCreateFile = {
 int yfs_fs_create_file(struct afs_fs_cursor *fc,
                       const char *name,
                       umode_t mode,
-                      u64 current_data_version,
+                      struct afs_status_cb *dvnode_scb,
                       struct afs_fid *newfid,
-                      struct afs_file_status *newstatus,
-                      struct afs_callback *newcb)
+                      struct afs_status_cb *new_scb)
 {
-       struct afs_vnode *vnode = fc->vnode;
+       struct afs_vnode *dvnode = fc->vnode;
        struct afs_call *call;
-       struct afs_net *net = afs_v2net(vnode);
+       struct afs_net *net = afs_v2net(dvnode);
        size_t namesz, reqsz, rplsz;
        __be32 *bp;
 
@@ -795,24 +701,23 @@ int yfs_fs_create_file(struct afs_fs_cursor *fc,
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->reply[1] = newfid;
-       call->reply[2] = newstatus;
-       call->reply[3] = newcb;
-       call->expected_version = current_data_version + 1;
+       call->out_dir_scb = dvnode_scb;
+       call->out_fid = newfid;
+       call->out_scb = new_scb;
 
        /* marshall the parameters */
        bp = call->request;
        bp = xdr_encode_u32(bp, YFSCREATEFILE);
        bp = xdr_encode_u32(bp, 0); /* RPC flags */
-       bp = xdr_encode_YFSFid(bp, &vnode->fid);
+       bp = xdr_encode_YFSFid(bp, &dvnode->fid);
        bp = xdr_encode_string(bp, name, namesz);
        bp = xdr_encode_YFSStoreStatus_mode(bp, mode);
        bp = xdr_encode_u32(bp, yfs_LockNone); /* ViceLockType */
        yfs_check_req(call, bp);
 
        afs_use_fs_server(call, fc->cbi);
-       trace_afs_make_fs_call1(call, &vnode->fid, name);
+       trace_afs_make_fs_call1(call, &dvnode->fid, name);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -830,14 +735,13 @@ static const struct afs_call_type yfs_RXFSMakeDir = {
 int yfs_fs_make_dir(struct afs_fs_cursor *fc,
                    const char *name,
                    umode_t mode,
-                   u64 current_data_version,
+                   struct afs_status_cb *dvnode_scb,
                    struct afs_fid *newfid,
-                   struct afs_file_status *newstatus,
-                   struct afs_callback *newcb)
+                   struct afs_status_cb *new_scb)
 {
-       struct afs_vnode *vnode = fc->vnode;
+       struct afs_vnode *dvnode = fc->vnode;
        struct afs_call *call;
-       struct afs_net *net = afs_v2net(vnode);
+       struct afs_net *net = afs_v2net(dvnode);
        size_t namesz, reqsz, rplsz;
        __be32 *bp;
 
@@ -860,23 +764,22 @@ int yfs_fs_make_dir(struct afs_fs_cursor *fc,
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->reply[1] = newfid;
-       call->reply[2] = newstatus;
-       call->reply[3] = newcb;
-       call->expected_version = current_data_version + 1;
+       call->out_dir_scb = dvnode_scb;
+       call->out_fid = newfid;
+       call->out_scb = new_scb;
 
        /* marshall the parameters */
        bp = call->request;
        bp = xdr_encode_u32(bp, YFSMAKEDIR);
        bp = xdr_encode_u32(bp, 0); /* RPC flags */
-       bp = xdr_encode_YFSFid(bp, &vnode->fid);
+       bp = xdr_encode_YFSFid(bp, &dvnode->fid);
        bp = xdr_encode_string(bp, name, namesz);
        bp = xdr_encode_YFSStoreStatus_mode(bp, mode);
        yfs_check_req(call, bp);
 
        afs_use_fs_server(call, fc->cbi);
-       trace_afs_make_fs_call1(call, &vnode->fid, name);
+       trace_afs_make_fs_call1(call, &dvnode->fid, name);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -886,8 +789,6 @@ int yfs_fs_make_dir(struct afs_fs_cursor *fc,
  */
 static int yfs_deliver_fs_remove_file2(struct afs_call *call)
 {
-       struct afs_vnode *dvnode = call->reply[0];
-       struct afs_vnode *vnode = call->reply[1];
        struct afs_fid fid;
        const __be32 *bp;
        int ret;
@@ -898,20 +799,18 @@ static int yfs_deliver_fs_remove_file2(struct afs_call *call)
        if (ret < 0)
                return ret;
 
-       /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       ret = yfs_decode_status(call, &bp, &dvnode->status, dvnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
        if (ret < 0)
                return ret;
 
        xdr_decode_YFSFid(&bp, &fid);
-       ret = yfs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL);
+       ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
        if (ret < 0)
                return ret;
        /* Was deleted if vnode->status.abort_code == VNOVNODE. */
 
-       xdr_decode_YFSVolSync(&bp, NULL);
+       xdr_decode_YFSVolSync(&bp, call->out_volsync);
        return 0;
 }
 
@@ -929,7 +828,8 @@ static const struct afs_call_type yfs_RXYFSRemoveFile2 = {
  * Remove a file and retrieve new file status.
  */
 int yfs_fs_remove_file2(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
-                       const char *name, u64 current_data_version)
+                       const char *name, struct afs_status_cb *dvnode_scb,
+                       struct afs_status_cb *vnode_scb)
 {
        struct afs_vnode *dvnode = fc->vnode;
        struct afs_call *call;
@@ -954,9 +854,8 @@ int yfs_fs_remove_file2(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = dvnode;
-       call->reply[1] = vnode;
-       call->expected_version = current_data_version + 1;
+       call->out_dir_scb = dvnode_scb;
+       call->out_scb = vnode_scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -968,6 +867,7 @@ int yfs_fs_remove_file2(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call1(call, &dvnode->fid, name);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -977,7 +877,6 @@ int yfs_fs_remove_file2(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
  */
 static int yfs_deliver_fs_remove(struct afs_call *call)
 {
-       struct afs_vnode *dvnode = call->reply[0];
        const __be32 *bp;
        int ret;
 
@@ -987,14 +886,12 @@ static int yfs_deliver_fs_remove(struct afs_call *call)
        if (ret < 0)
                return ret;
 
-       /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       ret = yfs_decode_status(call, &bp, &dvnode->status, dvnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
        if (ret < 0)
                return ret;
 
-       xdr_decode_YFSVolSync(&bp, NULL);
+       xdr_decode_YFSVolSync(&bp, call->out_volsync);
        return 0;
 }
 
@@ -1019,7 +916,8 @@ static const struct afs_call_type yfs_RXYFSRemoveDir = {
  * remove a file or directory
  */
 int yfs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
-                 const char *name, bool isdir, u64 current_data_version)
+                 const char *name, bool isdir,
+                 struct afs_status_cb *dvnode_scb)
 {
        struct afs_vnode *dvnode = fc->vnode;
        struct afs_call *call;
@@ -1042,9 +940,7 @@ int yfs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = dvnode;
-       call->reply[1] = vnode;
-       call->expected_version = current_data_version + 1;
+       call->out_dir_scb = dvnode_scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1056,6 +952,7 @@ int yfs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call1(call, &dvnode->fid, name);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1065,7 +962,6 @@ int yfs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
  */
 static int yfs_deliver_fs_link(struct afs_call *call)
 {
-       struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1];
        const __be32 *bp;
        int ret;
 
@@ -1075,16 +971,14 @@ static int yfs_deliver_fs_link(struct afs_call *call)
        if (ret < 0)
                return ret;
 
-       /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       ret = yfs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL);
+       ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
        if (ret < 0)
                return ret;
-       ret = yfs_decode_status(call, &bp, &dvnode->status, dvnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
        if (ret < 0)
                return ret;
-       xdr_decode_YFSVolSync(&bp, NULL);
+       xdr_decode_YFSVolSync(&bp, call->out_volsync);
        _leave(" = 0 [done]");
        return 0;
 }
@@ -1103,7 +997,9 @@ static const struct afs_call_type yfs_RXYFSLink = {
  * Make a hard link.
  */
 int yfs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
-               const char *name, u64 current_data_version)
+               const char *name,
+               struct afs_status_cb *dvnode_scb,
+               struct afs_status_cb *vnode_scb)
 {
        struct afs_vnode *dvnode = fc->vnode;
        struct afs_call *call;
@@ -1127,9 +1023,8 @@ int yfs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = dvnode;
-       call->reply[1] = vnode;
-       call->expected_version = current_data_version + 1;
+       call->out_dir_scb = dvnode_scb;
+       call->out_scb = vnode_scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1142,6 +1037,7 @@ int yfs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call1(call, &vnode->fid, name);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1151,7 +1047,6 @@ int yfs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
  */
 static int yfs_deliver_fs_symlink(struct afs_call *call)
 {
-       struct afs_vnode *vnode = call->reply[0];
        const __be32 *bp;
        int ret;
 
@@ -1163,15 +1058,14 @@ static int yfs_deliver_fs_symlink(struct afs_call *call)
 
        /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       xdr_decode_YFSFid(&bp, call->reply[1]);
-       ret = yfs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL);
+       xdr_decode_YFSFid(&bp, call->out_fid);
+       ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
        if (ret < 0)
                return ret;
-       ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
        if (ret < 0)
                return ret;
-       xdr_decode_YFSVolSync(&bp, NULL);
+       xdr_decode_YFSVolSync(&bp, call->out_volsync);
 
        _leave(" = 0 [done]");
        return 0;
@@ -1193,9 +1087,9 @@ static const struct afs_call_type yfs_RXYFSSymlink = {
 int yfs_fs_symlink(struct afs_fs_cursor *fc,
                   const char *name,
                   const char *contents,
-                  u64 current_data_version,
+                  struct afs_status_cb *dvnode_scb,
                   struct afs_fid *newfid,
-                  struct afs_file_status *newstatus)
+                  struct afs_status_cb *vnode_scb)
 {
        struct afs_vnode *dvnode = fc->vnode;
        struct afs_call *call;
@@ -1222,10 +1116,9 @@ int yfs_fs_symlink(struct afs_fs_cursor *fc,
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = dvnode;
-       call->reply[1] = newfid;
-       call->reply[2] = newstatus;
-       call->expected_version = current_data_version + 1;
+       call->out_dir_scb = dvnode_scb;
+       call->out_fid = newfid;
+       call->out_scb = vnode_scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1239,6 +1132,7 @@ int yfs_fs_symlink(struct afs_fs_cursor *fc,
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call1(call, &dvnode->fid, name);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1248,8 +1142,6 @@ int yfs_fs_symlink(struct afs_fs_cursor *fc,
  */
 static int yfs_deliver_fs_rename(struct afs_call *call)
 {
-       struct afs_vnode *orig_dvnode = call->reply[0];
-       struct afs_vnode *new_dvnode = call->reply[1];
        const __be32 *bp;
        int ret;
 
@@ -1259,20 +1151,17 @@ static int yfs_deliver_fs_rename(struct afs_call *call)
        if (ret < 0)
                return ret;
 
-       /* unmarshall the reply once we've received all of it */
        bp = call->buffer;
-       ret = yfs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode,
-                               &call->expected_version, NULL);
+       ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
        if (ret < 0)
                return ret;
-       if (new_dvnode != orig_dvnode) {
-               ret = yfs_decode_status(call, &bp, &new_dvnode->status, new_dvnode,
-                                       &call->expected_version_2, NULL);
+       if (call->out_dir_scb != call->out_scb) {
+               ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
                if (ret < 0)
                        return ret;
        }
 
-       xdr_decode_YFSVolSync(&bp, NULL);
+       xdr_decode_YFSVolSync(&bp, call->out_volsync);
        _leave(" = 0 [done]");
        return 0;
 }
@@ -1294,8 +1183,8 @@ int yfs_fs_rename(struct afs_fs_cursor *fc,
                  const char *orig_name,
                  struct afs_vnode *new_dvnode,
                  const char *new_name,
-                 u64 current_orig_data_version,
-                 u64 current_new_data_version)
+                 struct afs_status_cb *orig_dvnode_scb,
+                 struct afs_status_cb *new_dvnode_scb)
 {
        struct afs_vnode *orig_dvnode = fc->vnode;
        struct afs_call *call;
@@ -1321,10 +1210,8 @@ int yfs_fs_rename(struct afs_fs_cursor *fc,
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = orig_dvnode;
-       call->reply[1] = new_dvnode;
-       call->expected_version = current_orig_data_version + 1;
-       call->expected_version_2 = current_new_data_version + 1;
+       call->out_dir_scb = orig_dvnode_scb;
+       call->out_scb = new_dvnode_scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1338,46 +1225,18 @@ int yfs_fs_rename(struct afs_fs_cursor *fc,
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call2(call, &orig_dvnode->fid, orig_name, new_name);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
-/*
- * Deliver reply data to a YFS.StoreData64 operation.
- */
-static int yfs_deliver_fs_store_data(struct afs_call *call)
-{
-       struct afs_vnode *vnode = call->reply[0];
-       const __be32 *bp;
-       int ret;
-
-       _enter("");
-
-       ret = afs_transfer_reply(call);
-       if (ret < 0)
-               return ret;
-
-       /* unmarshall the reply once we've received all of it */
-       bp = call->buffer;
-       ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
-                               &call->expected_version, NULL);
-       if (ret < 0)
-               return ret;
-       xdr_decode_YFSVolSync(&bp, NULL);
-
-       afs_pages_written_back(vnode, call);
-
-       _leave(" = 0 [done]");
-       return 0;
-}
-
 /*
  * YFS.StoreData64 operation type.
  */
 static const struct afs_call_type yfs_RXYFSStoreData64 = {
        .name           = "YFS.StoreData64",
        .op             = yfs_FS_StoreData64,
-       .deliver        = yfs_deliver_fs_store_data,
+       .deliver        = yfs_deliver_status_and_volsync,
        .destructor     = afs_flat_call_destructor,
 };
 
@@ -1386,7 +1245,8 @@ static const struct afs_call_type yfs_RXYFSStoreData64 = {
  */
 int yfs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
                      pgoff_t first, pgoff_t last,
-                     unsigned offset, unsigned to)
+                     unsigned offset, unsigned to,
+                     struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1424,13 +1284,12 @@ int yfs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
 
        call->key = fc->key;
        call->mapping = mapping;
-       call->reply[0] = vnode;
        call->first = first;
        call->last = last;
        call->first_offset = offset;
        call->last_to = to;
        call->send_pages = true;
-       call->expected_version = vnode->status.data_version + 1;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1445,51 +1304,25 @@ int yfs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
-/*
- * deliver reply data to an FS.StoreStatus
- */
-static int yfs_deliver_fs_store_status(struct afs_call *call)
-{
-       struct afs_vnode *vnode = call->reply[0];
-       const __be32 *bp;
-       int ret;
-
-       _enter("");
-
-       ret = afs_transfer_reply(call);
-       if (ret < 0)
-               return ret;
-
-       /* unmarshall the reply once we've received all of it */
-       bp = call->buffer;
-       ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
-                               &call->expected_version, NULL);
-       if (ret < 0)
-               return ret;
-       xdr_decode_YFSVolSync(&bp, NULL);
-
-       _leave(" = 0 [done]");
-       return 0;
-}
-
 /*
  * YFS.StoreStatus operation type
  */
 static const struct afs_call_type yfs_RXYFSStoreStatus = {
        .name           = "YFS.StoreStatus",
        .op             = yfs_FS_StoreStatus,
-       .deliver        = yfs_deliver_fs_store_status,
+       .deliver        = yfs_deliver_status_and_volsync,
        .destructor     = afs_flat_call_destructor,
 };
 
 static const struct afs_call_type yfs_RXYFSStoreData64_as_Status = {
        .name           = "YFS.StoreData64",
        .op             = yfs_FS_StoreData64,
-       .deliver        = yfs_deliver_fs_store_status,
+       .deliver        = yfs_deliver_status_and_volsync,
        .destructor     = afs_flat_call_destructor,
 };
 
@@ -1497,7 +1330,8 @@ static const struct afs_call_type yfs_RXYFSStoreData64_as_Status = {
  * Set the attributes on a file, using YFS.StoreData64 rather than
  * YFS.StoreStatus so as to alter the file size also.
  */
-static int yfs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
+static int yfs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr,
+                              struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1518,8 +1352,7 @@ static int yfs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->expected_version = vnode->status.data_version + 1;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1534,6 +1367,7 @@ static int yfs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1542,7 +1376,8 @@ static int yfs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
  * Set the attributes on a file, using YFS.StoreData64 if there's a change in
  * file size, and YFS.StoreStatus otherwise.
  */
-int yfs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
+int yfs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr,
+                  struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1550,7 +1385,7 @@ int yfs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
        __be32 *bp;
 
        if (attr->ia_valid & ATTR_SIZE)
-               return yfs_fs_setattr_size(fc, attr);
+               return yfs_fs_setattr_size(fc, attr, scb);
 
        _enter(",%x,{%llx:%llu},,",
               key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
@@ -1565,8 +1400,7 @@ int yfs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->expected_version = vnode->status.data_version;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1578,6 +1412,7 @@ int yfs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1607,7 +1442,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
                        return ret;
 
                bp = call->buffer;
-               xdr_decode_YFSFetchVolumeStatus(&bp, call->reply[1]);
+               xdr_decode_YFSFetchVolumeStatus(&bp, call->out_volstatus);
                call->unmarshall++;
                afs_extract_to_tmp(call);
 
@@ -1623,7 +1458,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
                        return afs_protocol_error(call, -EBADMSG,
                                                  afs_eproto_volname_len);
                size = (call->count + 3) & ~3; /* It's padded */
-               afs_extract_begin(call, call->reply[2], size);
+               afs_extract_to_buf(call, size);
                call->unmarshall++;
 
                /* Fall through - and extract the volume name */
@@ -1633,7 +1468,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
                if (ret < 0)
                        return ret;
 
-               p = call->reply[2];
+               p = call->buffer;
                p[call->count] = 0;
                _debug("volname '%s'", p);
                afs_extract_to_tmp(call);
@@ -1651,7 +1486,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
                        return afs_protocol_error(call, -EBADMSG,
                                                  afs_eproto_offline_msg_len);
                size = (call->count + 3) & ~3; /* It's padded */
-               afs_extract_begin(call, call->reply[2], size);
+               afs_extract_to_buf(call, size);
                call->unmarshall++;
 
                /* Fall through - and extract the offline message */
@@ -1661,7 +1496,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
                if (ret < 0)
                        return ret;
 
-               p = call->reply[2];
+               p = call->buffer;
                p[call->count] = 0;
                _debug("offline '%s'", p);
 
@@ -1680,7 +1515,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
                        return afs_protocol_error(call, -EBADMSG,
                                                  afs_eproto_motd_len);
                size = (call->count + 3) & ~3; /* It's padded */
-               afs_extract_begin(call, call->reply[2], size);
+               afs_extract_to_buf(call, size);
                call->unmarshall++;
 
                /* Fall through - and extract the message of the day */
@@ -1690,7 +1525,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
                if (ret < 0)
                        return ret;
 
-               p = call->reply[2];
+               p = call->buffer;
                p[call->count] = 0;
                _debug("motd '%s'", p);
 
@@ -1705,16 +1540,6 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
        return 0;
 }
 
-/*
- * Destroy a YFS.GetVolumeStatus call.
- */
-static void yfs_get_volume_status_call_destructor(struct afs_call *call)
-{
-       kfree(call->reply[2]);
-       call->reply[2] = NULL;
-       afs_flat_call_destructor(call);
-}
-
 /*
  * YFS.GetVolumeStatus operation type
  */
@@ -1722,7 +1547,7 @@ static const struct afs_call_type yfs_RXYFSGetVolumeStatus = {
        .name           = "YFS.GetVolumeStatus",
        .op             = yfs_FS_GetVolumeStatus,
        .deliver        = yfs_deliver_fs_get_volume_status,
-       .destructor     = yfs_get_volume_status_call_destructor,
+       .destructor     = afs_flat_call_destructor,
 };
 
 /*
@@ -1735,28 +1560,21 @@ int yfs_fs_get_volume_status(struct afs_fs_cursor *fc,
        struct afs_call *call;
        struct afs_net *net = afs_v2net(vnode);
        __be32 *bp;
-       void *tmpbuf;
 
        _enter("");
 
-       tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
-       if (!tmpbuf)
-               return -ENOMEM;
-
        call = afs_alloc_flat_call(net, &yfs_RXYFSGetVolumeStatus,
                                   sizeof(__be32) * 2 +
                                   sizeof(struct yfs_xdr_u64),
-                                  sizeof(struct yfs_xdr_YFSFetchVolumeStatus) +
-                                  sizeof(__be32));
-       if (!call) {
-               kfree(tmpbuf);
+                                  max_t(size_t,
+                                        sizeof(struct yfs_xdr_YFSFetchVolumeStatus) +
+                                        sizeof(__be32),
+                                        AFSOPAQUEMAX + 1));
+       if (!call)
                return -ENOMEM;
-       }
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->reply[1] = vs;
-       call->reply[2] = tmpbuf;
+       call->out_volstatus = vs;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1767,38 +1585,11 @@ int yfs_fs_get_volume_status(struct afs_fs_cursor *fc,
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
-/*
- * Deliver reply data to operations that just return a file status and a volume
- * sync record.
- */
-static int yfs_deliver_status_and_volsync(struct afs_call *call)
-{
-       struct afs_vnode *vnode = call->reply[0];
-       const __be32 *bp;
-       int ret;
-
-       _enter("{%u}", call->unmarshall);
-
-       ret = afs_transfer_reply(call);
-       if (ret < 0)
-               return ret;
-
-       /* unmarshall the reply once we've received all of it */
-       bp = call->buffer;
-       ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
-                               &call->expected_version, NULL);
-       if (ret < 0)
-               return ret;
-       xdr_decode_YFSVolSync(&bp, NULL);
-
-       _leave(" = 0 [done]");
-       return 0;
-}
-
 /*
  * YFS.SetLock operation type
  */
@@ -1834,7 +1625,8 @@ static const struct afs_call_type yfs_RXYFSReleaseLock = {
 /*
  * Set a lock on a file
  */
-int yfs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
+int yfs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type,
+                   struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1853,8 +1645,8 @@ int yfs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->want_reply_time = true;
+       call->lvnode = vnode;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1866,6 +1658,7 @@ int yfs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_calli(call, &vnode->fid, type);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1873,7 +1666,7 @@ int yfs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
 /*
  * extend a lock on a file
  */
-int yfs_fs_extend_lock(struct afs_fs_cursor *fc)
+int yfs_fs_extend_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1891,8 +1684,8 @@ int yfs_fs_extend_lock(struct afs_fs_cursor *fc)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->want_reply_time = true;
+       call->lvnode = vnode;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1903,6 +1696,7 @@ int yfs_fs_extend_lock(struct afs_fs_cursor *fc)
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -1910,7 +1704,7 @@ int yfs_fs_extend_lock(struct afs_fs_cursor *fc)
 /*
  * release a lock on a file
  */
-int yfs_fs_release_lock(struct afs_fs_cursor *fc)
+int yfs_fs_release_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -1928,7 +1722,8 @@ int yfs_fs_release_lock(struct afs_fs_cursor *fc)
                return -ENOMEM;
 
        call->key = fc->key;
-       call->reply[0] = vnode;
+       call->lvnode = vnode;
+       call->out_scb = scb;
 
        /* marshall the parameters */
        bp = call->request;
@@ -1939,48 +1734,18 @@ int yfs_fs_release_lock(struct afs_fs_cursor *fc)
 
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
 
-/*
- * Deliver reply data to an FS.FetchStatus with no vnode.
- */
-static int yfs_deliver_fs_fetch_status(struct afs_call *call)
-{
-       struct afs_file_status *status = call->reply[1];
-       struct afs_callback *callback = call->reply[2];
-       struct afs_volsync *volsync = call->reply[3];
-       struct afs_vnode *vnode = call->reply[0];
-       const __be32 *bp;
-       int ret;
-
-       ret = afs_transfer_reply(call);
-       if (ret < 0)
-               return ret;
-
-       _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
-
-       /* unmarshall the reply once we've received all of it */
-       bp = call->buffer;
-       ret = yfs_decode_status(call, &bp, status, vnode,
-                               &call->expected_version, NULL);
-       if (ret < 0)
-               return ret;
-       xdr_decode_YFSCallBack_raw(&bp, callback);
-       xdr_decode_YFSVolSync(&bp, volsync);
-
-       _leave(" = 0 [done]");
-       return 0;
-}
-
 /*
  * YFS.FetchStatus operation type
  */
 static const struct afs_call_type yfs_RXYFSFetchStatus = {
        .name           = "YFS.FetchStatus",
        .op             = yfs_FS_FetchStatus,
-       .deliver        = yfs_deliver_fs_fetch_status,
+       .deliver        = yfs_deliver_fs_status_cb_and_volsync,
        .destructor     = afs_flat_call_destructor,
 };
 
@@ -1990,8 +1755,7 @@ static const struct afs_call_type yfs_RXYFSFetchStatus = {
 int yfs_fs_fetch_status(struct afs_fs_cursor *fc,
                        struct afs_net *net,
                        struct afs_fid *fid,
-                       struct afs_file_status *status,
-                       struct afs_callback *callback,
+                       struct afs_status_cb *scb,
                        struct afs_volsync *volsync)
 {
        struct afs_call *call;
@@ -2012,11 +1776,8 @@ int yfs_fs_fetch_status(struct afs_fs_cursor *fc,
        }
 
        call->key = fc->key;
-       call->reply[0] = NULL; /* vnode for fid[0] */
-       call->reply[1] = status;
-       call->reply[2] = callback;
-       call->reply[3] = volsync;
-       call->expected_version = 1; /* vnode->status.data_version */
+       call->out_scb = scb;
+       call->out_volsync = volsync;
 
        /* marshall the parameters */
        bp = call->request;
@@ -2025,9 +1786,9 @@ int yfs_fs_fetch_status(struct afs_fs_cursor *fc,
        bp = xdr_encode_YFSFid(bp, fid);
        yfs_check_req(call, bp);
 
-       call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, fid);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -2037,9 +1798,7 @@ int yfs_fs_fetch_status(struct afs_fs_cursor *fc,
  */
 static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
 {
-       struct afs_file_status *statuses;
-       struct afs_callback *callbacks;
-       struct afs_vnode *vnode = call->reply[0];
+       struct afs_status_cb *scb;
        const __be32 *bp;
        u32 tmp;
        int ret;
@@ -2078,10 +1837,8 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
                        return ret;
 
                bp = call->buffer;
-               statuses = call->reply[1];
-               ret = yfs_decode_status(call, &bp, &statuses[call->count],
-                                       call->count == 0 ? vnode : NULL,
-                                       NULL, NULL);
+               scb = &call->out_scb[call->count];
+               ret = xdr_decode_YFSFetchStatus(&bp, call, scb);
                if (ret < 0)
                        return ret;
 
@@ -2120,13 +1877,8 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
 
                _debug("unmarshall CB array");
                bp = call->buffer;
-               callbacks = call->reply[2];
-               xdr_decode_YFSCallBack_raw(&bp, &callbacks[call->count]);
-               statuses = call->reply[1];
-               if (call->count == 0 && vnode && statuses[0].abort_code == 0) {
-                       bp = call->buffer;
-                       xdr_decode_YFSCallBack(call, vnode, &bp);
-               }
+               scb = &call->out_scb[call->count];
+               xdr_decode_YFSCallBack(&bp, call, scb);
                call->count++;
                if (call->count < call->count2)
                        goto more_cbs;
@@ -2141,7 +1893,7 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
                        return ret;
 
                bp = call->buffer;
-               xdr_decode_YFSVolSync(&bp, call->reply[3]);
+               xdr_decode_YFSVolSync(&bp, call->out_volsync);
 
                call->unmarshall++;
 
@@ -2170,8 +1922,7 @@ static const struct afs_call_type yfs_RXYFSInlineBulkStatus = {
 int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
                              struct afs_net *net,
                              struct afs_fid *fids,
-                             struct afs_file_status *statuses,
-                             struct afs_callback *callbacks,
+                             struct afs_status_cb *statuses,
                              unsigned int nr_fids,
                              struct afs_volsync *volsync)
 {
@@ -2194,10 +1945,8 @@ int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
        }
 
        call->key = fc->key;
-       call->reply[0] = NULL; /* vnode for fid[0] */
-       call->reply[1] = statuses;
-       call->reply[2] = callbacks;
-       call->reply[3] = volsync;
+       call->out_scb = statuses;
+       call->out_volsync = volsync;
        call->count2 = nr_fids;
 
        /* marshall the parameters */
@@ -2209,9 +1958,9 @@ int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
                bp = xdr_encode_YFSFid(bp, &fids[i]);
        yfs_check_req(call, bp);
 
-       call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &fids[0]);
+       afs_set_fc_call(call, fc);
        afs_make_call(&fc->ac, call, GFP_NOFS);
        return afs_wait_for_call_to_complete(call, &fc->ac);
 }
@@ -2221,9 +1970,7 @@ int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
  */
 static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
 {
-       struct afs_volsync *volsync = call->reply[2];
-       struct afs_vnode *vnode = call->reply[1];
-       struct yfs_acl *yacl =  call->reply[0];
+       struct yfs_acl *yacl = call->out_yacl;
        struct afs_acl *acl;
        const __be32 *bp;
        unsigned int size;
@@ -2308,11 +2055,10 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
                bp = call->buffer;
                yacl->inherit_flag = ntohl(*bp++);
                yacl->num_cleaned = ntohl(*bp++);
-               ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
-                                       &call->expected_version, NULL);
+               ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
                if (ret < 0)
                        return ret;
-               xdr_decode_YFSVolSync(&bp, volsync);
+               xdr_decode_YFSVolSync(&bp, call->out_volsync);
 
                call->unmarshall++;
 
@@ -2333,12 +2079,6 @@ void yfs_free_opaque_acl(struct yfs_acl *yacl)
        }
 }
 
-static void yfs_destroy_fs_fetch_opaque_acl(struct afs_call *call)
-{
-       yfs_free_opaque_acl(call->reply[0]);
-       afs_flat_call_destructor(call);
-}
-
 /*
  * YFS.FetchOpaqueACL operation type
  */
@@ -2346,18 +2086,18 @@ static const struct afs_call_type yfs_RXYFSFetchOpaqueACL = {
        .name           = "YFS.FetchOpaqueACL",
        .op             = yfs_FS_FetchOpaqueACL,
        .deliver        = yfs_deliver_fs_fetch_opaque_acl,
-       .destructor     = yfs_destroy_fs_fetch_opaque_acl,
+       .destructor     = afs_flat_call_destructor,
 };
 
 /*
  * Fetch the YFS advanced ACLs for a file.
  */
 struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc,
-                                       unsigned int flags)
+                                       struct yfs_acl *yacl,
+                                       struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
-       struct yfs_acl *yacl;
        struct afs_net *net = afs_v2net(vnode);
        __be32 *bp;
 
@@ -2370,19 +2110,15 @@ struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc,
                                   sizeof(__be32) * 2 +
                                   sizeof(struct yfs_xdr_YFSFetchStatus) +
                                   sizeof(struct yfs_xdr_YFSVolSync));
-       if (!call)
-               goto nomem;
-
-       yacl = kzalloc(sizeof(struct yfs_acl), GFP_KERNEL);
-       if (!yacl)
-               goto nomem_call;
+       if (!call) {
+               fc->ac.error = -ENOMEM;
+               return ERR_PTR(-ENOMEM);
+       }
 
-       yacl->flags = flags;
        call->key = fc->key;
-       call->reply[0] = yacl;
-       call->reply[1] = vnode;
-       call->reply[2] = NULL; /* volsync */
-       call->ret_reply0 = true;
+       call->out_yacl = yacl;
+       call->out_scb = scb;
+       call->out_volsync = NULL;
 
        /* marshall the parameters */
        bp = call->request;
@@ -2391,17 +2127,10 @@ struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc,
        bp = xdr_encode_YFSFid(bp, &vnode->fid);
        yfs_check_req(call, bp);
 
-       call->cb_break = fc->cb_break;
        afs_use_fs_server(call, fc->cbi);
        trace_afs_make_fs_call(call, &vnode->fid);
        afs_make_call(&fc->ac, call, GFP_KERNEL);
        return (struct yfs_acl *)afs_wait_for_call_to_complete(call, &fc->ac);
-
-nomem_call:
-       afs_put_call(call);
-nomem:
-       fc->ac.error = -ENOMEM;
-       return ERR_PTR(-ENOMEM);
 }
 
 /*
@@ -2417,7 +2146,8 @@ static const struct afs_call_type yfs_RXYFSStoreOpaqueACL2 = {
 /*
  * Fetch the YFS ACL for a file.
  */
-int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *fc, const struct afs_acl *acl)
+int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *fc, const struct afs_acl *acl,
+                            struct afs_status_cb *scb)
 {
        struct afs_vnode *vnode = fc->vnode;
        struct afs_call *call;
@@ -2441,8 +2171,8 @@ int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *fc, const struct afs_acl *acl
        }
 
        call->key = fc->key;
-       call->reply[0] = vnode;
-       call->reply[2] = NULL; /* volsync */
+       call->out_scb = scb;
+       call->out_volsync = NULL;
 
        /* marshall the parameters */
        bp = call->request;
index 7d09d12..fa9e99a 100644 (file)
@@ -524,6 +524,19 @@ static inline int arch_check_elf(struct elfhdr *ehdr, bool has_interp,
 
 #endif /* !CONFIG_ARCH_BINFMT_ELF_STATE */
 
+static inline int make_prot(u32 p_flags)
+{
+       int prot = 0;
+
+       if (p_flags & PF_R)
+               prot |= PROT_READ;
+       if (p_flags & PF_W)
+               prot |= PROT_WRITE;
+       if (p_flags & PF_X)
+               prot |= PROT_EXEC;
+       return prot;
+}
+
 /* This is much more generalized than the library routine read function,
    so we keep this separate.  Technically the library read function
    is only provided so that we can read a.out libraries that have
@@ -563,16 +576,10 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
        for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
                if (eppnt->p_type == PT_LOAD) {
                        int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
-                       int elf_prot = 0;
+                       int elf_prot = make_prot(eppnt->p_flags);
                        unsigned long vaddr = 0;
                        unsigned long k, map_addr;
 
-                       if (eppnt->p_flags & PF_R)
-                               elf_prot = PROT_READ;
-                       if (eppnt->p_flags & PF_W)
-                               elf_prot |= PROT_WRITE;
-                       if (eppnt->p_flags & PF_X)
-                               elf_prot |= PROT_EXEC;
                        vaddr = eppnt->p_vaddr;
                        if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
                                elf_type |= MAP_FIXED_NOREPLACE;
@@ -687,7 +694,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
        struct file *interpreter = NULL; /* to shut gcc up */
        unsigned long load_addr = 0, load_bias = 0;
        int load_addr_set = 0;
-       char * elf_interpreter = NULL;
        unsigned long error;
        struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL;
        unsigned long elf_bss, elf_brk;
@@ -698,13 +704,12 @@ static int load_elf_binary(struct linux_binprm *bprm)
        unsigned long start_code, end_code, start_data, end_data;
        unsigned long reloc_func_desc __maybe_unused = 0;
        int executable_stack = EXSTACK_DEFAULT;
-       struct pt_regs *regs = current_pt_regs();
        struct {
                struct elfhdr elf_ex;
                struct elfhdr interp_elf_ex;
        } *loc;
        struct arch_elf_state arch_state = INIT_ARCH_ELF_STATE;
-       loff_t pos;
+       struct pt_regs *regs;
 
        loc = kmalloc(sizeof(*loc), GFP_KERNEL);
        if (!loc) {
@@ -734,69 +739,66 @@ static int load_elf_binary(struct linux_binprm *bprm)
                goto out;
 
        elf_ppnt = elf_phdata;
-       elf_bss = 0;
-       elf_brk = 0;
+       for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
+               char *elf_interpreter;
+               loff_t pos;
 
-       start_code = ~0UL;
-       end_code = 0;
-       start_data = 0;
-       end_data = 0;
+               if (elf_ppnt->p_type != PT_INTERP)
+                       continue;
 
-       for (i = 0; i < loc->elf_ex.e_phnum; i++) {
-               if (elf_ppnt->p_type == PT_INTERP) {
-                       /* This is the program interpreter used for
-                        * shared libraries - for now assume that this
-                        * is an a.out format binary
-                        */
-                       retval = -ENOEXEC;
-                       if (elf_ppnt->p_filesz > PATH_MAX || 
-                           elf_ppnt->p_filesz < 2)
-                               goto out_free_ph;
-
-                       retval = -ENOMEM;
-                       elf_interpreter = kmalloc(elf_ppnt->p_filesz,
-                                                 GFP_KERNEL);
-                       if (!elf_interpreter)
-                               goto out_free_ph;
-
-                       pos = elf_ppnt->p_offset;
-                       retval = kernel_read(bprm->file, elf_interpreter,
-                                            elf_ppnt->p_filesz, &pos);
-                       if (retval != elf_ppnt->p_filesz) {
-                               if (retval >= 0)
-                                       retval = -EIO;
-                               goto out_free_interp;
-                       }
-                       /* make sure path is NULL terminated */
-                       retval = -ENOEXEC;
-                       if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
-                               goto out_free_interp;
+               /*
+                * This is the program interpreter used for shared libraries -
+                * for now assume that this is an a.out format binary.
+                */
+               retval = -ENOEXEC;
+               if (elf_ppnt->p_filesz > PATH_MAX || elf_ppnt->p_filesz < 2)
+                       goto out_free_ph;
 
-                       interpreter = open_exec(elf_interpreter);
-                       retval = PTR_ERR(interpreter);
-                       if (IS_ERR(interpreter))
-                               goto out_free_interp;
+               retval = -ENOMEM;
+               elf_interpreter = kmalloc(elf_ppnt->p_filesz, GFP_KERNEL);
+               if (!elf_interpreter)
+                       goto out_free_ph;
 
-                       /*
-                        * If the binary is not readable then enforce
-                        * mm->dumpable = 0 regardless of the interpreter's
-                        * permissions.
-                        */
-                       would_dump(bprm, interpreter);
-
-                       /* Get the exec headers */
-                       pos = 0;
-                       retval = kernel_read(interpreter, &loc->interp_elf_ex,
-                                            sizeof(loc->interp_elf_ex), &pos);
-                       if (retval != sizeof(loc->interp_elf_ex)) {
-                               if (retval >= 0)
-                                       retval = -EIO;
-                               goto out_free_dentry;
-                       }
+               pos = elf_ppnt->p_offset;
+               retval = kernel_read(bprm->file, elf_interpreter,
+                                    elf_ppnt->p_filesz, &pos);
+               if (retval != elf_ppnt->p_filesz) {
+                       if (retval >= 0)
+                               retval = -EIO;
+                       goto out_free_interp;
+               }
+               /* make sure path is NULL terminated */
+               retval = -ENOEXEC;
+               if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
+                       goto out_free_interp;
 
-                       break;
+               interpreter = open_exec(elf_interpreter);
+               kfree(elf_interpreter);
+               retval = PTR_ERR(interpreter);
+               if (IS_ERR(interpreter))
+                       goto out_free_ph;
+
+               /*
+                * If the binary is not readable then enforce mm->dumpable = 0
+                * regardless of the interpreter's permissions.
+                */
+               would_dump(bprm, interpreter);
+
+               /* Get the exec headers */
+               pos = 0;
+               retval = kernel_read(interpreter, &loc->interp_elf_ex,
+                                    sizeof(loc->interp_elf_ex), &pos);
+               if (retval != sizeof(loc->interp_elf_ex)) {
+                       if (retval >= 0)
+                               retval = -EIO;
+                       goto out_free_dentry;
                }
-               elf_ppnt++;
+
+               break;
+
+out_free_interp:
+               kfree(elf_interpreter);
+               goto out_free_ph;
        }
 
        elf_ppnt = elf_phdata;
@@ -819,7 +821,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
                }
 
        /* Some simple consistency checks for the interpreter */
-       if (elf_interpreter) {
+       if (interpreter) {
                retval = -ELIBBAD;
                /* Not an ELF interpreter */
                if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
@@ -884,13 +886,19 @@ static int load_elf_binary(struct linux_binprm *bprm)
        if (retval < 0)
                goto out_free_dentry;
        
-       current->mm->start_stack = bprm->p;
+       elf_bss = 0;
+       elf_brk = 0;
+
+       start_code = ~0UL;
+       end_code = 0;
+       start_data = 0;
+       end_data = 0;
 
        /* Now we do a little grungy work by mmapping the ELF image into
           the correct location in memory. */
        for(i = 0, elf_ppnt = elf_phdata;
            i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
-               int elf_prot = 0, elf_flags, elf_fixed = MAP_FIXED_NOREPLACE;
+               int elf_prot, elf_flags, elf_fixed = MAP_FIXED_NOREPLACE;
                unsigned long k, vaddr;
                unsigned long total_size = 0;
 
@@ -931,12 +939,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
                        elf_fixed = MAP_FIXED;
                }
 
-               if (elf_ppnt->p_flags & PF_R)
-                       elf_prot |= PROT_READ;
-               if (elf_ppnt->p_flags & PF_W)
-                       elf_prot |= PROT_WRITE;
-               if (elf_ppnt->p_flags & PF_X)
-                       elf_prot |= PROT_EXEC;
+               elf_prot = make_prot(elf_ppnt->p_flags);
 
                elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE;
 
@@ -978,7 +981,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
                         * independently randomized mmap region (0 load_bias
                         * without MAP_FIXED).
                         */
-                       if (elf_interpreter) {
+                       if (interpreter) {
                                load_bias = ELF_ET_DYN_BASE;
                                if (current->flags & PF_RANDOMIZE)
                                        load_bias += arch_mmap_rnd();
@@ -1076,7 +1079,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
                goto out_free_dentry;
        }
 
-       if (elf_interpreter) {
+       if (interpreter) {
                unsigned long interp_map_addr = 0;
 
                elf_entry = load_elf_interp(&loc->interp_elf_ex,
@@ -1100,7 +1103,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
 
                allow_write_access(interpreter);
                fput(interpreter);
-               kfree(elf_interpreter);
        } else {
                elf_entry = loc->elf_ex.e_entry;
                if (BAD_ADDR(elf_entry)) {
@@ -1115,7 +1117,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
        set_binfmt(&elf_format);
 
 #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
-       retval = arch_setup_additional_pages(bprm, !!elf_interpreter);
+       retval = arch_setup_additional_pages(bprm, !!interpreter);
        if (retval < 0)
                goto out;
 #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
@@ -1132,6 +1134,17 @@ static int load_elf_binary(struct linux_binprm *bprm)
        current->mm->start_stack = bprm->p;
 
        if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) {
+               /*
+                * For architectures with ELF randomization, when executing
+                * a loader directly (i.e. no interpreter listed in ELF
+                * headers), move the brk area out of the mmap region
+                * (since it grows up, and may collide early with the stack
+                * growing down), and into the unused ELF_ET_DYN_BASE region.
+                */
+               if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) && !interpreter)
+                       current->mm->brk = current->mm->start_brk =
+                               ELF_ET_DYN_BASE;
+
                current->mm->brk = current->mm->start_brk =
                        arch_randomize_brk(current->mm);
 #ifdef compat_brk_randomized
@@ -1148,6 +1161,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
                                MAP_FIXED | MAP_PRIVATE, 0);
        }
 
+       regs = current_pt_regs();
 #ifdef ELF_PLAT_INIT
        /*
         * The ABI may specify that certain registers be set up in special
@@ -1176,8 +1190,6 @@ out_free_dentry:
        allow_write_access(interpreter);
        if (interpreter)
                fput(interpreter);
-out_free_interp:
-       kfree(elf_interpreter);
 out_free_ph:
        kfree(elf_phdata);
        goto out;
@@ -1456,8 +1468,6 @@ static void fill_elf_header(struct elfhdr *elf, int segs,
        elf->e_ehsize = sizeof(struct elfhdr);
        elf->e_phentsize = sizeof(struct elf_phdr);
        elf->e_phnum = segs;
-
-       return;
 }
 
 static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, loff_t offset)
@@ -1470,7 +1480,6 @@ static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, loff_t offset)
        phdr->p_memsz = 0;
        phdr->p_flags = 0;
        phdr->p_align = 0;
-       return;
 }
 
 static void fill_note(struct memelfnote *note, const char *name, int type, 
@@ -1480,7 +1489,6 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
        note->type = type;
        note->datasz = sz;
        note->data = data;
-       return;
 }
 
 /*
index f800450..0f7552a 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/namei.h>
 #include <linux/log2.h>
 #include <linux/cleancache.h>
-#include <linux/dax.h>
 #include <linux/task_io_accounting_ops.h>
 #include <linux/falloc.h>
 #include <linux/uaccess.h>
index 1645fcf..d27720c 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/namei.h>
 #include <linux/security.h>
 #include <linux/slab.h>
-#include <linux/xattr.h>
 #include "internal.h"
 
 #define CACHEFILES_KEYBUF_SIZE 512
index 36a8dc6..72f8e13 100644 (file)
@@ -892,8 +892,8 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch)
        int have = ci->i_snap_caps;
 
        if ((have & mask) == mask) {
-               dout("__ceph_caps_issued_mask %p snap issued %s"
-                    " (mask %s)\n", &ci->vfs_inode,
+               dout("__ceph_caps_issued_mask ino 0x%lx snap issued %s"
+                    " (mask %s)\n", ci->vfs_inode.i_ino,
                     ceph_cap_string(have),
                     ceph_cap_string(mask));
                return 1;
@@ -904,8 +904,8 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch)
                if (!__cap_is_valid(cap))
                        continue;
                if ((cap->issued & mask) == mask) {
-                       dout("__ceph_caps_issued_mask %p cap %p issued %s"
-                            " (mask %s)\n", &ci->vfs_inode, cap,
+                       dout("__ceph_caps_issued_mask ino 0x%lx cap %p issued %s"
+                            " (mask %s)\n", ci->vfs_inode.i_ino, cap,
                             ceph_cap_string(cap->issued),
                             ceph_cap_string(mask));
                        if (touch)
@@ -916,8 +916,8 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch)
                /* does a combination of caps satisfy mask? */
                have |= cap->issued;
                if ((have & mask) == mask) {
-                       dout("__ceph_caps_issued_mask %p combo issued %s"
-                            " (mask %s)\n", &ci->vfs_inode,
+                       dout("__ceph_caps_issued_mask ino 0x%lx combo issued %s"
+                            " (mask %s)\n", ci->vfs_inode.i_ino,
                             ceph_cap_string(cap->issued),
                             ceph_cap_string(mask));
                        if (touch) {
@@ -2257,8 +2257,6 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
        if (datasync)
                goto out;
 
-       inode_lock(inode);
-
        dirty = try_flush_caps(inode, &flush_tid);
        dout("fsync dirty caps are %s\n", ceph_cap_string(dirty));
 
@@ -2273,7 +2271,6 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
                ret = wait_event_interruptible(ci->i_cap_wq,
                                        caps_are_flushed(inode, flush_tid));
        }
-       inode_unlock(inode);
 out:
        dout("fsync %p%s result=%d\n", inode, datasync ? " datasync" : "", ret);
        return ret;
@@ -2528,9 +2525,14 @@ static void __take_cap_refs(struct ceph_inode_info *ci, int got,
  * to (when applicable), and check against max_size here as well.
  * Note that caller is responsible for ensuring max_size increases are
  * requested from the MDS.
+ *
+ * Returns 0 if caps were not able to be acquired (yet), a 1 if they were,
+ * or a negative error code.
+ *
+ * FIXME: how does a 0 return differ from -EAGAIN?
  */
 static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want,
-                           loff_t endoff, bool nonblock, int *got, int *err)
+                           loff_t endoff, bool nonblock, int *got)
 {
        struct inode *inode = &ci->vfs_inode;
        struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
@@ -2550,8 +2552,7 @@ again:
        if ((file_wanted & need) != need) {
                dout("try_get_cap_refs need %s file_wanted %s, EBADF\n",
                     ceph_cap_string(need), ceph_cap_string(file_wanted));
-               *err = -EBADF;
-               ret = 1;
+               ret = -EBADF;
                goto out_unlock;
        }
 
@@ -2572,10 +2573,8 @@ again:
                if (endoff >= 0 && endoff > (loff_t)ci->i_max_size) {
                        dout("get_cap_refs %p endoff %llu > maxsize %llu\n",
                             inode, endoff, ci->i_max_size);
-                       if (endoff > ci->i_requested_max_size) {
-                               *err = -EAGAIN;
-                               ret = 1;
-                       }
+                       if (endoff > ci->i_requested_max_size)
+                               ret = -EAGAIN;
                        goto out_unlock;
                }
                /*
@@ -2610,8 +2609,7 @@ again:
                                         * task isn't in TASK_RUNNING state
                                         */
                                        if (nonblock) {
-                                               *err = -EAGAIN;
-                                               ret = 1;
+                                               ret = -EAGAIN;
                                                goto out_unlock;
                                        }
 
@@ -2640,8 +2638,7 @@ again:
                if (session_readonly) {
                        dout("get_cap_refs %p needed %s but mds%d readonly\n",
                             inode, ceph_cap_string(need), ci->i_auth_cap->mds);
-                       *err = -EROFS;
-                       ret = 1;
+                       ret = -EROFS;
                        goto out_unlock;
                }
 
@@ -2650,16 +2647,14 @@ again:
                        if (READ_ONCE(mdsc->fsc->mount_state) ==
                            CEPH_MOUNT_SHUTDOWN) {
                                dout("get_cap_refs %p forced umount\n", inode);
-                               *err = -EIO;
-                               ret = 1;
+                               ret = -EIO;
                                goto out_unlock;
                        }
                        mds_wanted = __ceph_caps_mds_wanted(ci, false);
                        if (need & ~(mds_wanted & need)) {
                                dout("get_cap_refs %p caps were dropped"
                                     " (session killed?)\n", inode);
-                               *err = -ESTALE;
-                               ret = 1;
+                               ret = -ESTALE;
                                goto out_unlock;
                        }
                        if (!(file_wanted & ~mds_wanted))
@@ -2710,7 +2705,7 @@ static void check_max_size(struct inode *inode, loff_t endoff)
 int ceph_try_get_caps(struct ceph_inode_info *ci, int need, int want,
                      bool nonblock, int *got)
 {
-       int ret, err = 0;
+       int ret;
 
        BUG_ON(need & ~CEPH_CAP_FILE_RD);
        BUG_ON(want & ~(CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO|CEPH_CAP_FILE_SHARED));
@@ -2718,15 +2713,8 @@ int ceph_try_get_caps(struct ceph_inode_info *ci, int need, int want,
        if (ret < 0)
                return ret;
 
-       ret = try_get_cap_refs(ci, need, want, 0, nonblock, got, &err);
-       if (ret) {
-               if (err == -EAGAIN) {
-                       ret = 0;
-               } else if (err < 0) {
-                       ret = err;
-               }
-       }
-       return ret;
+       ret = try_get_cap_refs(ci, need, want, 0, nonblock, got);
+       return ret == -EAGAIN ? 0 : ret;
 }
 
 /*
@@ -2737,7 +2725,7 @@ int ceph_try_get_caps(struct ceph_inode_info *ci, int need, int want,
 int ceph_get_caps(struct ceph_inode_info *ci, int need, int want,
                  loff_t endoff, int *got, struct page **pinned_page)
 {
-       int _got, ret, err = 0;
+       int _got, ret;
 
        ret = ceph_pool_perm_check(ci, need);
        if (ret < 0)
@@ -2747,21 +2735,19 @@ int ceph_get_caps(struct ceph_inode_info *ci, int need, int want,
                if (endoff > 0)
                        check_max_size(&ci->vfs_inode, endoff);
 
-               err = 0;
                _got = 0;
                ret = try_get_cap_refs(ci, need, want, endoff,
-                                      false, &_got, &err);
-               if (ret) {
-                       if (err == -EAGAIN)
-                               continue;
-                       if (err < 0)
-                               ret = err;
-               } else {
+                                      false, &_got);
+               if (ret == -EAGAIN) {
+                       continue;
+               } else if (!ret) {
+                       int err;
+
                        DEFINE_WAIT_FUNC(wait, woken_wake_function);
                        add_wait_queue(&ci->i_cap_wq, &wait);
 
-                       while (!try_get_cap_refs(ci, need, want, endoff,
-                                                true, &_got, &err)) {
+                       while (!(err = try_get_cap_refs(ci, need, want, endoff,
+                                                       true, &_got))) {
                                if (signal_pending(current)) {
                                        ret = -ERESTARTSYS;
                                        break;
@@ -2770,19 +2756,14 @@ int ceph_get_caps(struct ceph_inode_info *ci, int need, int want,
                        }
 
                        remove_wait_queue(&ci->i_cap_wq, &wait);
-
                        if (err == -EAGAIN)
                                continue;
-                       if (err < 0)
-                               ret = err;
                }
-               if (ret < 0) {
-                       if (err == -ESTALE) {
-                               /* session was killed, try renew caps */
-                               ret = ceph_renew_caps(&ci->vfs_inode);
-                               if (ret == 0)
-                                       continue;
-                       }
+               if (ret == -ESTALE) {
+                       /* session was killed, try renew caps */
+                       ret = ceph_renew_caps(&ci->vfs_inode);
+                       if (ret == 0)
+                               continue;
                        return ret;
                }
 
@@ -4099,7 +4080,7 @@ void ceph_put_fmode(struct ceph_inode_info *ci, int fmode)
 }
 
 /*
- * For a soon-to-be unlinked file, drop the AUTH_RDCACHE caps. If it
+ * For a soon-to-be unlinked file, drop the LINK caps. If it
  * looks like the link count will hit 0, drop any other caps (other
  * than PIN) we don't specifically want (due to the file still being
  * open).
index 98365e7..b3fc5fe 100644 (file)
@@ -37,7 +37,7 @@ static int mdsmap_show(struct seq_file *s, void *p)
                struct ceph_entity_addr *addr = &mdsmap->m_info[i].addr;
                int state = mdsmap->m_info[i].state;
                seq_printf(s, "\tmds%d\t%s\t(%s)\n", i,
-                              ceph_pr_addr(&addr->in_addr),
+                              ceph_pr_addr(addr),
                               ceph_mds_state_name(state));
        }
        return 0;
@@ -88,7 +88,7 @@ static int mdsc_show(struct seq_file *s, void *p)
                                   req->r_dentry,
                                   path ? path : "");
                        spin_unlock(&req->r_dentry->d_lock);
-                       kfree(path);
+                       ceph_mdsc_free_path(path, pathlen);
                } else if (req->r_path1) {
                        seq_printf(s, " #%llx/%s", req->r_ino1.ino,
                                   req->r_path1);
@@ -108,7 +108,7 @@ static int mdsc_show(struct seq_file *s, void *p)
                                   req->r_old_dentry,
                                   path ? path : "");
                        spin_unlock(&req->r_old_dentry->d_lock);
-                       kfree(path);
+                       ceph_mdsc_free_path(path, pathlen);
                } else if (req->r_path2 && req->r_op != CEPH_MDS_OP_SYMLINK) {
                        if (req->r_ino2.ino)
                                seq_printf(s, " #%llx/%s", req->r_ino2.ino,
@@ -124,18 +124,48 @@ static int mdsc_show(struct seq_file *s, void *p)
        return 0;
 }
 
+static int caps_show_cb(struct inode *inode, struct ceph_cap *cap, void *p)
+{
+       struct seq_file *s = p;
+
+       seq_printf(s, "0x%-17lx%-17s%-17s\n", inode->i_ino,
+                  ceph_cap_string(cap->issued),
+                  ceph_cap_string(cap->implemented));
+       return 0;
+}
+
 static int caps_show(struct seq_file *s, void *p)
 {
        struct ceph_fs_client *fsc = s->private;
-       int total, avail, used, reserved, min;
+       struct ceph_mds_client *mdsc = fsc->mdsc;
+       int total, avail, used, reserved, min, i;
 
        ceph_reservation_status(fsc, &total, &avail, &used, &reserved, &min);
        seq_printf(s, "total\t\t%d\n"
                   "avail\t\t%d\n"
                   "used\t\t%d\n"
                   "reserved\t%d\n"
-                  "min\t%d\n",
+                  "min\t\t%d\n\n",
                   total, avail, used, reserved, min);
+       seq_printf(s, "ino                issued           implemented\n");
+       seq_printf(s, "-----------------------------------------------\n");
+
+       mutex_lock(&mdsc->mutex);
+       for (i = 0; i < mdsc->max_sessions; i++) {
+               struct ceph_mds_session *session;
+
+               session = __ceph_lookup_mds_session(mdsc, i);
+               if (!session)
+                       continue;
+               mutex_unlock(&mdsc->mutex);
+               mutex_lock(&session->s_mutex);
+               ceph_iterate_session_caps(session, caps_show_cb, s);
+               mutex_unlock(&session->s_mutex);
+               ceph_put_mds_session(session);
+               mutex_lock(&mdsc->mutex);
+       }
+       mutex_unlock(&mdsc->mutex);
+
        return 0;
 }
 
index 3c59ad1..d3ef7ee 100644 (file)
@@ -22,18 +22,77 @@ struct ceph_nfs_confh {
        u64 ino, parent_ino;
 } __attribute__ ((packed));
 
+/*
+ * fh for snapped inode
+ */
+struct ceph_nfs_snapfh {
+       u64 ino;
+       u64 snapid;
+       u64 parent_ino;
+       u32 hash;
+} __attribute__ ((packed));
+
+static int ceph_encode_snapfh(struct inode *inode, u32 *rawfh, int *max_len,
+                             struct inode *parent_inode)
+{
+       const static int snap_handle_length =
+               sizeof(struct ceph_nfs_snapfh) >> 2;
+       struct ceph_nfs_snapfh *sfh = (void *)rawfh;
+       u64 snapid = ceph_snap(inode);
+       int ret;
+       bool no_parent = true;
+
+       if (*max_len < snap_handle_length) {
+               *max_len = snap_handle_length;
+               ret = FILEID_INVALID;
+               goto out;
+       }
+
+       ret =  -EINVAL;
+       if (snapid != CEPH_SNAPDIR) {
+               struct inode *dir;
+               struct dentry *dentry = d_find_alias(inode);
+               if (!dentry)
+                       goto out;
+
+               rcu_read_lock();
+               dir = d_inode_rcu(dentry->d_parent);
+               if (ceph_snap(dir) != CEPH_SNAPDIR) {
+                       sfh->parent_ino = ceph_ino(dir);
+                       sfh->hash = ceph_dentry_hash(dir, dentry);
+                       no_parent = false;
+               }
+               rcu_read_unlock();
+               dput(dentry);
+       }
+
+       if (no_parent) {
+               if (!S_ISDIR(inode->i_mode))
+                       goto out;
+               sfh->parent_ino = sfh->ino;
+               sfh->hash = 0;
+       }
+       sfh->ino = ceph_ino(inode);
+       sfh->snapid = snapid;
+
+       *max_len = snap_handle_length;
+       ret = FILEID_BTRFS_WITH_PARENT;
+out:
+       dout("encode_snapfh %llx.%llx ret=%d\n", ceph_vinop(inode), ret);
+       return ret;
+}
+
 static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
                          struct inode *parent_inode)
 {
+       const static int handle_length =
+               sizeof(struct ceph_nfs_fh) >> 2;
+       const static int connected_handle_length =
+               sizeof(struct ceph_nfs_confh) >> 2;
        int type;
-       struct ceph_nfs_fh *fh = (void *)rawfh;
-       struct ceph_nfs_confh *cfh = (void *)rawfh;
-       int connected_handle_length = sizeof(*cfh)/4;
-       int handle_length = sizeof(*fh)/4;
 
-       /* don't re-export snaps */
        if (ceph_snap(inode) != CEPH_NOSNAP)
-               return -EINVAL;
+               return ceph_encode_snapfh(inode, rawfh, max_len, parent_inode);
 
        if (parent_inode && (*max_len < connected_handle_length)) {
                *max_len = connected_handle_length;
@@ -44,6 +103,7 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
        }
 
        if (parent_inode) {
+               struct ceph_nfs_confh *cfh = (void *)rawfh;
                dout("encode_fh %llx with parent %llx\n",
                     ceph_ino(inode), ceph_ino(parent_inode));
                cfh->ino = ceph_ino(inode);
@@ -51,6 +111,7 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
                *max_len = connected_handle_length;
                type = FILEID_INO32_GEN_PARENT;
        } else {
+               struct ceph_nfs_fh *fh = (void *)rawfh;
                dout("encode_fh %llx\n", ceph_ino(inode));
                fh->ino = ceph_ino(inode);
                *max_len = handle_length;
@@ -59,7 +120,7 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
        return type;
 }
 
-static struct dentry *__fh_to_dentry(struct super_block *sb, u64 ino)
+static struct inode *__lookup_inode(struct super_block *sb, u64 ino)
 {
        struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
        struct inode *inode;
@@ -81,7 +142,7 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, u64 ino)
                mask = CEPH_STAT_CAP_INODE;
                if (ceph_security_xattr_wanted(d_inode(sb->s_root)))
                        mask |= CEPH_CAP_XATTR_SHARED;
-               req->r_args.getattr.mask = cpu_to_le32(mask);
+               req->r_args.lookupino.mask = cpu_to_le32(mask);
 
                req->r_ino1 = vino;
                req->r_num_caps = 1;
@@ -91,16 +152,114 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, u64 ino)
                        ihold(inode);
                ceph_mdsc_put_request(req);
                if (!inode)
-                       return ERR_PTR(-ESTALE);
-               if (inode->i_nlink == 0) {
-                       iput(inode);
-                       return ERR_PTR(-ESTALE);
-               }
+                       return err < 0 ? ERR_PTR(err) : ERR_PTR(-ESTALE);
        }
+       return inode;
+}
+
+struct inode *ceph_lookup_inode(struct super_block *sb, u64 ino)
+{
+       struct inode *inode = __lookup_inode(sb, ino);
+       if (IS_ERR(inode))
+               return inode;
+       if (inode->i_nlink == 0) {
+               iput(inode);
+               return ERR_PTR(-ESTALE);
+       }
+       return inode;
+}
 
+static struct dentry *__fh_to_dentry(struct super_block *sb, u64 ino)
+{
+       struct inode *inode = __lookup_inode(sb, ino);
+       if (IS_ERR(inode))
+               return ERR_CAST(inode);
+       if (inode->i_nlink == 0) {
+               iput(inode);
+               return ERR_PTR(-ESTALE);
+       }
        return d_obtain_alias(inode);
 }
 
+static struct dentry *__snapfh_to_dentry(struct super_block *sb,
+                                         struct ceph_nfs_snapfh *sfh,
+                                         bool want_parent)
+{
+       struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
+       struct ceph_mds_request *req;
+       struct inode *inode;
+       struct ceph_vino vino;
+       int mask;
+       int err;
+       bool unlinked = false;
+
+       if (want_parent) {
+               vino.ino = sfh->parent_ino;
+               if (sfh->snapid == CEPH_SNAPDIR)
+                       vino.snap = CEPH_NOSNAP;
+               else if (sfh->ino == sfh->parent_ino)
+                       vino.snap = CEPH_SNAPDIR;
+               else
+                       vino.snap = sfh->snapid;
+       } else {
+               vino.ino = sfh->ino;
+               vino.snap = sfh->snapid;
+       }
+       inode = ceph_find_inode(sb, vino);
+       if (inode)
+               return d_obtain_alias(inode);
+
+       req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPINO,
+                                      USE_ANY_MDS);
+       if (IS_ERR(req))
+               return ERR_CAST(req);
+
+       mask = CEPH_STAT_CAP_INODE;
+       if (ceph_security_xattr_wanted(d_inode(sb->s_root)))
+               mask |= CEPH_CAP_XATTR_SHARED;
+       req->r_args.lookupino.mask = cpu_to_le32(mask);
+       if (vino.snap < CEPH_NOSNAP) {
+               req->r_args.lookupino.snapid = cpu_to_le64(vino.snap);
+               if (!want_parent && sfh->ino != sfh->parent_ino) {
+                       req->r_args.lookupino.parent =
+                                       cpu_to_le64(sfh->parent_ino);
+                       req->r_args.lookupino.hash =
+                                       cpu_to_le32(sfh->hash);
+               }
+       }
+
+       req->r_ino1 = vino;
+       req->r_num_caps = 1;
+       err = ceph_mdsc_do_request(mdsc, NULL, req);
+       inode = req->r_target_inode;
+       if (inode) {
+               if (vino.snap == CEPH_SNAPDIR) {
+                       if (inode->i_nlink == 0)
+                               unlinked = true;
+                       inode = ceph_get_snapdir(inode);
+               } else if (ceph_snap(inode) == vino.snap) {
+                       ihold(inode);
+               } else {
+                       /* mds does not support lookup snapped inode */
+                       err = -EOPNOTSUPP;
+                       inode = NULL;
+               }
+       }
+       ceph_mdsc_put_request(req);
+
+       if (want_parent) {
+               dout("snapfh_to_parent %llx.%llx\n err=%d\n",
+                    vino.ino, vino.snap, err);
+       } else {
+               dout("snapfh_to_dentry %llx.%llx parent %llx hash %x err=%d",
+                     vino.ino, vino.snap, sfh->parent_ino, sfh->hash, err);
+       }
+       if (!inode)
+               return ERR_PTR(-ESTALE);
+       /* see comments in ceph_get_parent() */
+       return unlinked ? d_obtain_root(inode) : d_obtain_alias(inode);
+}
+
 /*
  * convert regular fh to dentry
  */
@@ -110,6 +269,11 @@ static struct dentry *ceph_fh_to_dentry(struct super_block *sb,
 {
        struct ceph_nfs_fh *fh = (void *)fid->raw;
 
+       if (fh_type == FILEID_BTRFS_WITH_PARENT) {
+               struct ceph_nfs_snapfh *sfh = (void *)fid->raw;
+               return __snapfh_to_dentry(sb, sfh, false);
+       }
+
        if (fh_type != FILEID_INO32_GEN  &&
            fh_type != FILEID_INO32_GEN_PARENT)
                return NULL;
@@ -163,13 +327,49 @@ static struct dentry *__get_parent(struct super_block *sb,
 
 static struct dentry *ceph_get_parent(struct dentry *child)
 {
-       /* don't re-export snaps */
-       if (ceph_snap(d_inode(child)) != CEPH_NOSNAP)
-               return ERR_PTR(-EINVAL);
-
-       dout("get_parent %p ino %llx.%llx\n",
-            child, ceph_vinop(d_inode(child)));
-       return __get_parent(child->d_sb, child, 0);
+       struct inode *inode = d_inode(child);
+       struct dentry *dn;
+
+       if (ceph_snap(inode) != CEPH_NOSNAP) {
+               struct inode* dir;
+               bool unlinked = false;
+               /* do not support non-directory */
+               if (!d_is_dir(child)) {
+                       dn = ERR_PTR(-EINVAL);
+                       goto out;
+               }
+               dir = __lookup_inode(inode->i_sb, ceph_ino(inode));
+               if (IS_ERR(dir)) {
+                       dn = ERR_CAST(dir);
+                       goto out;
+               }
+               /* There can be multiple paths to access snapped inode.
+                * For simplicity, treat snapdir of head inode as parent */
+               if (ceph_snap(inode) != CEPH_SNAPDIR) {
+                       struct inode *snapdir = ceph_get_snapdir(dir);
+                       if (dir->i_nlink == 0)
+                               unlinked = true;
+                       iput(dir);
+                       if (IS_ERR(snapdir)) {
+                               dn = ERR_CAST(snapdir);
+                               goto out;
+                       }
+                       dir = snapdir;
+               }
+               /* If directory has already been deleted, futher get_parent
+                * will fail. Do not mark snapdir dentry as disconnected,
+                * this prevent exportfs from doing futher get_parent. */
+               if (unlinked)
+                       dn = d_obtain_root(dir);
+               else
+                       dn = d_obtain_alias(dir);
+       } else {
+               dn = __get_parent(child->d_sb, child, 0);
+       }
+out:
+       dout("get_parent %p ino %llx.%llx err=%ld\n",
+            child, ceph_vinop(inode), (IS_ERR(dn) ? PTR_ERR(dn) : 0));
+       return dn;
 }
 
 /*
@@ -182,6 +382,11 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb,
        struct ceph_nfs_confh *cfh = (void *)fid->raw;
        struct dentry *dentry;
 
+       if (fh_type == FILEID_BTRFS_WITH_PARENT) {
+               struct ceph_nfs_snapfh *sfh = (void *)fid->raw;
+               return __snapfh_to_dentry(sb, sfh, true);
+       }
+
        if (fh_type != FILEID_INO32_GEN_PARENT)
                return NULL;
        if (fh_len < sizeof(*cfh) / 4)
@@ -194,14 +399,115 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb,
        return dentry;
 }
 
+static int __get_snap_name(struct dentry *parent, char *name,
+                          struct dentry *child)
+{
+       struct inode *inode = d_inode(child);
+       struct inode *dir = d_inode(parent);
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+       struct ceph_mds_request *req = NULL;
+       char *last_name = NULL;
+       unsigned next_offset = 2;
+       int err = -EINVAL;
+
+       if (ceph_ino(inode) != ceph_ino(dir))
+               goto out;
+       if (ceph_snap(inode) == CEPH_SNAPDIR) {
+               if (ceph_snap(dir) == CEPH_NOSNAP) {
+                       strcpy(name, fsc->mount_options->snapdir_name);
+                       err = 0;
+               }
+               goto out;
+       }
+       if (ceph_snap(dir) != CEPH_SNAPDIR)
+               goto out;
+
+       while (1) {
+               struct ceph_mds_reply_info_parsed *rinfo;
+               struct ceph_mds_reply_dir_entry *rde;
+               int i;
+
+               req = ceph_mdsc_create_request(fsc->mdsc, CEPH_MDS_OP_LSSNAP,
+                                              USE_AUTH_MDS);
+               if (IS_ERR(req)) {
+                       err = PTR_ERR(req);
+                       req = NULL;
+                       goto out;
+               }
+               err = ceph_alloc_readdir_reply_buffer(req, inode);
+               if (err)
+                       goto out;
+
+               req->r_direct_mode = USE_AUTH_MDS;
+               req->r_readdir_offset = next_offset;
+               req->r_args.readdir.flags =
+                               cpu_to_le16(CEPH_READDIR_REPLY_BITFLAGS);
+               if (last_name) {
+                       req->r_path2 = last_name;
+                       last_name = NULL;
+               }
+
+               req->r_inode = dir;
+               ihold(dir);
+               req->r_dentry = dget(parent);
+
+               inode_lock(dir);
+               err = ceph_mdsc_do_request(fsc->mdsc, NULL, req);
+               inode_unlock(dir);
+
+               if (err < 0)
+                       goto out;
+
+                rinfo = &req->r_reply_info;
+                for (i = 0; i < rinfo->dir_nr; i++) {
+                        rde = rinfo->dir_entries + i;
+                        BUG_ON(!rde->inode.in);
+                        if (ceph_snap(inode) ==
+                            le64_to_cpu(rde->inode.in->snapid)) {
+                                memcpy(name, rde->name, rde->name_len);
+                                name[rde->name_len] = '\0';
+                                err = 0;
+                                goto out;
+                        }
+                }
+
+                if (rinfo->dir_end)
+                        break;
+
+                BUG_ON(rinfo->dir_nr <= 0);
+                rde = rinfo->dir_entries + (rinfo->dir_nr - 1);
+                next_offset += rinfo->dir_nr;
+                last_name = kstrndup(rde->name, rde->name_len, GFP_KERNEL);
+                if (!last_name) {
+                        err = -ENOMEM;
+                        goto out;
+                }
+
+                ceph_mdsc_put_request(req);
+                req = NULL;
+       }
+       err = -ENOENT;
+out:
+       if (req)
+               ceph_mdsc_put_request(req);
+       kfree(last_name);
+       dout("get_snap_name %p ino %llx.%llx err=%d\n",
+            child, ceph_vinop(inode), err);
+       return err;
+}
+
 static int ceph_get_name(struct dentry *parent, char *name,
                         struct dentry *child)
 {
        struct ceph_mds_client *mdsc;
        struct ceph_mds_request *req;
+       struct inode *inode = d_inode(child);
        int err;
 
-       mdsc = ceph_inode_to_client(d_inode(child))->mdsc;
+       if (ceph_snap(inode) != CEPH_NOSNAP)
+               return __get_snap_name(parent, name, child);
+
+       mdsc = ceph_inode_to_client(inode)->mdsc;
        req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPNAME,
                                       USE_ANY_MDS);
        if (IS_ERR(req))
@@ -209,8 +515,8 @@ static int ceph_get_name(struct dentry *parent, char *name,
 
        inode_lock(d_inode(parent));
 
-       req->r_inode = d_inode(child);
-       ihold(d_inode(child));
+       req->r_inode = inode;
+       ihold(inode);
        req->r_ino2 = ceph_vino(d_inode(parent));
        req->r_parent = d_inode(parent);
        set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
@@ -224,10 +530,10 @@ static int ceph_get_name(struct dentry *parent, char *name,
                memcpy(name, rinfo->dname, rinfo->dname_len);
                name[rinfo->dname_len] = 0;
                dout("get_name %p ino %llx.%llx name %s\n",
-                    child, ceph_vinop(d_inode(child)), name);
+                    child, ceph_vinop(inode), name);
        } else {
                dout("get_name %p ino %llx.%llx err %d\n",
-                    child, ceph_vinop(d_inode(child)), err);
+                    child, ceph_vinop(inode), err);
        }
 
        ceph_mdsc_put_request(req);
index 84725b5..305daf0 100644 (file)
@@ -929,7 +929,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
 
        dout("sync_direct_%s on file %p %lld~%u snapc %p seq %lld\n",
             (write ? "write" : "read"), file, pos, (unsigned)count,
-            snapc, snapc->seq);
+            snapc, snapc ? snapc->seq : 0);
 
        ret = filemap_write_and_wait_range(inode->i_mapping,
                                           pos, pos + count - 1);
index 35dae6d..f85355b 100644 (file)
@@ -2266,43 +2266,72 @@ int ceph_permission(struct inode *inode, int mask)
        return err;
 }
 
+/* Craft a mask of needed caps given a set of requested statx attrs. */
+static int statx_to_caps(u32 want)
+{
+       int mask = 0;
+
+       if (want & (STATX_MODE|STATX_UID|STATX_GID|STATX_CTIME))
+               mask |= CEPH_CAP_AUTH_SHARED;
+
+       if (want & (STATX_NLINK|STATX_CTIME))
+               mask |= CEPH_CAP_LINK_SHARED;
+
+       if (want & (STATX_ATIME|STATX_MTIME|STATX_CTIME|STATX_SIZE|
+                   STATX_BLOCKS))
+               mask |= CEPH_CAP_FILE_SHARED;
+
+       if (want & (STATX_CTIME))
+               mask |= CEPH_CAP_XATTR_SHARED;
+
+       return mask;
+}
+
 /*
- * Get all attributes.  Hopefully somedata we'll have a statlite()
- * and can limit the fields we require to be accurate.
+ * Get all the attributes. If we have sufficient caps for the requested attrs,
+ * then we can avoid talking to the MDS at all.
  */
 int ceph_getattr(const struct path *path, struct kstat *stat,
                 u32 request_mask, unsigned int flags)
 {
        struct inode *inode = d_inode(path->dentry);
        struct ceph_inode_info *ci = ceph_inode(inode);
-       int err;
+       int err = 0;
 
-       err = ceph_do_getattr(inode, CEPH_STAT_CAP_INODE_ALL, false);
-       if (!err) {
-               generic_fillattr(inode, stat);
-               stat->ino = ceph_translate_ino(inode->i_sb, inode->i_ino);
-               if (ceph_snap(inode) == CEPH_NOSNAP)
-                       stat->dev = inode->i_sb->s_dev;
+       /* Skip the getattr altogether if we're asked not to sync */
+       if (!(flags & AT_STATX_DONT_SYNC)) {
+               err = ceph_do_getattr(inode, statx_to_caps(request_mask),
+                                     flags & AT_STATX_FORCE_SYNC);
+               if (err)
+                       return err;
+       }
+
+       generic_fillattr(inode, stat);
+       stat->ino = ceph_translate_ino(inode->i_sb, inode->i_ino);
+       if (ceph_snap(inode) == CEPH_NOSNAP)
+               stat->dev = inode->i_sb->s_dev;
+       else
+               stat->dev = ci->i_snapid_map ? ci->i_snapid_map->dev : 0;
+
+       if (S_ISDIR(inode->i_mode)) {
+               if (ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb),
+                                       RBYTES))
+                       stat->size = ci->i_rbytes;
                else
-                       stat->dev = ci->i_snapid_map ? ci->i_snapid_map->dev : 0;
-
-               if (S_ISDIR(inode->i_mode)) {
-                       if (ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb),
-                                               RBYTES))
-                               stat->size = ci->i_rbytes;
-                       else
-                               stat->size = ci->i_files + ci->i_subdirs;
-                       stat->blocks = 0;
-                       stat->blksize = 65536;
-                       /*
-                        * Some applications rely on the number of st_nlink
-                        * value on directories to be either 0 (if unlinked)
-                        * or 2 + number of subdirectories.
-                        */
-                       if (stat->nlink == 1)
-                               /* '.' + '..' + subdirs */
-                               stat->nlink = 1 + 1 + ci->i_subdirs;
-               }
+                       stat->size = ci->i_files + ci->i_subdirs;
+               stat->blocks = 0;
+               stat->blksize = 65536;
+               /*
+                * Some applications rely on the number of st_nlink
+                * value on directories to be either 0 (if unlinked)
+                * or 2 + number of subdirectories.
+                */
+               if (stat->nlink == 1)
+                       /* '.' + '..' + subdirs */
+                       stat->nlink = 1 + 1 + ci->i_subdirs;
        }
+
+       /* Mask off any higher bits (e.g. btime) until we have support */
+       stat->result_mask = request_mask & STATX_BASIC_STATS;
        return err;
 }
index 9dae2ec..ac9b53b 100644 (file)
@@ -237,15 +237,6 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
        spin_lock(&ci->i_ceph_lock);
        if (ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) {
                err = -EIO;
-       } else if (op == CEPH_MDS_OP_SETFILELOCK) {
-               /*
-                * increasing i_filelock_ref closes race window between
-                * handling request reply and adding file_lock struct to
-                * inode. Otherwise, i_auth_cap may get trimmed in the
-                * window. Caller function will decrease the counter.
-                */
-               fl->fl_ops = &ceph_fl_lock_ops;
-               atomic_inc(&ci->i_filelock_ref);
        }
        spin_unlock(&ci->i_ceph_lock);
        if (err < 0) {
@@ -299,10 +290,6 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
        spin_lock(&ci->i_ceph_lock);
        if (ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) {
                err = -EIO;
-       } else {
-               /* see comment in ceph_lock */
-               fl->fl_ops = &ceph_fl_lock_ops;
-               atomic_inc(&ci->i_filelock_ref);
        }
        spin_unlock(&ci->i_ceph_lock);
        if (err < 0) {
index 9049c2a..959b1bf 100644 (file)
@@ -550,15 +550,9 @@ void ceph_put_mds_session(struct ceph_mds_session *s)
 struct ceph_mds_session *__ceph_lookup_mds_session(struct ceph_mds_client *mdsc,
                                                   int mds)
 {
-       struct ceph_mds_session *session;
-
        if (mds >= mdsc->max_sessions || !mdsc->sessions[mds])
                return NULL;
-       session = mdsc->sessions[mds];
-       dout("lookup_mds_session %p %d\n", session,
-            refcount_read(&session->s_ref));
-       get_session(session);
-       return session;
+       return get_session(mdsc->sessions[mds]);
 }
 
 static bool __have_session(struct ceph_mds_client *mdsc, int mds)
@@ -1284,9 +1278,9 @@ static void cleanup_session_requests(struct ceph_mds_client *mdsc,
  *
  * Caller must hold session s_mutex.
  */
-static int iterate_session_caps(struct ceph_mds_session *session,
-                                int (*cb)(struct inode *, struct ceph_cap *,
-                                           void *), void *arg)
+int ceph_iterate_session_caps(struct ceph_mds_session *session,
+                             int (*cb)(struct inode *, struct ceph_cap *,
+                                       void *), void *arg)
 {
        struct list_head *p;
        struct ceph_cap *cap;
@@ -1451,7 +1445,7 @@ static void remove_session_caps(struct ceph_mds_session *session)
        LIST_HEAD(dispose);
 
        dout("remove_session_caps on %p\n", session);
-       iterate_session_caps(session, remove_session_caps_cb, fsc);
+       ceph_iterate_session_caps(session, remove_session_caps_cb, fsc);
 
        wake_up_all(&fsc->mdsc->cap_flushing_wq);
 
@@ -1534,8 +1528,8 @@ static int wake_up_session_cb(struct inode *inode, struct ceph_cap *cap,
 static void wake_up_session_caps(struct ceph_mds_session *session, int ev)
 {
        dout("wake_up_session_caps %p mds%d\n", session, session->s_mds);
-       iterate_session_caps(session, wake_up_session_cb,
-                            (void *)(unsigned long)ev);
+       ceph_iterate_session_caps(session, wake_up_session_cb,
+                                 (void *)(unsigned long)ev);
 }
 
 /*
@@ -1768,7 +1762,7 @@ int ceph_trim_caps(struct ceph_mds_client *mdsc,
             session->s_mds, session->s_nr_caps, max_caps, trim_caps);
        if (trim_caps > 0) {
                session->s_trim_caps = trim_caps;
-               iterate_session_caps(session, trim_caps_cb, session);
+               ceph_iterate_session_caps(session, trim_caps_cb, session);
                dout("trim_caps mds%d done: %d / %d, trimmed %d\n",
                     session->s_mds, session->s_nr_caps, max_caps,
                        trim_caps - session->s_trim_caps);
@@ -1861,7 +1855,8 @@ again:
                num_cap_releases--;
 
                head = msg->front.iov_base;
-               le32_add_cpu(&head->num, 1);
+               put_unaligned_le32(get_unaligned_le32(&head->num) + 1,
+                                  &head->num);
                item = msg->front.iov_base + msg->front.iov_len;
                item->ino = cpu_to_le64(cap->cap_ino);
                item->cap_id = cpu_to_le64(cap->cap_id);
@@ -2089,43 +2084,29 @@ static inline  u64 __get_oldest_tid(struct ceph_mds_client *mdsc)
  * Encode hidden .snap dirs as a double /, i.e.
  *   foo/.snap/bar -> foo//bar
  */
-char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base,
+char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase,
                           int stop_on_nosnap)
 {
        struct dentry *temp;
        char *path;
-       int len, pos;
+       int pos;
        unsigned seq;
+       u64 base;
 
        if (!dentry)
                return ERR_PTR(-EINVAL);
 
-retry:
-       len = 0;
-       seq = read_seqbegin(&rename_lock);
-       rcu_read_lock();
-       for (temp = dentry; !IS_ROOT(temp);) {
-               struct inode *inode = d_inode(temp);
-               if (inode && ceph_snap(inode) == CEPH_SNAPDIR)
-                       len++;  /* slash only */
-               else if (stop_on_nosnap && inode &&
-                        ceph_snap(inode) == CEPH_NOSNAP)
-                       break;
-               else
-                       len += 1 + temp->d_name.len;
-               temp = temp->d_parent;
-       }
-       rcu_read_unlock();
-       if (len)
-               len--;  /* no leading '/' */
-
-       path = kmalloc(len+1, GFP_NOFS);
+       path = __getname();
        if (!path)
                return ERR_PTR(-ENOMEM);
-       pos = len;
-       path[pos] = 0;  /* trailing null */
+retry:
+       pos = PATH_MAX - 1;
+       path[pos] = '\0';
+
+       seq = read_seqbegin(&rename_lock);
        rcu_read_lock();
-       for (temp = dentry; !IS_ROOT(temp) && pos != 0; ) {
+       temp = dentry;
+       for (;;) {
                struct inode *inode;
 
                spin_lock(&temp->d_lock);
@@ -2143,83 +2124,54 @@ retry:
                                spin_unlock(&temp->d_lock);
                                break;
                        }
-                       strncpy(path + pos, temp->d_name.name,
-                               temp->d_name.len);
+                       memcpy(path + pos, temp->d_name.name, temp->d_name.len);
                }
                spin_unlock(&temp->d_lock);
-               if (pos)
-                       path[--pos] = '/';
                temp = temp->d_parent;
+
+               /* Are we at the root? */
+               if (IS_ROOT(temp))
+                       break;
+
+               /* Are we out of buffer? */
+               if (--pos < 0)
+                       break;
+
+               path[pos] = '/';
        }
+       base = ceph_ino(d_inode(temp));
        rcu_read_unlock();
-       if (pos != 0 || read_seqretry(&rename_lock, seq)) {
+       if (pos < 0 || read_seqretry(&rename_lock, seq)) {
                pr_err("build_path did not end path lookup where "
-                      "expected, namelen is %d, pos is %d\n", len, pos);
+                      "expected, pos is %d\n", pos);
                /* presumably this is only possible if racing with a
                   rename of one of the parent directories (we can not
                   lock the dentries above us to prevent this, but
                   retrying should be harmless) */
-               kfree(path);
                goto retry;
        }
 
-       *base = ceph_ino(d_inode(temp));
-       *plen = len;
+       *pbase = base;
+       *plen = PATH_MAX - 1 - pos;
        dout("build_path on %p %d built %llx '%.*s'\n",
-            dentry, d_count(dentry), *base, len, path);
-       return path;
-}
-
-/* Duplicate the dentry->d_name.name safely */
-static int clone_dentry_name(struct dentry *dentry, const char **ppath,
-                            int *ppathlen)
-{
-       u32 len;
-       char *name;
-
-retry:
-       len = READ_ONCE(dentry->d_name.len);
-       name = kmalloc(len + 1, GFP_NOFS);
-       if (!name)
-               return -ENOMEM;
-
-       spin_lock(&dentry->d_lock);
-       if (dentry->d_name.len != len) {
-               spin_unlock(&dentry->d_lock);
-               kfree(name);
-               goto retry;
-       }
-       memcpy(name, dentry->d_name.name, len);
-       spin_unlock(&dentry->d_lock);
-
-       name[len] = '\0';
-       *ppath = name;
-       *ppathlen = len;
-       return 0;
+            dentry, d_count(dentry), base, *plen, path + pos);
+       return path + pos;
 }
 
 static int build_dentry_path(struct dentry *dentry, struct inode *dir,
                             const char **ppath, int *ppathlen, u64 *pino,
                             bool *pfreepath, bool parent_locked)
 {
-       int ret;
        char *path;
 
        rcu_read_lock();
        if (!dir)
                dir = d_inode_rcu(dentry->d_parent);
-       if (dir && ceph_snap(dir) == CEPH_NOSNAP) {
+       if (dir && parent_locked && ceph_snap(dir) == CEPH_NOSNAP) {
                *pino = ceph_ino(dir);
                rcu_read_unlock();
-               if (parent_locked) {
-                       *ppath = dentry->d_name.name;
-                       *ppathlen = dentry->d_name.len;
-               } else {
-                       ret = clone_dentry_name(dentry, ppath, ppathlen);
-                       if (ret)
-                               return ret;
-                       *pfreepath = true;
-               }
+               *ppath = dentry->d_name.name;
+               *ppathlen = dentry->d_name.len;
                return 0;
        }
        rcu_read_unlock();
@@ -2331,9 +2283,9 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
                (!!req->r_inode_drop + !!req->r_dentry_drop +
                 !!req->r_old_inode_drop + !!req->r_old_dentry_drop);
        if (req->r_dentry_drop)
-               len += req->r_dentry->d_name.len;
+               len += pathlen1;
        if (req->r_old_dentry_drop)
-               len += req->r_old_dentry->d_name.len;
+               len += pathlen2;
 
        msg = ceph_msg_new2(CEPH_MSG_CLIENT_REQUEST, len, 1, GFP_NOFS, false);
        if (!msg) {
@@ -2410,10 +2362,10 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
 
 out_free2:
        if (freepath2)
-               kfree((char *)path2);
+               ceph_mdsc_free_path((char *)path2, pathlen2);
 out_free1:
        if (freepath1)
-               kfree((char *)path1);
+               ceph_mdsc_free_path((char *)path1, pathlen1);
 out:
        return msg;
 }
@@ -2427,8 +2379,7 @@ static void complete_request(struct ceph_mds_client *mdsc,
 {
        if (req->r_callback)
                req->r_callback(mdsc, req);
-       else
-               complete_all(&req->r_completion);
+       complete_all(&req->r_completion);
 }
 
 /*
@@ -2670,28 +2621,11 @@ static void kick_requests(struct ceph_mds_client *mdsc, int mds)
        }
 }
 
-void ceph_mdsc_submit_request(struct ceph_mds_client *mdsc,
+int ceph_mdsc_submit_request(struct ceph_mds_client *mdsc, struct inode *dir,
                              struct ceph_mds_request *req)
-{
-       dout("submit_request on %p\n", req);
-       mutex_lock(&mdsc->mutex);
-       __register_request(mdsc, req, NULL);
-       __do_request(mdsc, req);
-       mutex_unlock(&mdsc->mutex);
-}
-
-/*
- * Synchrously perform an mds request.  Take care of all of the
- * session setup, forwarding, retry details.
- */
-int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
-                        struct inode *dir,
-                        struct ceph_mds_request *req)
 {
        int err;
 
-       dout("do_request on %p\n", req);
-
        /* take CAP_PIN refs for r_inode, r_parent, r_old_dentry */
        if (req->r_inode)
                ceph_get_cap_refs(ceph_inode(req->r_inode), CEPH_CAP_PIN);
@@ -2701,18 +2635,21 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
                ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir),
                                  CEPH_CAP_PIN);
 
-       /* issue */
+       dout("submit_request on %p for inode %p\n", req, dir);
        mutex_lock(&mdsc->mutex);
        __register_request(mdsc, req, dir);
        __do_request(mdsc, req);
+       err = req->r_err;
+       mutex_unlock(&mdsc->mutex);
+       return err;
+}
 
-       if (req->r_err) {
-               err = req->r_err;
-               goto out;
-       }
+static int ceph_mdsc_wait_request(struct ceph_mds_client *mdsc,
+                                 struct ceph_mds_request *req)
+{
+       int err;
 
        /* wait */
-       mutex_unlock(&mdsc->mutex);
        dout("do_request waiting\n");
        if (!req->r_timeout && req->r_wait_for_completion) {
                err = req->r_wait_for_completion(mdsc, req);
@@ -2753,8 +2690,26 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
                err = req->r_err;
        }
 
-out:
        mutex_unlock(&mdsc->mutex);
+       return err;
+}
+
+/*
+ * Synchrously perform an mds request.  Take care of all of the
+ * session setup, forwarding, retry details.
+ */
+int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
+                        struct inode *dir,
+                        struct ceph_mds_request *req)
+{
+       int err;
+
+       dout("do_request on %p\n", req);
+
+       /* issue */
+       err = ceph_mdsc_submit_request(mdsc, dir, req);
+       if (!err)
+               err = ceph_mdsc_wait_request(mdsc, req);
        dout("do_request %p done, result %d\n", req, err);
        return err;
 }
@@ -3485,7 +3440,7 @@ out_freeflocks:
                ceph_pagelist_encode_string(pagelist, path, pathlen);
                ceph_pagelist_append(pagelist, &rec, sizeof(rec.v1));
 out_freepath:
-               kfree(path);
+               ceph_mdsc_free_path(path, pathlen);
        }
 
 out_err:
@@ -3642,7 +3597,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
                recon_state.msg_version = 2;
        }
        /* trsaverse this session's caps */
-       err = iterate_session_caps(session, encode_caps_cb, &recon_state);
+       err = ceph_iterate_session_caps(session, encode_caps_cb, &recon_state);
 
        spin_lock(&session->s_cap_lock);
        session->s_cap_reconnect = 0;
@@ -4125,6 +4080,8 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
        mdsc->max_sessions = 0;
        mdsc->stopping = 0;
        atomic64_set(&mdsc->quotarealms_count, 0);
+       mdsc->quotarealms_inodes = RB_ROOT;
+       mutex_init(&mdsc->quotarealms_inodes_mutex);
        mdsc->last_snap_seq = 0;
        init_rwsem(&mdsc->snap_rwsem);
        mdsc->snap_realms = RB_ROOT;
@@ -4216,6 +4173,8 @@ void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc)
         * their inode/dcache refs
         */
        ceph_msgr_flush();
+
+       ceph_cleanup_quotarealms_inodes(mdsc);
 }
 
 /*
index 50385a4..a83f28b 100644 (file)
@@ -325,6 +325,18 @@ struct ceph_snapid_map {
        unsigned long last_used;
 };
 
+/*
+ * node for list of quotarealm inodes that are not visible from the filesystem
+ * mountpoint, but required to handle, e.g. quotas.
+ */
+struct ceph_quotarealm_inode {
+       struct rb_node node;
+       u64 ino;
+       unsigned long timeout; /* last time a lookup failed for this inode */
+       struct mutex mutex;
+       struct inode *inode;
+};
+
 /*
  * mds client state
  */
@@ -344,6 +356,12 @@ struct ceph_mds_client {
        int                     stopping;      /* true if shutting down */
 
        atomic64_t              quotarealms_count; /* # realms with quota */
+       /*
+        * We keep a list of inodes we don't see in the mountpoint but that we
+        * need to track quota realms.
+        */
+       struct rb_root          quotarealms_inodes;
+       struct mutex            quotarealms_inodes_mutex;
 
        /*
         * snap_rwsem will cover cap linkage into snaprealms, and
@@ -447,8 +465,9 @@ extern int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req,
                                           struct inode *dir);
 extern struct ceph_mds_request *
 ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode);
-extern void ceph_mdsc_submit_request(struct ceph_mds_client *mdsc,
-                                    struct ceph_mds_request *req);
+extern int ceph_mdsc_submit_request(struct ceph_mds_client *mdsc,
+                                   struct inode *dir,
+                                   struct ceph_mds_request *req);
 extern int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
                                struct inode *dir,
                                struct ceph_mds_request *req);
@@ -468,8 +487,18 @@ extern void ceph_flush_cap_releases(struct ceph_mds_client *mdsc,
                                    struct ceph_mds_session *session);
 extern void ceph_queue_cap_reclaim_work(struct ceph_mds_client *mdsc);
 extern void ceph_reclaim_caps_nr(struct ceph_mds_client *mdsc, int nr);
+extern int ceph_iterate_session_caps(struct ceph_mds_session *session,
+                                    int (*cb)(struct inode *,
+                                              struct ceph_cap *, void *),
+                                    void *arg);
 extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc);
 
+static inline void ceph_mdsc_free_path(char *path, int len)
+{
+       if (path)
+               __putname(path - (PATH_MAX - 1 - len));
+}
+
 extern char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base,
                                  int stop_on_nosnap);
 
index 1a2c5d3..701b4fb 100644 (file)
@@ -205,7 +205,7 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
 
                dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s\n",
                     i+1, n, global_id, mds, inc,
-                    ceph_pr_addr(&addr.in_addr),
+                    ceph_pr_addr(&addr),
                     ceph_mds_state_name(state));
 
                if (mds < 0 || state <= 0)
index 9455d3a..c452221 100644 (file)
@@ -22,7 +22,16 @@ void ceph_adjust_quota_realms_count(struct inode *inode, bool inc)
 static inline bool ceph_has_realms_with_quotas(struct inode *inode)
 {
        struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
-       return atomic64_read(&mdsc->quotarealms_count) > 0;
+       struct super_block *sb = mdsc->fsc->sb;
+
+       if (atomic64_read(&mdsc->quotarealms_count) > 0)
+               return true;
+       /* if root is the real CephFS root, we don't have quota realms */
+       if (sb->s_root->d_inode &&
+           (sb->s_root->d_inode->i_ino == CEPH_INO_ROOT))
+               return false;
+       /* otherwise, we can't know for sure */
+       return true;
 }
 
 void ceph_handle_quota(struct ceph_mds_client *mdsc,
@@ -68,6 +77,108 @@ void ceph_handle_quota(struct ceph_mds_client *mdsc,
        iput(inode);
 }
 
+static struct ceph_quotarealm_inode *
+find_quotarealm_inode(struct ceph_mds_client *mdsc, u64 ino)
+{
+       struct ceph_quotarealm_inode *qri = NULL;
+       struct rb_node **node, *parent = NULL;
+
+       mutex_lock(&mdsc->quotarealms_inodes_mutex);
+       node = &(mdsc->quotarealms_inodes.rb_node);
+       while (*node) {
+               parent = *node;
+               qri = container_of(*node, struct ceph_quotarealm_inode, node);
+
+               if (ino < qri->ino)
+                       node = &((*node)->rb_left);
+               else if (ino > qri->ino)
+                       node = &((*node)->rb_right);
+               else
+                       break;
+       }
+       if (!qri || (qri->ino != ino)) {
+               /* Not found, create a new one and insert it */
+               qri = kmalloc(sizeof(*qri), GFP_KERNEL);
+               if (qri) {
+                       qri->ino = ino;
+                       qri->inode = NULL;
+                       qri->timeout = 0;
+                       mutex_init(&qri->mutex);
+                       rb_link_node(&qri->node, parent, node);
+                       rb_insert_color(&qri->node, &mdsc->quotarealms_inodes);
+               } else
+                       pr_warn("Failed to alloc quotarealms_inode\n");
+       }
+       mutex_unlock(&mdsc->quotarealms_inodes_mutex);
+
+       return qri;
+}
+
+/*
+ * This function will try to lookup a realm inode which isn't visible in the
+ * filesystem mountpoint.  A list of these kind of inodes (not visible) is
+ * maintained in the mdsc and freed only when the filesystem is umounted.
+ *
+ * Note that these inodes are kept in this list even if the lookup fails, which
+ * allows to prevent useless lookup requests.
+ */
+static struct inode *lookup_quotarealm_inode(struct ceph_mds_client *mdsc,
+                                            struct super_block *sb,
+                                            struct ceph_snap_realm *realm)
+{
+       struct ceph_quotarealm_inode *qri;
+       struct inode *in;
+
+       qri = find_quotarealm_inode(mdsc, realm->ino);
+       if (!qri)
+               return NULL;
+
+       mutex_lock(&qri->mutex);
+       if (qri->inode) {
+               /* A request has already returned the inode */
+               mutex_unlock(&qri->mutex);
+               return qri->inode;
+       }
+       /* Check if this inode lookup has failed recently */
+       if (qri->timeout &&
+           time_before_eq(jiffies, qri->timeout)) {
+               mutex_unlock(&qri->mutex);
+               return NULL;
+       }
+       in = ceph_lookup_inode(sb, realm->ino);
+       if (IS_ERR(in)) {
+               pr_warn("Can't lookup inode %llx (err: %ld)\n",
+                       realm->ino, PTR_ERR(in));
+               qri->timeout = jiffies + msecs_to_jiffies(60 * 1000); /* XXX */
+       } else {
+               qri->timeout = 0;
+               qri->inode = in;
+       }
+       mutex_unlock(&qri->mutex);
+
+       return in;
+}
+
+void ceph_cleanup_quotarealms_inodes(struct ceph_mds_client *mdsc)
+{
+       struct ceph_quotarealm_inode *qri;
+       struct rb_node *node;
+
+       /*
+        * It should now be safe to clean quotarealms_inode tree without holding
+        * mdsc->quotarealms_inodes_mutex...
+        */
+       mutex_lock(&mdsc->quotarealms_inodes_mutex);
+       while (!RB_EMPTY_ROOT(&mdsc->quotarealms_inodes)) {
+               node = rb_first(&mdsc->quotarealms_inodes);
+               qri = rb_entry(node, struct ceph_quotarealm_inode, node);
+               rb_erase(node, &mdsc->quotarealms_inodes);
+               iput(qri->inode);
+               kfree(qri);
+       }
+       mutex_unlock(&mdsc->quotarealms_inodes_mutex);
+}
+
 /*
  * This function walks through the snaprealm for an inode and returns the
  * ceph_snap_realm for the first snaprealm that has quotas set (either max_files
@@ -76,9 +187,15 @@ void ceph_handle_quota(struct ceph_mds_client *mdsc,
  *
  * Note that the caller is responsible for calling ceph_put_snap_realm() on the
  * returned realm.
+ *
+ * Callers of this function need to hold mdsc->snap_rwsem.  However, if there's
+ * a need to do an inode lookup, this rwsem will be temporarily dropped.  Hence
+ * the 'retry' argument: if rwsem needs to be dropped and 'retry' is 'false'
+ * this function will return -EAGAIN; otherwise, the snaprealms walk-through
+ * will be restarted.
  */
 static struct ceph_snap_realm *get_quota_realm(struct ceph_mds_client *mdsc,
-                                              struct inode *inode)
+                                              struct inode *inode, bool retry)
 {
        struct ceph_inode_info *ci = NULL;
        struct ceph_snap_realm *realm, *next;
@@ -88,6 +205,7 @@ static struct ceph_snap_realm *get_quota_realm(struct ceph_mds_client *mdsc,
        if (ceph_snap(inode) != CEPH_NOSNAP)
                return NULL;
 
+restart:
        realm = ceph_inode(inode)->i_snap_realm;
        if (realm)
                ceph_get_snap_realm(mdsc, realm);
@@ -95,11 +213,25 @@ static struct ceph_snap_realm *get_quota_realm(struct ceph_mds_client *mdsc,
                pr_err_ratelimited("get_quota_realm: ino (%llx.%llx) "
                                   "null i_snap_realm\n", ceph_vinop(inode));
        while (realm) {
+               bool has_inode;
+
                spin_lock(&realm->inodes_with_caps_lock);
-               in = realm->inode ? igrab(realm->inode) : NULL;
+               has_inode = realm->inode;
+               in = has_inode ? igrab(realm->inode) : NULL;
                spin_unlock(&realm->inodes_with_caps_lock);
-               if (!in)
+               if (has_inode && !in)
                        break;
+               if (!in) {
+                       up_read(&mdsc->snap_rwsem);
+                       in = lookup_quotarealm_inode(mdsc, inode->i_sb, realm);
+                       down_read(&mdsc->snap_rwsem);
+                       if (IS_ERR_OR_NULL(in))
+                               break;
+                       ceph_put_snap_realm(mdsc, realm);
+                       if (!retry)
+                               return ERR_PTR(-EAGAIN);
+                       goto restart;
+               }
 
                ci = ceph_inode(in);
                has_quota = __ceph_has_any_quota(ci);
@@ -125,9 +257,22 @@ bool ceph_quota_is_same_realm(struct inode *old, struct inode *new)
        struct ceph_snap_realm *old_realm, *new_realm;
        bool is_same;
 
+restart:
+       /*
+        * We need to lookup 2 quota realms atomically, i.e. with snap_rwsem.
+        * However, get_quota_realm may drop it temporarily.  By setting the
+        * 'retry' parameter to 'false', we'll get -EAGAIN if the rwsem was
+        * dropped and we can then restart the whole operation.
+        */
        down_read(&mdsc->snap_rwsem);
-       old_realm = get_quota_realm(mdsc, old);
-       new_realm = get_quota_realm(mdsc, new);
+       old_realm = get_quota_realm(mdsc, old, true);
+       new_realm = get_quota_realm(mdsc, new, false);
+       if (PTR_ERR(new_realm) == -EAGAIN) {
+               up_read(&mdsc->snap_rwsem);
+               if (old_realm)
+                       ceph_put_snap_realm(mdsc, old_realm);
+               goto restart;
+       }
        is_same = (old_realm == new_realm);
        up_read(&mdsc->snap_rwsem);
 
@@ -166,6 +311,7 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
                return false;
 
        down_read(&mdsc->snap_rwsem);
+restart:
        realm = ceph_inode(inode)->i_snap_realm;
        if (realm)
                ceph_get_snap_realm(mdsc, realm);
@@ -173,12 +319,23 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
                pr_err_ratelimited("check_quota_exceeded: ino (%llx.%llx) "
                                   "null i_snap_realm\n", ceph_vinop(inode));
        while (realm) {
+               bool has_inode;
+
                spin_lock(&realm->inodes_with_caps_lock);
-               in = realm->inode ? igrab(realm->inode) : NULL;
+               has_inode = realm->inode;
+               in = has_inode ? igrab(realm->inode) : NULL;
                spin_unlock(&realm->inodes_with_caps_lock);
-               if (!in)
+               if (has_inode && !in)
                        break;
-
+               if (!in) {
+                       up_read(&mdsc->snap_rwsem);
+                       in = lookup_quotarealm_inode(mdsc, inode->i_sb, realm);
+                       down_read(&mdsc->snap_rwsem);
+                       if (IS_ERR_OR_NULL(in))
+                               break;
+                       ceph_put_snap_realm(mdsc, realm);
+                       goto restart;
+               }
                ci = ceph_inode(in);
                spin_lock(&ci->i_ceph_lock);
                if (op == QUOTA_CHECK_MAX_FILES_OP) {
@@ -314,7 +471,7 @@ bool ceph_quota_update_statfs(struct ceph_fs_client *fsc, struct kstatfs *buf)
        bool is_updated = false;
 
        down_read(&mdsc->snap_rwsem);
-       realm = get_quota_realm(mdsc, d_inode(fsc->sb->s_root));
+       realm = get_quota_realm(mdsc, d_inode(fsc->sb->s_root), true);
        up_read(&mdsc->snap_rwsem);
        if (!realm)
                return false;
index 285edda..c864b44 100644 (file)
@@ -845,6 +845,12 @@ static void ceph_umount_begin(struct super_block *sb)
        return;
 }
 
+static int ceph_remount(struct super_block *sb, int *flags, char *data)
+{
+       sync_filesystem(sb);
+       return 0;
+}
+
 static const struct super_operations ceph_super_ops = {
        .alloc_inode    = ceph_alloc_inode,
        .destroy_inode  = ceph_destroy_inode,
@@ -853,6 +859,7 @@ static const struct super_operations ceph_super_ops = {
        .drop_inode     = ceph_drop_inode,
        .sync_fs        = ceph_sync_fs,
        .put_super      = ceph_put_super,
+       .remount_fs     = ceph_remount,
        .show_options   = ceph_show_options,
        .statfs         = ceph_statfs,
        .umount_begin   = ceph_umount_begin,
index c5b4a05..6edab9a 100644 (file)
@@ -1083,6 +1083,7 @@ extern long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 
 /* export.c */
 extern const struct export_operations ceph_export_ops;
+struct inode *ceph_lookup_inode(struct super_block *sb, u64 ino);
 
 /* locks.c */
 extern __init void ceph_flock_init(void);
@@ -1133,5 +1134,6 @@ extern bool ceph_quota_is_max_bytes_approaching(struct inode *inode,
                                                loff_t newlen);
 extern bool ceph_quota_update_statfs(struct ceph_fs_client *fsc,
                                     struct kstatfs *buf);
+extern void ceph_cleanup_quotarealms_inodes(struct ceph_mds_client *mdsc);
 
 #endif /* _FS_CEPH_SUPER_H */
index 7ede730..1e21b25 100644 (file)
@@ -77,7 +77,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
                goto name_is_IP_address;
 
        /* Perform the upcall */
-       rc = dns_query(NULL, hostname, len, NULL, ip_addr, NULL);
+       rc = dns_query(NULL, hostname, len, NULL, ip_addr, NULL, false);
        if (rc < 0)
                cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n",
                         __func__, len, len, hostname);
index c5234c2..f2bb798 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/device.h>
 #include <linux/pid_namespace.h>
 #include <asm/io.h>
-#include <linux/poll.h>
 #include <linux/uaccess.h>
 
 #include <linux/coda.h>
index 591e82b..5e7932d 100644 (file)
@@ -1757,12 +1757,19 @@ int configfs_register_group(struct config_group *parent_group,
 
        inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
        ret = create_default_group(parent_group, group);
-       if (!ret) {
-               spin_lock(&configfs_dirent_lock);
-               configfs_dir_set_ready(group->cg_item.ci_dentry->d_fsdata);
-               spin_unlock(&configfs_dirent_lock);
-       }
+       if (ret)
+               goto err_out;
+
+       spin_lock(&configfs_dirent_lock);
+       configfs_dir_set_ready(group->cg_item.ci_dentry->d_fsdata);
+       spin_unlock(&configfs_dirent_lock);
+       inode_unlock(d_inode(parent));
+       return 0;
+err_out:
        inode_unlock(d_inode(parent));
+       mutex_lock(&subsys->su_mutex);
+       unlink_group(group);
+       mutex_unlock(&subsys->su_mutex);
        return ret;
 }
 EXPORT_SYMBOL(configfs_register_group);
index e5e54da..f743862 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -814,7 +814,7 @@ static void dax_entry_mkclean(struct address_space *mapping, pgoff_t index,
                                goto unlock_pmd;
 
                        flush_cache_page(vma, address, pfn);
-                       pmd = pmdp_huge_clear_flush(vma, address, pmdp);
+                       pmd = pmdp_invalidate(vma, address, pmdp);
                        pmd = pmd_wrprotect(pmd);
                        pmd = pmd_mkclean(pmd);
                        set_pmd_at(vma->vm_mm, address, pmdp, pmd);
@@ -1575,8 +1575,7 @@ static vm_fault_t dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp,
                }
 
                trace_dax_pmd_insert_mapping(inode, vmf, PMD_SIZE, pfn, entry);
-               result = vmf_insert_pfn_pmd(vma, vmf->address, vmf->pmd, pfn,
-                                           write);
+               result = vmf_insert_pfn_pmd(vmf, pfn, write);
                break;
        case IOMAP_UNWRITTEN:
        case IOMAP_HOLE:
@@ -1686,8 +1685,7 @@ dax_insert_pfn_mkwrite(struct vm_fault *vmf, pfn_t pfn, unsigned int order)
                ret = vmf_insert_mixed_mkwrite(vmf->vma, vmf->address, pfn);
 #ifdef CONFIG_FS_DAX_PMD
        else if (order == PMD_ORDER)
-               ret = vmf_insert_pfn_pmd(vmf->vma, vmf->address, vmf->pmd,
-                       pfn, true);
+               ret = vmf_insert_pfn_pmd(vmf, pfn, FAULT_FLAG_WRITE);
 #endif
        else
                ret = VM_FAULT_FALLBACK;
index 08d3bd6..93b1fa7 100644 (file)
@@ -21,6 +21,9 @@
 #include <linux/eventfd.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/idr.h>
+
+static DEFINE_IDA(eventfd_ida);
 
 struct eventfd_ctx {
        struct kref kref;
@@ -35,6 +38,7 @@ struct eventfd_ctx {
         */
        __u64 count;
        unsigned int flags;
+       int id;
 };
 
 /**
@@ -69,6 +73,8 @@ EXPORT_SYMBOL_GPL(eventfd_signal);
 
 static void eventfd_free_ctx(struct eventfd_ctx *ctx)
 {
+       if (ctx->id >= 0)
+               ida_simple_remove(&eventfd_ida, ctx->id);
        kfree(ctx);
 }
 
@@ -297,6 +303,7 @@ static void eventfd_show_fdinfo(struct seq_file *m, struct file *f)
        seq_printf(m, "eventfd-count: %16llx\n",
                   (unsigned long long)ctx->count);
        spin_unlock_irq(&ctx->wqh.lock);
+       seq_printf(m, "eventfd-id: %d\n", ctx->id);
 }
 #endif
 
@@ -400,6 +407,7 @@ static int do_eventfd(unsigned int count, int flags)
        init_waitqueue_head(&ctx->wqh);
        ctx->count = count;
        ctx->flags = flags;
+       ctx->id = ida_simple_get(&eventfd_ida, 0, 0, GFP_KERNEL);
 
        fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx,
                              O_RDWR | (flags & EFD_SHARED_FCNTL_FLAGS));
index 2e00333..d88584e 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1652,11 +1652,13 @@ int search_binary_handler(struct linux_binprm *bprm)
                if (!try_module_get(fmt->module))
                        continue;
                read_unlock(&binfmt_lock);
+
                bprm->recursion_depth++;
                retval = fmt->load_binary(bprm);
+               bprm->recursion_depth--;
+
                read_lock(&binfmt_lock);
                put_binfmt(fmt);
-               bprm->recursion_depth--;
                if (retval < 0 && !bprm->mm) {
                        /* we got to flush_old_exec() and failed after it */
                        read_unlock(&binfmt_lock);
index c27c273..e474127 100644 (file)
@@ -451,7 +451,9 @@ failed_out:
 /**
  *     ext2_alloc_branch - allocate and set up a chain of blocks.
  *     @inode: owner
- *     @num: depth of the chain (number of blocks to allocate)
+ *     @indirect_blks: depth of the chain (number of blocks to allocate)
+ *     @blks: number of allocated direct blocks
+ *     @goal: preferred place for allocation
  *     @offsets: offsets (in the blocks) to store the pointers to next.
  *     @branch: place to store the chain in.
  *
index 63e5995..217b290 100644 (file)
@@ -285,7 +285,7 @@ static int f2fs_acl_create_masq(struct posix_acl *acl, umode_t *mode_p)
        /* assert(atomic_read(acl->a_refcount) == 1); */
 
        FOREACH_ACL_ENTRY(pa, acl, pe) {
-               switch(pa->e_tag) {
+               switch (pa->e_tag) {
                case ACL_USER_OBJ:
                        pa->e_perm &= (mode >> 6) | ~S_IRWXO;
                        mode &= (pa->e_perm << 6) | ~S_IRWXU;
@@ -326,7 +326,7 @@ static int f2fs_acl_create_masq(struct posix_acl *acl, umode_t *mode_p)
        }
 
        *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
-        return not_equiv;
+       return not_equiv;
 }
 
 static int f2fs_acl_create(struct inode *dir, umode_t *mode,
index a98e1b0..ed70b68 100644 (file)
@@ -66,7 +66,7 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,
                .old_blkaddr = index,
                .new_blkaddr = index,
                .encrypted_page = NULL,
-               .is_meta = is_meta,
+               .is_por = !is_meta,
        };
        int err;
 
@@ -130,6 +130,30 @@ struct page *f2fs_get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index)
        return __get_meta_page(sbi, index, false);
 }
 
+static bool __is_bitmap_valid(struct f2fs_sb_info *sbi, block_t blkaddr,
+                                                       int type)
+{
+       struct seg_entry *se;
+       unsigned int segno, offset;
+       bool exist;
+
+       if (type != DATA_GENERIC_ENHANCE && type != DATA_GENERIC_ENHANCE_READ)
+               return true;
+
+       segno = GET_SEGNO(sbi, blkaddr);
+       offset = GET_BLKOFF_FROM_SEG0(sbi, blkaddr);
+       se = get_seg_entry(sbi, segno);
+
+       exist = f2fs_test_bit(offset, se->cur_valid_map);
+       if (!exist && type == DATA_GENERIC_ENHANCE) {
+               f2fs_msg(sbi->sb, KERN_ERR, "Inconsistent error "
+                       "blkaddr:%u, sit bitmap:%d", blkaddr, exist);
+               set_sbi_flag(sbi, SBI_NEED_FSCK);
+               WARN_ON(1);
+       }
+       return exist;
+}
+
 bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
                                        block_t blkaddr, int type)
 {
@@ -151,15 +175,22 @@ bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
                        return false;
                break;
        case META_POR:
+               if (unlikely(blkaddr >= MAX_BLKADDR(sbi) ||
+                       blkaddr < MAIN_BLKADDR(sbi)))
+                       return false;
+               break;
        case DATA_GENERIC:
+       case DATA_GENERIC_ENHANCE:
+       case DATA_GENERIC_ENHANCE_READ:
                if (unlikely(blkaddr >= MAX_BLKADDR(sbi) ||
-                       blkaddr < MAIN_BLKADDR(sbi))) {
-                       if (type == DATA_GENERIC) {
-                               f2fs_msg(sbi->sb, KERN_WARNING,
-                                       "access invalid blkaddr:%u", blkaddr);
-                               WARN_ON(1);
-                       }
+                               blkaddr < MAIN_BLKADDR(sbi))) {
+                       f2fs_msg(sbi->sb, KERN_WARNING,
+                               "access invalid blkaddr:%u", blkaddr);
+                       set_sbi_flag(sbi, SBI_NEED_FSCK);
+                       WARN_ON(1);
                        return false;
+               } else {
+                       return __is_bitmap_valid(sbi, blkaddr, type);
                }
                break;
        case META_GENERIC:
@@ -189,7 +220,7 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
                .op_flags = sync ? (REQ_META | REQ_PRIO) : REQ_RAHEAD,
                .encrypted_page = NULL,
                .in_list = false,
-               .is_meta = (type != META_POR),
+               .is_por = (type == META_POR),
        };
        struct blk_plug plug;
 
@@ -644,6 +675,12 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
        if (!is_set_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG))
                return 0;
 
+       if (bdev_read_only(sbi->sb->s_bdev)) {
+               f2fs_msg(sbi->sb, KERN_INFO, "write access "
+                       "unavailable, skipping orphan cleanup");
+               return 0;
+       }
+
        if (s_flags & SB_RDONLY) {
                f2fs_msg(sbi->sb, KERN_INFO, "orphan cleanup on readonly fs");
                sbi->sb->s_flags &= ~SB_RDONLY;
@@ -758,13 +795,27 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
        }
 }
 
+static __u32 f2fs_checkpoint_chksum(struct f2fs_sb_info *sbi,
+                                               struct f2fs_checkpoint *ckpt)
+{
+       unsigned int chksum_ofs = le32_to_cpu(ckpt->checksum_offset);
+       __u32 chksum;
+
+       chksum = f2fs_crc32(sbi, ckpt, chksum_ofs);
+       if (chksum_ofs < CP_CHKSUM_OFFSET) {
+               chksum_ofs += sizeof(chksum);
+               chksum = f2fs_chksum(sbi, chksum, (__u8 *)ckpt + chksum_ofs,
+                                               F2FS_BLKSIZE - chksum_ofs);
+       }
+       return chksum;
+}
+
 static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
                struct f2fs_checkpoint **cp_block, struct page **cp_page,
                unsigned long long *version)
 {
-       unsigned long blk_size = sbi->blocksize;
        size_t crc_offset = 0;
-       __u32 crc = 0;
+       __u32 crc;
 
        *cp_page = f2fs_get_meta_page(sbi, cp_addr);
        if (IS_ERR(*cp_page))
@@ -773,15 +824,27 @@ static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
        *cp_block = (struct f2fs_checkpoint *)page_address(*cp_page);
 
        crc_offset = le32_to_cpu((*cp_block)->checksum_offset);
-       if (crc_offset > (blk_size - sizeof(__le32))) {
+       if (crc_offset < CP_MIN_CHKSUM_OFFSET ||
+                       crc_offset > CP_CHKSUM_OFFSET) {
                f2fs_put_page(*cp_page, 1);
                f2fs_msg(sbi->sb, KERN_WARNING,
                        "invalid crc_offset: %zu", crc_offset);
                return -EINVAL;
        }
 
-       crc = cur_cp_crc(*cp_block);
-       if (!f2fs_crc_valid(sbi, crc, *cp_block, crc_offset)) {
+       if (__is_set_ckpt_flags(*cp_block, CP_LARGE_NAT_BITMAP_FLAG)) {
+               if (crc_offset != CP_MIN_CHKSUM_OFFSET) {
+                       f2fs_put_page(*cp_page, 1);
+                       f2fs_msg(sbi->sb, KERN_WARNING,
+                               "layout of large_nat_bitmap is deprecated, "
+                               "run fsck to repair, chksum_offset: %zu",
+                               crc_offset);
+                       return -EINVAL;
+               }
+       }
+
+       crc = f2fs_checkpoint_chksum(sbi, *cp_block);
+       if (crc != cur_cp_crc(*cp_block)) {
                f2fs_put_page(*cp_page, 1);
                f2fs_msg(sbi->sb, KERN_WARNING, "invalid crc value");
                return -EINVAL;
@@ -1009,13 +1072,11 @@ retry:
        if (inode) {
                unsigned long cur_ino = inode->i_ino;
 
-               if (is_dir)
-                       F2FS_I(inode)->cp_task = current;
+               F2FS_I(inode)->cp_task = current;
 
                filemap_fdatawrite(inode->i_mapping);
 
-               if (is_dir)
-                       F2FS_I(inode)->cp_task = NULL;
+               F2FS_I(inode)->cp_task = NULL;
 
                iput(inode);
                /* We need to give cpu to another writers. */
@@ -1391,7 +1452,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
        get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP));
        get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP));
 
-       crc32 = f2fs_crc32(sbi, ckpt, le32_to_cpu(ckpt->checksum_offset));
+       crc32 = f2fs_checkpoint_chksum(sbi, ckpt);
        *((__le32 *)((unsigned char *)ckpt +
                                le32_to_cpu(ckpt->checksum_offset)))
                                = cpu_to_le32(crc32);
@@ -1475,7 +1536,11 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
        clear_sbi_flag(sbi, SBI_IS_DIRTY);
        clear_sbi_flag(sbi, SBI_NEED_CP);
        clear_sbi_flag(sbi, SBI_QUOTA_SKIP_FLUSH);
+
+       spin_lock(&sbi->stat_lock);
        sbi->unusable_block_count = 0;
+       spin_unlock(&sbi->stat_lock);
+
        __set_cp_next_pack(sbi);
 
        /*
@@ -1500,6 +1565,9 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
        unsigned long long ckpt_ver;
        int err = 0;
 
+       if (f2fs_readonly(sbi->sb) || f2fs_hw_is_readonly(sbi))
+               return -EROFS;
+
        if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
                if (cpc->reason != CP_PAUSE)
                        return 0;
@@ -1516,10 +1584,6 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
                err = -EIO;
                goto out;
        }
-       if (f2fs_readonly(sbi->sb)) {
-               err = -EROFS;
-               goto out;
-       }
 
        trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "start block_ops");
 
index 64040e9..eda4181 100644 (file)
@@ -218,12 +218,14 @@ struct block_device *f2fs_target_device(struct f2fs_sb_info *sbi,
        struct block_device *bdev = sbi->sb->s_bdev;
        int i;
 
-       for (i = 0; i < sbi->s_ndevs; i++) {
-               if (FDEV(i).start_blk <= blk_addr &&
-                                       FDEV(i).end_blk >= blk_addr) {
-                       blk_addr -= FDEV(i).start_blk;
-                       bdev = FDEV(i).bdev;
-                       break;
+       if (f2fs_is_multi_device(sbi)) {
+               for (i = 0; i < sbi->s_ndevs; i++) {
+                       if (FDEV(i).start_blk <= blk_addr &&
+                           FDEV(i).end_blk >= blk_addr) {
+                               blk_addr -= FDEV(i).start_blk;
+                               bdev = FDEV(i).bdev;
+                               break;
+                       }
                }
        }
        if (bio) {
@@ -237,6 +239,9 @@ int f2fs_target_device_index(struct f2fs_sb_info *sbi, block_t blkaddr)
 {
        int i;
 
+       if (!f2fs_is_multi_device(sbi))
+               return 0;
+
        for (i = 0; i < sbi->s_ndevs; i++)
                if (FDEV(i).start_blk <= blkaddr && FDEV(i).end_blk >= blkaddr)
                        return i;
@@ -420,7 +425,7 @@ static void __submit_merged_write_cond(struct f2fs_sb_info *sbi,
 
 void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type)
 {
-       __submit_merged_write_cond(sbi, NULL, 0, 0, type, true);
+       __submit_merged_write_cond(sbi, NULL, NULL, 0, type, true);
 }
 
 void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
@@ -448,7 +453,8 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
                        fio->encrypted_page : fio->page;
 
        if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr,
-                       __is_meta_io(fio) ? META_GENERIC : DATA_GENERIC))
+                       fio->is_por ? META_POR : (__is_meta_io(fio) ?
+                       META_GENERIC : DATA_GENERIC_ENHANCE)))
                return -EFAULT;
 
        trace_f2fs_submit_page_bio(page, fio);
@@ -498,9 +504,7 @@ next:
                spin_unlock(&io->io_lock);
        }
 
-       if (__is_valid_data_blkaddr(fio->old_blkaddr))
-               verify_block_addr(fio, fio->old_blkaddr);
-       verify_block_addr(fio, fio->new_blkaddr);
+       verify_fio_blkaddr(fio);
 
        bio_page = fio->encrypted_page ? fio->encrypted_page : fio->page;
 
@@ -557,9 +561,6 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
        struct bio_post_read_ctx *ctx;
        unsigned int post_read_steps = 0;
 
-       if (!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC))
-               return ERR_PTR(-EFAULT);
-
        bio = f2fs_bio_alloc(sbi, min_t(int, nr_pages, BIO_MAX_PAGES), false);
        if (!bio)
                return ERR_PTR(-ENOMEM);
@@ -587,8 +588,10 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
 static int f2fs_submit_page_read(struct inode *inode, struct page *page,
                                                        block_t blkaddr)
 {
-       struct bio *bio = f2fs_grab_read_bio(inode, blkaddr, 1, 0);
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       struct bio *bio;
 
+       bio = f2fs_grab_read_bio(inode, blkaddr, 1, 0);
        if (IS_ERR(bio))
                return PTR_ERR(bio);
 
@@ -600,8 +603,8 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page,
                return -EFAULT;
        }
        ClearPageError(page);
-       inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
-       __submit_bio(F2FS_I_SB(inode), bio, DATA);
+       inc_page_count(sbi, F2FS_RD_DATA);
+       __submit_bio(sbi, bio, DATA);
        return 0;
 }
 
@@ -729,6 +732,11 @@ struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
 
        if (f2fs_lookup_extent_cache(inode, index, &ei)) {
                dn.data_blkaddr = ei.blk + index - ei.fofs;
+               if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), dn.data_blkaddr,
+                                               DATA_GENERIC_ENHANCE_READ)) {
+                       err = -EFAULT;
+                       goto put_err;
+               }
                goto got_it;
        }
 
@@ -742,6 +750,13 @@ struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
                err = -ENOENT;
                goto put_err;
        }
+       if (dn.data_blkaddr != NEW_ADDR &&
+                       !f2fs_is_valid_blkaddr(F2FS_I_SB(inode),
+                                               dn.data_blkaddr,
+                                               DATA_GENERIC_ENHANCE)) {
+               err = -EFAULT;
+               goto put_err;
+       }
 got_it:
        if (PageUptodate(page)) {
                unlock_page(page);
@@ -1084,12 +1099,12 @@ next_block:
        blkaddr = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node);
 
        if (__is_valid_data_blkaddr(blkaddr) &&
-               !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC)) {
+               !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) {
                err = -EFAULT;
                goto sync_out;
        }
 
-       if (is_valid_data_blkaddr(sbi, blkaddr)) {
+       if (__is_valid_data_blkaddr(blkaddr)) {
                /* use out-place-update for driect IO under LFS mode */
                if (test_opt(sbi, LFS) && flag == F2FS_GET_BLOCK_DIO &&
                                                        map->m_may_create) {
@@ -1499,6 +1514,118 @@ out:
        return ret;
 }
 
+static int f2fs_read_single_page(struct inode *inode, struct page *page,
+                                       unsigned nr_pages,
+                                       struct f2fs_map_blocks *map,
+                                       struct bio **bio_ret,
+                                       sector_t *last_block_in_bio,
+                                       bool is_readahead)
+{
+       struct bio *bio = *bio_ret;
+       const unsigned blkbits = inode->i_blkbits;
+       const unsigned blocksize = 1 << blkbits;
+       sector_t block_in_file;
+       sector_t last_block;
+       sector_t last_block_in_file;
+       sector_t block_nr;
+       int ret = 0;
+
+       block_in_file = (sector_t)page->index;
+       last_block = block_in_file + nr_pages;
+       last_block_in_file = (i_size_read(inode) + blocksize - 1) >>
+                                                       blkbits;
+       if (last_block > last_block_in_file)
+               last_block = last_block_in_file;
+
+       /* just zeroing out page which is beyond EOF */
+       if (block_in_file >= last_block)
+               goto zero_out;
+       /*
+        * Map blocks using the previous result first.
+        */
+       if ((map->m_flags & F2FS_MAP_MAPPED) &&
+                       block_in_file > map->m_lblk &&
+                       block_in_file < (map->m_lblk + map->m_len))
+               goto got_it;
+
+       /*
+        * Then do more f2fs_map_blocks() calls until we are
+        * done with this page.
+        */
+       map->m_lblk = block_in_file;
+       map->m_len = last_block - block_in_file;
+
+       ret = f2fs_map_blocks(inode, map, 0, F2FS_GET_BLOCK_DEFAULT);
+       if (ret)
+               goto out;
+got_it:
+       if ((map->m_flags & F2FS_MAP_MAPPED)) {
+               block_nr = map->m_pblk + block_in_file - map->m_lblk;
+               SetPageMappedToDisk(page);
+
+               if (!PageUptodate(page) && !cleancache_get_page(page)) {
+                       SetPageUptodate(page);
+                       goto confused;
+               }
+
+               if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), block_nr,
+                                               DATA_GENERIC_ENHANCE_READ)) {
+                       ret = -EFAULT;
+                       goto out;
+               }
+       } else {
+zero_out:
+               zero_user_segment(page, 0, PAGE_SIZE);
+               if (!PageUptodate(page))
+                       SetPageUptodate(page);
+               unlock_page(page);
+               goto out;
+       }
+
+       /*
+        * This page will go to BIO.  Do we need to send this
+        * BIO off first?
+        */
+       if (bio && (*last_block_in_bio != block_nr - 1 ||
+               !__same_bdev(F2FS_I_SB(inode), block_nr, bio))) {
+submit_and_realloc:
+               __submit_bio(F2FS_I_SB(inode), bio, DATA);
+               bio = NULL;
+       }
+       if (bio == NULL) {
+               bio = f2fs_grab_read_bio(inode, block_nr, nr_pages,
+                               is_readahead ? REQ_RAHEAD : 0);
+               if (IS_ERR(bio)) {
+                       ret = PTR_ERR(bio);
+                       bio = NULL;
+                       goto out;
+               }
+       }
+
+       /*
+        * If the page is under writeback, we need to wait for
+        * its completion to see the correct decrypted data.
+        */
+       f2fs_wait_on_block_writeback(inode, block_nr);
+
+       if (bio_add_page(bio, page, blocksize, 0) < blocksize)
+               goto submit_and_realloc;
+
+       inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
+       ClearPageError(page);
+       *last_block_in_bio = block_nr;
+       goto out;
+confused:
+       if (bio) {
+               __submit_bio(F2FS_I_SB(inode), bio, DATA);
+               bio = NULL;
+       }
+       unlock_page(page);
+out:
+       *bio_ret = bio;
+       return ret;
+}
+
 /*
  * This function was originally taken from fs/mpage.c, and customized for f2fs.
  * Major change was from block_size == page_size in f2fs by default.
@@ -1515,13 +1642,8 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
        struct bio *bio = NULL;
        sector_t last_block_in_bio = 0;
        struct inode *inode = mapping->host;
-       const unsigned blkbits = inode->i_blkbits;
-       const unsigned blocksize = 1 << blkbits;
-       sector_t block_in_file;
-       sector_t last_block;
-       sector_t last_block_in_file;
-       sector_t block_nr;
        struct f2fs_map_blocks map;
+       int ret = 0;
 
        map.m_pblk = 0;
        map.m_lblk = 0;
@@ -1544,98 +1666,13 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
                                goto next_page;
                }
 
-               block_in_file = (sector_t)page->index;
-               last_block = block_in_file + nr_pages;
-               last_block_in_file = (i_size_read(inode) + blocksize - 1) >>
-                                                               blkbits;
-               if (last_block > last_block_in_file)
-                       last_block = last_block_in_file;
-
-               /* just zeroing out page which is beyond EOF */
-               if (block_in_file >= last_block)
-                       goto zero_out;
-               /*
-                * Map blocks using the previous result first.
-                */
-               if ((map.m_flags & F2FS_MAP_MAPPED) &&
-                               block_in_file > map.m_lblk &&
-                               block_in_file < (map.m_lblk + map.m_len))
-                       goto got_it;
-
-               /*
-                * Then do more f2fs_map_blocks() calls until we are
-                * done with this page.
-                */
-               map.m_lblk = block_in_file;
-               map.m_len = last_block - block_in_file;
-
-               if (f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_DEFAULT))
-                       goto set_error_page;
-got_it:
-               if ((map.m_flags & F2FS_MAP_MAPPED)) {
-                       block_nr = map.m_pblk + block_in_file - map.m_lblk;
-                       SetPageMappedToDisk(page);
-
-                       if (!PageUptodate(page) && !cleancache_get_page(page)) {
-                               SetPageUptodate(page);
-                               goto confused;
-                       }
-
-                       if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), block_nr,
-                                                               DATA_GENERIC))
-                               goto set_error_page;
-               } else {
-zero_out:
+               ret = f2fs_read_single_page(inode, page, nr_pages, &map, &bio,
+                                       &last_block_in_bio, is_readahead);
+               if (ret) {
+                       SetPageError(page);
                        zero_user_segment(page, 0, PAGE_SIZE);
-                       if (!PageUptodate(page))
-                               SetPageUptodate(page);
                        unlock_page(page);
-                       goto next_page;
                }
-
-               /*
-                * This page will go to BIO.  Do we need to send this
-                * BIO off first?
-                */
-               if (bio && (last_block_in_bio != block_nr - 1 ||
-                       !__same_bdev(F2FS_I_SB(inode), block_nr, bio))) {
-submit_and_realloc:
-                       __submit_bio(F2FS_I_SB(inode), bio, DATA);
-                       bio = NULL;
-               }
-               if (bio == NULL) {
-                       bio = f2fs_grab_read_bio(inode, block_nr, nr_pages,
-                                       is_readahead ? REQ_RAHEAD : 0);
-                       if (IS_ERR(bio)) {
-                               bio = NULL;
-                               goto set_error_page;
-                       }
-               }
-
-               /*
-                * If the page is under writeback, we need to wait for
-                * its completion to see the correct decrypted data.
-                */
-               f2fs_wait_on_block_writeback(inode, block_nr);
-
-               if (bio_add_page(bio, page, blocksize, 0) < blocksize)
-                       goto submit_and_realloc;
-
-               inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA);
-               ClearPageError(page);
-               last_block_in_bio = block_nr;
-               goto next_page;
-set_error_page:
-               SetPageError(page);
-               zero_user_segment(page, 0, PAGE_SIZE);
-               unlock_page(page);
-               goto next_page;
-confused:
-               if (bio) {
-                       __submit_bio(F2FS_I_SB(inode), bio, DATA);
-                       bio = NULL;
-               }
-               unlock_page(page);
 next_page:
                if (pages)
                        put_page(page);
@@ -1643,7 +1680,7 @@ next_page:
        BUG_ON(pages && !list_empty(pages));
        if (bio)
                __submit_bio(F2FS_I_SB(inode), bio, DATA);
-       return 0;
+       return pages ? 0 : ret;
 }
 
 static int f2fs_read_data_page(struct file *file, struct page *page)
@@ -1813,7 +1850,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
                fio->old_blkaddr = ei.blk + page->index - ei.fofs;
 
                if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
-                                                       DATA_GENERIC))
+                                               DATA_GENERIC_ENHANCE))
                        return -EFAULT;
 
                ipu_force = true;
@@ -1840,7 +1877,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
 got_it:
        if (__is_valid_data_blkaddr(fio->old_blkaddr) &&
                !f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
-                                                       DATA_GENERIC)) {
+                                               DATA_GENERIC_ENHANCE)) {
                err = -EFAULT;
                goto out_writepage;
        }
@@ -1848,7 +1885,8 @@ got_it:
         * If current allocation needs SSR,
         * it had better in-place writes for updated data.
         */
-       if (ipu_force || (is_valid_data_blkaddr(fio->sbi, fio->old_blkaddr) &&
+       if (ipu_force ||
+               (__is_valid_data_blkaddr(fio->old_blkaddr) &&
                                        need_inplace_update(fio))) {
                err = encrypt_one_page(fio);
                if (err)
@@ -1866,9 +1904,10 @@ got_it:
                                                                        true);
                        if (PageWriteback(page))
                                end_page_writeback(page);
+               } else {
+                       set_inode_flag(inode, FI_UPDATE_WRITE);
                }
                trace_f2fs_do_write_data_page(fio->page, IPU);
-               set_inode_flag(inode, FI_UPDATE_WRITE);
                return err;
        }
 
@@ -2030,7 +2069,8 @@ out:
        }
 
        unlock_page(page);
-       if (!S_ISDIR(inode->i_mode) && !IS_NOQUOTA(inode))
+       if (!S_ISDIR(inode->i_mode) && !IS_NOQUOTA(inode) &&
+                                       !F2FS_I(inode)->cp_task)
                f2fs_balance_fs(sbi, need_balance_fs);
 
        if (unlikely(f2fs_cp_error(sbi))) {
@@ -2491,6 +2531,11 @@ repeat:
                zero_user_segment(page, 0, PAGE_SIZE);
                SetPageUptodate(page);
        } else {
+               if (!f2fs_is_valid_blkaddr(sbi, blkaddr,
+                               DATA_GENERIC_ENHANCE_READ)) {
+                       err = -EFAULT;
+                       goto fail;
+               }
                err = f2fs_submit_page_read(inode, page, blkaddr);
                if (err)
                        goto fail;
index bacf5c2..06b89a9 100644 (file)
@@ -210,7 +210,14 @@ enum {
        META_SSA,
        META_MAX,
        META_POR,
-       DATA_GENERIC,
+       DATA_GENERIC,           /* check range only */
+       DATA_GENERIC_ENHANCE,   /* strong check on range and segment bitmap */
+       DATA_GENERIC_ENHANCE_READ,      /*
+                                        * strong check on range and segment
+                                        * bitmap but no warning due to race
+                                        * condition of read on truncated area
+                                        * by extent_cache
+                                        */
        META_GENERIC,
 };
 
@@ -1041,7 +1048,7 @@ struct f2fs_io_info {
        bool submitted;         /* indicate IO submission */
        int need_lock;          /* indicate we need to lock cp_rwsem */
        bool in_list;           /* indicate fio is in io_list */
-       bool is_meta;           /* indicate borrow meta inode mapping or not */
+       bool is_por;            /* indicate IO is from recovery or not */
        bool retry;             /* need to reallocate block address */
        enum iostat_type io_type;       /* io type */
        struct writeback_control *io_wbc; /* writeback control */
@@ -1068,8 +1075,8 @@ struct f2fs_dev_info {
        block_t start_blk;
        block_t end_blk;
 #ifdef CONFIG_BLK_DEV_ZONED
-       unsigned int nr_blkz;                   /* Total number of zones */
-       u8 *blkz_type;                          /* Array of zones type */
+       unsigned int nr_blkz;           /* Total number of zones */
+       unsigned long *blkz_seq;        /* Bitmap indicating sequential zones */
 #endif
 };
 
@@ -1366,6 +1373,17 @@ static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type)
 }
 #endif
 
+/*
+ * Test if the mounted volume is a multi-device volume.
+ *   - For a single regular disk volume, sbi->s_ndevs is 0.
+ *   - For a single zoned disk volume, sbi->s_ndevs is 1.
+ *   - For a multi-device volume, sbi->s_ndevs is always 2 or more.
+ */
+static inline bool f2fs_is_multi_device(struct f2fs_sb_info *sbi)
+{
+       return sbi->s_ndevs > 1;
+}
+
 /* For write statistics. Suppose sector size is 512 bytes,
  * and the return value is in kbytes. s is of struct f2fs_sb_info.
  */
@@ -1777,6 +1795,7 @@ enospc:
        return -ENOSPC;
 }
 
+void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...);
 static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,
                                                struct inode *inode,
                                                block_t count)
@@ -1785,13 +1804,21 @@ static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,
 
        spin_lock(&sbi->stat_lock);
        f2fs_bug_on(sbi, sbi->total_valid_block_count < (block_t) count);
-       f2fs_bug_on(sbi, inode->i_blocks < sectors);
        sbi->total_valid_block_count -= (block_t)count;
        if (sbi->reserved_blocks &&
                sbi->current_reserved_blocks < sbi->reserved_blocks)
                sbi->current_reserved_blocks = min(sbi->reserved_blocks,
                                        sbi->current_reserved_blocks + count);
        spin_unlock(&sbi->stat_lock);
+       if (unlikely(inode->i_blocks < sectors)) {
+               f2fs_msg(sbi->sb, KERN_WARNING,
+                       "Inconsistent i_blocks, ino:%lu, iblocks:%llu, sectors:%llu",
+                       inode->i_ino,
+                       (unsigned long long)inode->i_blocks,
+                       (unsigned long long)sectors);
+               set_sbi_flag(sbi, SBI_NEED_FSCK);
+               return;
+       }
        f2fs_i_blocks_write(inode, count, false, true);
 }
 
@@ -1889,7 +1916,11 @@ static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
        if (is_set_ckpt_flags(sbi, CP_LARGE_NAT_BITMAP_FLAG)) {
                offset = (flag == SIT_BITMAP) ?
                        le32_to_cpu(ckpt->nat_ver_bitmap_bytesize) : 0;
-               return &ckpt->sit_nat_version_bitmap + offset;
+               /*
+                * if large_nat_bitmap feature is enabled, leave checksum
+                * protection for all nat/sit bitmaps.
+                */
+               return &ckpt->sit_nat_version_bitmap + offset + sizeof(__le32);
        }
 
        if (__cp_payload(sbi) > 0) {
@@ -2008,7 +2039,6 @@ static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
 
        f2fs_bug_on(sbi, !sbi->total_valid_block_count);
        f2fs_bug_on(sbi, !sbi->total_valid_node_count);
-       f2fs_bug_on(sbi, !is_inode && !inode->i_blocks);
 
        sbi->total_valid_node_count--;
        sbi->total_valid_block_count--;
@@ -2018,10 +2048,19 @@ static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
 
        spin_unlock(&sbi->stat_lock);
 
-       if (is_inode)
+       if (is_inode) {
                dquot_free_inode(inode);
-       else
+       } else {
+               if (unlikely(inode->i_blocks == 0)) {
+                       f2fs_msg(sbi->sb, KERN_WARNING,
+                               "Inconsistent i_blocks, ino:%lu, iblocks:%llu",
+                               inode->i_ino,
+                               (unsigned long long)inode->i_blocks);
+                       set_sbi_flag(sbi, SBI_NEED_FSCK);
+                       return;
+               }
                f2fs_i_blocks_write(inode, 1, false, true);
+       }
 }
 
 static inline unsigned int valid_node_count(struct f2fs_sb_info *sbi)
@@ -2545,7 +2584,14 @@ static inline int f2fs_has_inline_xattr(struct inode *inode)
 
 static inline unsigned int addrs_per_inode(struct inode *inode)
 {
-       return CUR_ADDRS_PER_INODE(inode) - get_inline_xattr_addrs(inode);
+       unsigned int addrs = CUR_ADDRS_PER_INODE(inode) -
+                               get_inline_xattr_addrs(inode);
+       return ALIGN_DOWN(addrs, 1);
+}
+
+static inline unsigned int addrs_per_block(struct inode *inode)
+{
+       return ALIGN_DOWN(DEF_ADDRS_PER_BLOCK, 1);
 }
 
 static inline void *inline_xattr_addr(struct inode *inode, struct page *page)
@@ -2558,7 +2604,9 @@ static inline void *inline_xattr_addr(struct inode *inode, struct page *page)
 
 static inline int inline_xattr_size(struct inode *inode)
 {
-       return get_inline_xattr_addrs(inode) * sizeof(__le32);
+       if (f2fs_has_inline_xattr(inode))
+               return get_inline_xattr_addrs(inode) * sizeof(__le32);
+       return 0;
 }
 
 static inline int f2fs_has_inline_data(struct inode *inode)
@@ -2800,12 +2848,10 @@ static inline void f2fs_update_iostat(struct f2fs_sb_info *sbi,
 
 #define __is_large_section(sbi)                ((sbi)->segs_per_sec > 1)
 
-#define __is_meta_io(fio) (PAGE_TYPE_OF_BIO((fio)->type) == META &&    \
-                               (!is_read_io((fio)->op) || (fio)->is_meta))
+#define __is_meta_io(fio) (PAGE_TYPE_OF_BIO((fio)->type) == META)
 
 bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
                                        block_t blkaddr, int type);
-void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...);
 static inline void verify_blkaddr(struct f2fs_sb_info *sbi,
                                        block_t blkaddr, int type)
 {
@@ -2824,15 +2870,6 @@ static inline bool __is_valid_data_blkaddr(block_t blkaddr)
        return true;
 }
 
-static inline bool is_valid_data_blkaddr(struct f2fs_sb_info *sbi,
-                                               block_t blkaddr)
-{
-       if (!__is_valid_data_blkaddr(blkaddr))
-               return false;
-       verify_blkaddr(sbi, blkaddr, DATA_GENERIC);
-       return true;
-}
-
 static inline void f2fs_set_page_private(struct page *page,
                                                unsigned long data)
 {
@@ -3530,16 +3567,12 @@ F2FS_FEATURE_FUNCS(lost_found, LOST_FOUND);
 F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM);
 
 #ifdef CONFIG_BLK_DEV_ZONED
-static inline int get_blkz_type(struct f2fs_sb_info *sbi,
-                       struct block_device *bdev, block_t blkaddr)
+static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi,
+                                   block_t blkaddr)
 {
        unsigned int zno = blkaddr >> sbi->log_blocks_per_blkz;
-       int i;
 
-       for (i = 0; i < sbi->s_ndevs; i++)
-               if (FDEV(i).bdev == bdev)
-                       return FDEV(i).blkz_type[zno];
-       return -EINVAL;
+       return test_bit(zno, FDEV(devi).blkz_seq);
 }
 #endif
 
@@ -3548,9 +3581,23 @@ static inline bool f2fs_hw_should_discard(struct f2fs_sb_info *sbi)
        return f2fs_sb_has_blkzoned(sbi);
 }
 
+static inline bool f2fs_bdev_support_discard(struct block_device *bdev)
+{
+       return blk_queue_discard(bdev_get_queue(bdev)) ||
+              bdev_is_zoned(bdev);
+}
+
 static inline bool f2fs_hw_support_discard(struct f2fs_sb_info *sbi)
 {
-       return blk_queue_discard(bdev_get_queue(sbi->sb->s_bdev));
+       int i;
+
+       if (!f2fs_is_multi_device(sbi))
+               return f2fs_bdev_support_discard(sbi->sb->s_bdev);
+
+       for (i = 0; i < sbi->s_ndevs; i++)
+               if (f2fs_bdev_support_discard(FDEV(i).bdev))
+                       return true;
+       return false;
 }
 
 static inline bool f2fs_realtime_discard_enable(struct f2fs_sb_info *sbi)
@@ -3559,6 +3606,20 @@ static inline bool f2fs_realtime_discard_enable(struct f2fs_sb_info *sbi)
                                        f2fs_hw_should_discard(sbi);
 }
 
+static inline bool f2fs_hw_is_readonly(struct f2fs_sb_info *sbi)
+{
+       int i;
+
+       if (!f2fs_is_multi_device(sbi))
+               return bdev_read_only(sbi->sb->s_bdev);
+
+       for (i = 0; i < sbi->s_ndevs; i++)
+               if (bdev_read_only(FDEV(i).bdev))
+                       return true;
+       return false;
+}
+
+
 static inline void set_opt_mode(struct f2fs_sb_info *sbi, unsigned int mt)
 {
        clear_opt(sbi, ADAPTIVE);
@@ -3614,7 +3675,7 @@ static inline bool f2fs_force_buffered_io(struct inode *inode,
 
        if (f2fs_post_read_required(inode))
                return true;
-       if (sbi->s_ndevs)
+       if (f2fs_is_multi_device(sbi))
                return true;
        /*
         * for blkzoned device, fallback direct IO to buffered IO, so
@@ -3651,4 +3712,4 @@ static inline bool is_journalled_quota(struct f2fs_sb_info *sbi)
        return false;
 }
 
-#endif
+#endif /* _LINUX_F2FS_H */
index 5742ab8..45b45f3 100644 (file)
@@ -39,6 +39,8 @@ static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf)
        ret = filemap_fault(vmf);
        up_read(&F2FS_I(inode)->i_mmap_sem);
 
+       trace_f2fs_filemap_fault(inode, vmf->pgoff, (unsigned long)ret);
+
        return ret;
 }
 
@@ -356,7 +358,7 @@ static bool __found_offset(struct f2fs_sb_info *sbi, block_t blkaddr,
        switch (whence) {
        case SEEK_DATA:
                if ((blkaddr == NEW_ADDR && dirty == pgofs) ||
-                       is_valid_data_blkaddr(sbi, blkaddr))
+                       __is_valid_data_blkaddr(blkaddr))
                        return true;
                break;
        case SEEK_HOLE:
@@ -422,7 +424,7 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
 
                        if (__is_valid_data_blkaddr(blkaddr) &&
                                !f2fs_is_valid_blkaddr(F2FS_I_SB(inode),
-                                               blkaddr, DATA_GENERIC)) {
+                                       blkaddr, DATA_GENERIC_ENHANCE)) {
                                f2fs_put_dnode(&dn);
                                goto fail;
                        }
@@ -523,7 +525,8 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count)
                f2fs_set_data_blkaddr(dn);
 
                if (__is_valid_data_blkaddr(blkaddr) &&
-                       !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC))
+                       !f2fs_is_valid_blkaddr(sbi, blkaddr,
+                                       DATA_GENERIC_ENHANCE))
                        continue;
 
                f2fs_invalidate_blocks(sbi, blkaddr);
@@ -552,7 +555,7 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count)
 
 void f2fs_truncate_data_blocks(struct dnode_of_data *dn)
 {
-       f2fs_truncate_data_blocks_range(dn, ADDRS_PER_BLOCK);
+       f2fs_truncate_data_blocks_range(dn, ADDRS_PER_BLOCK(dn->inode));
 }
 
 static int truncate_partial_data_page(struct inode *inode, u64 from,
@@ -1006,7 +1009,8 @@ next_dnode:
        } else if (ret == -ENOENT) {
                if (dn.max_level == 0)
                        return -ENOENT;
-               done = min((pgoff_t)ADDRS_PER_BLOCK - dn.ofs_in_node, len);
+               done = min((pgoff_t)ADDRS_PER_BLOCK(inode) - dn.ofs_in_node,
+                                                                       len);
                blkaddr += done;
                do_replace += done;
                goto next;
@@ -1017,6 +1021,14 @@ next_dnode:
        for (i = 0; i < done; i++, blkaddr++, do_replace++, dn.ofs_in_node++) {
                *blkaddr = datablock_addr(dn.inode,
                                        dn.node_page, dn.ofs_in_node);
+
+               if (__is_valid_data_blkaddr(*blkaddr) &&
+                       !f2fs_is_valid_blkaddr(sbi, *blkaddr,
+                                       DATA_GENERIC_ENHANCE)) {
+                       f2fs_put_dnode(&dn);
+                       return -EFAULT;
+               }
+
                if (!f2fs_is_checkpointed_data(sbi, *blkaddr)) {
 
                        if (test_opt(sbi, LFS)) {
@@ -1157,7 +1169,7 @@ static int __exchange_data_block(struct inode *src_inode,
        int ret;
 
        while (len) {
-               olen = min((pgoff_t)4 * ADDRS_PER_BLOCK, len);
+               olen = min((pgoff_t)4 * ADDRS_PER_BLOCK(src_inode), len);
 
                src_blkaddr = f2fs_kvzalloc(F2FS_I_SB(src_inode),
                                        array_size(olen, sizeof(block_t)),
@@ -2573,10 +2585,10 @@ static int f2fs_ioc_flush_device(struct file *filp, unsigned long arg)
                                                        sizeof(range)))
                return -EFAULT;
 
-       if (sbi->s_ndevs <= 1 || sbi->s_ndevs - 1 <= range.dev_num ||
+       if (!f2fs_is_multi_device(sbi) || sbi->s_ndevs - 1 <= range.dev_num ||
                        __is_large_section(sbi)) {
                f2fs_msg(sbi->sb, KERN_WARNING,
-                       "Can't flush %u in %d for segs_per_sec %u != 1\n",
+                       "Can't flush %u in %d for segs_per_sec %u != 1",
                                range.dev_num, sbi->s_ndevs,
                                sbi->segs_per_sec);
                return -EINVAL;
@@ -2858,7 +2870,7 @@ int f2fs_pin_file_control(struct inode *inode, bool inc)
 
        if (fi->i_gc_failures[GC_FAILURE_PIN] > sbi->gc_pin_file_threshold) {
                f2fs_msg(sbi->sb, KERN_WARNING,
-                       "%s: Enable GC = ino %lx after %x GC trials\n",
+                       "%s: Enable GC = ino %lx after %x GC trials",
                        __func__, inode->i_ino,
                        fi->i_gc_failures[GC_FAILURE_PIN]);
                clear_inode_flag(inode, FI_PIN_FILE);
@@ -3035,15 +3047,21 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        struct inode *inode = file_inode(file);
        ssize_t ret;
 
-       if (unlikely(f2fs_cp_error(F2FS_I_SB(inode))))
-               return -EIO;
+       if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) {
+               ret = -EIO;
+               goto out;
+       }
 
-       if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT))
-               return -EINVAL;
+       if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT)) {
+               ret = -EINVAL;
+               goto out;
+       }
 
        if (!inode_trylock(inode)) {
-               if (iocb->ki_flags & IOCB_NOWAIT)
-                       return -EAGAIN;
+               if (iocb->ki_flags & IOCB_NOWAIT) {
+                       ret = -EAGAIN;
+                       goto out;
+               }
                inode_lock(inode);
        }
 
@@ -3056,19 +3074,16 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
                if (iov_iter_fault_in_readable(from, iov_iter_count(from)))
                        set_inode_flag(inode, FI_NO_PREALLOC);
 
-               if ((iocb->ki_flags & IOCB_NOWAIT) &&
-                       (iocb->ki_flags & IOCB_DIRECT)) {
-                               if (!f2fs_overwrite_io(inode, iocb->ki_pos,
+               if ((iocb->ki_flags & IOCB_NOWAIT)) {
+                       if (!f2fs_overwrite_io(inode, iocb->ki_pos,
                                                iov_iter_count(from)) ||
-                                       f2fs_has_inline_data(inode) ||
-                                       f2fs_force_buffered_io(inode,
-                                                       iocb, from)) {
-                                               clear_inode_flag(inode,
-                                                               FI_NO_PREALLOC);
-                                               inode_unlock(inode);
-                                               return -EAGAIN;
-                               }
-
+                               f2fs_has_inline_data(inode) ||
+                               f2fs_force_buffered_io(inode, iocb, from)) {
+                               clear_inode_flag(inode, FI_NO_PREALLOC);
+                               inode_unlock(inode);
+                               ret = -EAGAIN;
+                               goto out;
+                       }
                } else {
                        preallocated = true;
                        target_size = iocb->ki_pos + iov_iter_count(from);
@@ -3077,7 +3092,8 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
                        if (err) {
                                clear_inode_flag(inode, FI_NO_PREALLOC);
                                inode_unlock(inode);
-                               return err;
+                               ret = err;
+                               goto out;
                        }
                }
                ret = __generic_file_write_iter(iocb, from);
@@ -3091,7 +3107,9 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
                        f2fs_update_iostat(F2FS_I_SB(inode), APP_WRITE_IO, ret);
        }
        inode_unlock(inode);
-
+out:
+       trace_f2fs_file_write_iter(inode, iocb->ki_pos,
+                                       iov_iter_count(from), ret);
        if (ret > 0)
                ret = generic_write_sync(iocb, ret);
        return ret;
index 195cf0f..963fb45 100644 (file)
@@ -591,7 +591,7 @@ block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode)
                int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
                bidx = node_ofs - 5 - dec;
        }
-       return bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE(inode);
+       return bidx * ADDRS_PER_BLOCK(inode) + ADDRS_PER_INODE(inode);
 }
 
 static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
@@ -656,6 +656,11 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
 
        if (f2fs_lookup_extent_cache(inode, index, &ei)) {
                dn.data_blkaddr = ei.blk + index - ei.fofs;
+               if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
+                                               DATA_GENERIC_ENHANCE_READ))) {
+                       err = -EFAULT;
+                       goto put_page;
+               }
                goto got_it;
        }
 
@@ -665,8 +670,12 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
                goto put_page;
        f2fs_put_dnode(&dn);
 
+       if (!__is_valid_data_blkaddr(dn.data_blkaddr)) {
+               err = -ENOENT;
+               goto put_page;
+       }
        if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
-                                               DATA_GENERIC))) {
+                                               DATA_GENERIC_ENHANCE))) {
                err = -EFAULT;
                goto put_page;
        }
@@ -1175,6 +1184,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
                                "type [%d, %d] in SSA and SIT",
                                segno, type, GET_SUM_TYPE((&sum->footer)));
                        set_sbi_flag(sbi, SBI_NEED_FSCK);
+                       f2fs_stop_checkpoint(sbi, false);
                        goto skip;
                }
 
@@ -1346,7 +1356,7 @@ void f2fs_build_gc_manager(struct f2fs_sb_info *sbi)
        sbi->gc_pin_file_threshold = DEF_GC_FAILED_PINNED_FILES;
 
        /* give warm/cold data area from slower device */
-       if (sbi->s_ndevs && !__is_large_section(sbi))
+       if (f2fs_is_multi_device(sbi) && !__is_large_section(sbi))
                SIT_I(sbi)->last_victim[ALLOC_NEXT] =
                                GET_SEGNO(sbi, FDEV(0).end_blk) + 1;
 }
index bb6a152..404d246 100644 (file)
@@ -420,6 +420,14 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,
        stat_dec_inline_dir(dir);
        clear_inode_flag(dir, FI_INLINE_DENTRY);
 
+       /*
+        * should retrieve reserved space which was used to keep
+        * inline_dentry's structure for backward compatibility.
+        */
+       if (!f2fs_sb_has_flexible_inline_xattr(F2FS_I_SB(dir)) &&
+                       !f2fs_has_inline_xattr(dir))
+               F2FS_I(dir)->i_inline_xattr_size = 0;
+
        f2fs_i_depth_write(dir, 1);
        if (i_size_read(dir) < PAGE_SIZE)
                f2fs_i_size_write(dir, PAGE_SIZE);
@@ -501,6 +509,15 @@ static int f2fs_move_rehashed_dirents(struct inode *dir, struct page *ipage,
 
        stat_dec_inline_dir(dir);
        clear_inode_flag(dir, FI_INLINE_DENTRY);
+
+       /*
+        * should retrieve reserved space which was used to keep
+        * inline_dentry's structure for backward compatibility.
+        */
+       if (!f2fs_sb_has_flexible_inline_xattr(F2FS_I_SB(dir)) &&
+                       !f2fs_has_inline_xattr(dir))
+               F2FS_I(dir)->i_inline_xattr_size = 0;
+
        kvfree(backup_dentry);
        return 0;
 recover:
index e7f2e87..ccb0222 100644 (file)
@@ -73,7 +73,7 @@ static int __written_first_block(struct f2fs_sb_info *sbi,
 
        if (!__is_valid_data_blkaddr(addr))
                return 1;
-       if (!f2fs_is_valid_blkaddr(sbi, addr, DATA_GENERIC))
+       if (!f2fs_is_valid_blkaddr(sbi, addr, DATA_GENERIC_ENHANCE))
                return -EFAULT;
        return 0;
 }
@@ -177,8 +177,8 @@ bool f2fs_inode_chksum_verify(struct f2fs_sb_info *sbi, struct page *page)
 
        if (provided != calculated)
                f2fs_msg(sbi->sb, KERN_WARNING,
-                       "checksum invalid, ino = %x, %x vs. %x",
-                       ino_of_node(page), provided, calculated);
+                       "checksum invalid, nid = %lu, ino_of_node = %x, %x vs. %x",
+                       page->index, ino_of_node(page), provided, calculated);
 
        return provided == calculated;
 }
@@ -267,9 +267,10 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page)
                struct extent_info *ei = &F2FS_I(inode)->extent_tree->largest;
 
                if (ei->len &&
-                       (!f2fs_is_valid_blkaddr(sbi, ei->blk, DATA_GENERIC) ||
+                       (!f2fs_is_valid_blkaddr(sbi, ei->blk,
+                                               DATA_GENERIC_ENHANCE) ||
                        !f2fs_is_valid_blkaddr(sbi, ei->blk + ei->len - 1,
-                                                       DATA_GENERIC))) {
+                                               DATA_GENERIC_ENHANCE))) {
                        set_sbi_flag(sbi, SBI_NEED_FSCK);
                        f2fs_msg(sbi->sb, KERN_WARNING,
                                "%s: inode (ino=%lx) extent info [%u, %u, %u] "
@@ -488,6 +489,7 @@ make_now:
        return inode;
 
 bad_inode:
+       f2fs_inode_synced(inode);
        iget_failed(inode);
        trace_f2fs_iget_exit(inode, ret);
        return ERR_PTR(ret);
index c3e8a90..0f77f92 100644 (file)
@@ -143,7 +143,7 @@ fail_drop:
        return ERR_PTR(err);
 }
 
-static int is_extension_exist(const unsigned char *s, const char *sub)
+static inline int is_extension_exist(const unsigned char *s, const char *sub)
 {
        size_t slen = strlen(s);
        size_t sublen = strlen(sub);
index d6e48a6..18a038a 100644 (file)
@@ -454,7 +454,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
                        new_blkaddr == NULL_ADDR);
        f2fs_bug_on(sbi, nat_get_blkaddr(e) == NEW_ADDR &&
                        new_blkaddr == NEW_ADDR);
-       f2fs_bug_on(sbi, is_valid_data_blkaddr(sbi, nat_get_blkaddr(e)) &&
+       f2fs_bug_on(sbi, __is_valid_data_blkaddr(nat_get_blkaddr(e)) &&
                        new_blkaddr == NEW_ADDR);
 
        /* increment version no as node is removed */
@@ -465,7 +465,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
 
        /* change address */
        nat_set_blkaddr(e, new_blkaddr);
-       if (!is_valid_data_blkaddr(sbi, new_blkaddr))
+       if (!__is_valid_data_blkaddr(new_blkaddr))
                set_nat_flag(e, IS_CHECKPOINTED, false);
        __set_nat_cache_dirty(nm_i, e);
 
@@ -526,6 +526,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
        struct f2fs_nat_entry ne;
        struct nat_entry *e;
        pgoff_t index;
+       block_t blkaddr;
        int i;
 
        ni->nid = nid;
@@ -569,6 +570,11 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
        node_info_from_raw_nat(ni, &ne);
        f2fs_put_page(page, 1);
 cache:
+       blkaddr = le32_to_cpu(ne.block_addr);
+       if (__is_valid_data_blkaddr(blkaddr) &&
+               !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE))
+               return -EFAULT;
+
        /* cache nat entry */
        cache_nat_entry(sbi, nid, &ne);
        return 0;
@@ -600,9 +606,9 @@ static void f2fs_ra_node_pages(struct page *parent, int start, int n)
 pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs)
 {
        const long direct_index = ADDRS_PER_INODE(dn->inode);
-       const long direct_blks = ADDRS_PER_BLOCK;
-       const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
-       unsigned int skipped_unit = ADDRS_PER_BLOCK;
+       const long direct_blks = ADDRS_PER_BLOCK(dn->inode);
+       const long indirect_blks = ADDRS_PER_BLOCK(dn->inode) * NIDS_PER_BLOCK;
+       unsigned int skipped_unit = ADDRS_PER_BLOCK(dn->inode);
        int cur_level = dn->cur_level;
        int max_level = dn->max_level;
        pgoff_t base = 0;
@@ -638,9 +644,9 @@ static int get_node_path(struct inode *inode, long block,
                                int offset[4], unsigned int noffset[4])
 {
        const long direct_index = ADDRS_PER_INODE(inode);
-       const long direct_blks = ADDRS_PER_BLOCK;
+       const long direct_blks = ADDRS_PER_BLOCK(inode);
        const long dptrs_per_blk = NIDS_PER_BLOCK;
-       const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
+       const long indirect_blks = ADDRS_PER_BLOCK(inode) * NIDS_PER_BLOCK;
        const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
        int n = 0;
        int level = 0;
@@ -1181,8 +1187,14 @@ int f2fs_remove_inode_page(struct inode *inode)
                f2fs_put_dnode(&dn);
                return -EIO;
        }
-       f2fs_bug_on(F2FS_I_SB(inode),
-                       inode->i_blocks != 0 && inode->i_blocks != 8);
+
+       if (unlikely(inode->i_blocks != 0 && inode->i_blocks != 8)) {
+               f2fs_msg(F2FS_I_SB(inode)->sb, KERN_WARNING,
+                       "Inconsistent i_blocks, ino:%lu, iblocks:%llu",
+                       inode->i_ino,
+                       (unsigned long long)inode->i_blocks);
+               set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
+       }
 
        /* will put inode & node pages */
        err = truncate_node(&dn);
@@ -1277,9 +1289,10 @@ static int read_node_page(struct page *page, int op_flags)
        int err;
 
        if (PageUptodate(page)) {
-#ifdef CONFIG_F2FS_CHECK_FS
-               f2fs_bug_on(sbi, !f2fs_inode_chksum_verify(sbi, page));
-#endif
+               if (!f2fs_inode_chksum_verify(sbi, page)) {
+                       ClearPageUptodate(page);
+                       return -EBADMSG;
+               }
                return LOCKED_PAGE;
        }
 
@@ -1543,7 +1556,8 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
        }
 
        if (__is_valid_data_blkaddr(ni.blk_addr) &&
-               !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC)) {
+               !f2fs_is_valid_blkaddr(sbi, ni.blk_addr,
+                                       DATA_GENERIC_ENHANCE)) {
                up_read(&sbi->node_write);
                goto redirty_out;
        }
@@ -2078,6 +2092,9 @@ static bool add_free_nid(struct f2fs_sb_info *sbi,
        if (unlikely(nid == 0))
                return false;
 
+       if (unlikely(f2fs_check_nid_range(sbi, nid)))
+               return false;
+
        i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS);
        i->nid = nid;
        i->state = FREE_NID;
index e3883db..e04f82b 100644 (file)
@@ -325,8 +325,10 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
                        break;
                }
 
-               if (!is_recoverable_dnode(page))
+               if (!is_recoverable_dnode(page)) {
+                       f2fs_put_page(page, 1);
                        break;
+               }
 
                if (!is_fsync_dnode(page))
                        goto next;
@@ -338,8 +340,10 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
                        if (!check_only &&
                                        IS_INODE(page) && is_dent_dnode(page)) {
                                err = f2fs_recover_inode_page(sbi, page);
-                               if (err)
+                               if (err) {
+                                       f2fs_put_page(page, 1);
                                        break;
+                               }
                                quota_inode = true;
                        }
 
@@ -355,6 +359,7 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
                                        err = 0;
                                        goto next;
                                }
+                               f2fs_put_page(page, 1);
                                break;
                        }
                }
@@ -370,6 +375,7 @@ next:
                                "%s: detect looped node chain, "
                                "blkaddr:%u, next:%u",
                                __func__, blkaddr, next_blkaddr_of_node(page));
+                       f2fs_put_page(page, 1);
                        err = -EINVAL;
                        break;
                }
@@ -380,7 +386,6 @@ next:
 
                f2fs_ra_meta_pages_cond(sbi, blkaddr);
        }
-       f2fs_put_page(page, 1);
        return err;
 }
 
@@ -546,7 +551,15 @@ retry_dn:
                goto err;
 
        f2fs_bug_on(sbi, ni.ino != ino_of_node(page));
-       f2fs_bug_on(sbi, ofs_of_node(dn.node_page) != ofs_of_node(page));
+
+       if (ofs_of_node(dn.node_page) != ofs_of_node(page)) {
+               f2fs_msg(sbi->sb, KERN_WARNING,
+                       "Inconsistent ofs_of_node, ino:%lu, ofs:%u, %u",
+                       inode->i_ino, ofs_of_node(dn.node_page),
+                       ofs_of_node(page));
+               err = -EFAULT;
+               goto err;
+       }
 
        for (; start < end; start++, dn.ofs_in_node++) {
                block_t src, dest;
@@ -554,6 +567,18 @@ retry_dn:
                src = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node);
                dest = datablock_addr(dn.inode, page, dn.ofs_in_node);
 
+               if (__is_valid_data_blkaddr(src) &&
+                       !f2fs_is_valid_blkaddr(sbi, src, META_POR)) {
+                       err = -EFAULT;
+                       goto err;
+               }
+
+               if (__is_valid_data_blkaddr(dest) &&
+                       !f2fs_is_valid_blkaddr(sbi, dest, META_POR)) {
+                       err = -EFAULT;
+                       goto err;
+               }
+
                /* skip recovering if dest is the same as src */
                if (src == dest)
                        continue;
@@ -666,8 +691,10 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list,
                 */
                if (IS_INODE(page)) {
                        err = recover_inode(entry->inode, page);
-                       if (err)
+                       if (err) {
+                               f2fs_put_page(page, 1);
                                break;
+                       }
                }
                if (entry->last_dentry == blkaddr) {
                        err = recover_dentry(entry->inode, page, dir_list);
index aa7fe79..8dee063 100644 (file)
@@ -580,7 +580,7 @@ static int submit_flush_wait(struct f2fs_sb_info *sbi, nid_t ino)
        int ret = 0;
        int i;
 
-       if (!sbi->s_ndevs)
+       if (!f2fs_is_multi_device(sbi))
                return __submit_flush_wait(sbi, sbi->sb->s_bdev);
 
        for (i = 0; i < sbi->s_ndevs; i++) {
@@ -648,7 +648,8 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi, nid_t ino)
                return ret;
        }
 
-       if (atomic_inc_return(&fcc->queued_flush) == 1 || sbi->s_ndevs > 1) {
+       if (atomic_inc_return(&fcc->queued_flush) == 1 ||
+           f2fs_is_multi_device(sbi)) {
                ret = submit_flush_wait(sbi, ino);
                atomic_dec(&fcc->queued_flush);
 
@@ -754,7 +755,7 @@ int f2fs_flush_device_cache(struct f2fs_sb_info *sbi)
 {
        int ret = 0, i;
 
-       if (!sbi->s_ndevs)
+       if (!f2fs_is_multi_device(sbi))
                return 0;
 
        for (i = 1; i < sbi->s_ndevs; i++) {
@@ -1367,9 +1368,12 @@ static int __queue_discard_cmd(struct f2fs_sb_info *sbi,
 {
        block_t lblkstart = blkstart;
 
+       if (!f2fs_bdev_support_discard(bdev))
+               return 0;
+
        trace_f2fs_queue_discard(bdev, blkstart, blklen);
 
-       if (sbi->s_ndevs) {
+       if (f2fs_is_multi_device(sbi)) {
                int devi = f2fs_target_device_index(sbi, blkstart);
 
                blkstart -= FDEV(devi).start_blk;
@@ -1732,42 +1736,36 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi,
        block_t lblkstart = blkstart;
        int devi = 0;
 
-       if (sbi->s_ndevs) {
+       if (f2fs_is_multi_device(sbi)) {
                devi = f2fs_target_device_index(sbi, blkstart);
+               if (blkstart < FDEV(devi).start_blk ||
+                   blkstart > FDEV(devi).end_blk) {
+                       f2fs_msg(sbi->sb, KERN_ERR, "Invalid block %x",
+                                blkstart);
+                       return -EIO;
+               }
                blkstart -= FDEV(devi).start_blk;
        }
 
-       /*
-        * We need to know the type of the zone: for conventional zones,
-        * use regular discard if the drive supports it. For sequential
-        * zones, reset the zone write pointer.
-        */
-       switch (get_blkz_type(sbi, bdev, blkstart)) {
-
-       case BLK_ZONE_TYPE_CONVENTIONAL:
-               if (!blk_queue_discard(bdev_get_queue(bdev)))
-                       return 0;
-               return __queue_discard_cmd(sbi, bdev, lblkstart, blklen);
-       case BLK_ZONE_TYPE_SEQWRITE_REQ:
-       case BLK_ZONE_TYPE_SEQWRITE_PREF:
+       /* For sequential zones, reset the zone write pointer */
+       if (f2fs_blkz_is_seq(sbi, devi, blkstart)) {
                sector = SECTOR_FROM_BLOCK(blkstart);
                nr_sects = SECTOR_FROM_BLOCK(blklen);
 
                if (sector & (bdev_zone_sectors(bdev) - 1) ||
                                nr_sects != bdev_zone_sectors(bdev)) {
-                       f2fs_msg(sbi->sb, KERN_INFO,
-                               "(%d) %s: Unaligned discard attempted (block %x + %x)",
+                       f2fs_msg(sbi->sb, KERN_ERR,
+                               "(%d) %s: Unaligned zone reset attempted (block %x + %x)",
                                devi, sbi->s_ndevs ? FDEV(devi).path: "",
                                blkstart, blklen);
                        return -EIO;
                }
                trace_f2fs_issue_reset_zone(bdev, blkstart);
-               return blkdev_reset_zones(bdev, sector,
-                                         nr_sects, GFP_NOFS);
-       default:
-               /* Unknown zone type: broken device ? */
-               return -EIO;
+               return blkdev_reset_zones(bdev, sector, nr_sects, GFP_NOFS);
        }
+
+       /* For conventional zones, use regular discard if supported */
+       return __queue_discard_cmd(sbi, bdev, lblkstart, blklen);
 }
 #endif
 
@@ -1775,8 +1773,7 @@ static int __issue_discard_async(struct f2fs_sb_info *sbi,
                struct block_device *bdev, block_t blkstart, block_t blklen)
 {
 #ifdef CONFIG_BLK_DEV_ZONED
-       if (f2fs_sb_has_blkzoned(sbi) &&
-                               bdev_zoned_model(bdev) != BLK_ZONED_NONE)
+       if (f2fs_sb_has_blkzoned(sbi) && bdev_is_zoned(bdev))
                return __f2fs_issue_discard_zone(sbi, bdev, blkstart, blklen);
 #endif
        return __queue_discard_cmd(sbi, bdev, blkstart, blklen);
@@ -2172,8 +2169,11 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
                         * before, we must track that to know how much space we
                         * really have.
                         */
-                       if (f2fs_test_bit(offset, se->ckpt_valid_map))
+                       if (f2fs_test_bit(offset, se->ckpt_valid_map)) {
+                               spin_lock(&sbi->stat_lock);
                                sbi->unusable_block_count++;
+                               spin_unlock(&sbi->stat_lock);
+                       }
                }
 
                if (f2fs_test_and_clear_bit(offset, se->discard_map))
@@ -2220,7 +2220,7 @@ bool f2fs_is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr)
        struct seg_entry *se;
        bool is_cp = false;
 
-       if (!is_valid_data_blkaddr(sbi, blkaddr))
+       if (!__is_valid_data_blkaddr(blkaddr))
                return true;
 
        down_read(&sit_i->sentry_lock);
@@ -3089,7 +3089,7 @@ static void update_device_state(struct f2fs_io_info *fio)
        struct f2fs_sb_info *sbi = fio->sbi;
        unsigned int devidx;
 
-       if (!sbi->s_ndevs)
+       if (!f2fs_is_multi_device(sbi))
                return;
 
        devidx = f2fs_target_device_index(sbi, fio->new_blkaddr);
@@ -3187,13 +3187,18 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
 {
        int err;
        struct f2fs_sb_info *sbi = fio->sbi;
+       unsigned int segno;
 
        fio->new_blkaddr = fio->old_blkaddr;
        /* i/o temperature is needed for passing down write hints */
        __get_segment_type(fio);
 
-       f2fs_bug_on(sbi, !IS_DATASEG(get_seg_entry(sbi,
-                       GET_SEGNO(sbi, fio->new_blkaddr))->type));
+       segno = GET_SEGNO(sbi, fio->new_blkaddr);
+
+       if (!IS_DATASEG(get_seg_entry(sbi, segno)->type)) {
+               set_sbi_flag(sbi, SBI_NEED_FSCK);
+               return -EFAULT;
+       }
 
        stat_inc_inplace_blocks(fio->sbi);
 
@@ -3336,7 +3341,7 @@ void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr)
        if (!f2fs_post_read_required(inode))
                return;
 
-       if (!is_valid_data_blkaddr(sbi, blkaddr))
+       if (!__is_valid_data_blkaddr(blkaddr))
                return;
 
        cpage = find_lock_page(META_MAPPING(sbi), blkaddr);
index 5c7ed04..429007b 100644 (file)
@@ -82,7 +82,7 @@
        (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & ((sbi)->blocks_per_seg - 1))
 
 #define GET_SEGNO(sbi, blk_addr)                                       \
-       ((!is_valid_data_blkaddr(sbi, blk_addr)) ?                      \
+       ((!__is_valid_data_blkaddr(blk_addr)) ?                 \
        NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi),                 \
                GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
 #define BLKS_PER_SEC(sbi)                                      \
@@ -656,14 +656,15 @@ static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno)
        f2fs_bug_on(sbi, segno > TOTAL_SEGS(sbi) - 1);
 }
 
-static inline void verify_block_addr(struct f2fs_io_info *fio, block_t blk_addr)
+static inline void verify_fio_blkaddr(struct f2fs_io_info *fio)
 {
        struct f2fs_sb_info *sbi = fio->sbi;
 
-       if (__is_meta_io(fio))
-               verify_blkaddr(sbi, blk_addr, META_GENERIC);
-       else
-               verify_blkaddr(sbi, blk_addr, DATA_GENERIC);
+       if (__is_valid_data_blkaddr(fio->old_blkaddr))
+               verify_blkaddr(sbi, fio->old_blkaddr, __is_meta_io(fio) ?
+                                       META_GENERIC : DATA_GENERIC);
+       verify_blkaddr(sbi, fio->new_blkaddr, __is_meta_io(fio) ?
+                                       META_GENERIC : DATA_GENERIC_ENHANCE);
 }
 
 /*
@@ -672,7 +673,6 @@ static inline void verify_block_addr(struct f2fs_io_info *fio, block_t blk_addr)
 static inline int check_block_count(struct f2fs_sb_info *sbi,
                int segno, struct f2fs_sit_entry *raw_sit)
 {
-#ifdef CONFIG_F2FS_CHECK_FS
        bool is_valid  = test_bit_le(0, raw_sit->valid_map) ? true : false;
        int valid_blocks = 0;
        int cur_pos = 0, next_pos;
@@ -699,7 +699,7 @@ static inline int check_block_count(struct f2fs_sb_info *sbi,
                set_sbi_flag(sbi, SBI_NEED_FSCK);
                return -EINVAL;
        }
-#endif
+
        /* check segment usage, and check boundary of a given segment number */
        if (unlikely(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg
                                        || segno > TOTAL_SEGS(sbi) - 1)) {
index 4c55d2e..6b959bb 100644 (file)
@@ -1019,7 +1019,7 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
        for (i = 0; i < sbi->s_ndevs; i++) {
                blkdev_put(FDEV(i).bdev, FMODE_EXCL);
 #ifdef CONFIG_BLK_DEV_ZONED
-               kvfree(FDEV(i).blkz_type);
+               kvfree(FDEV(i).blkz_seq);
 #endif
        }
        kvfree(sbi->devs);
@@ -1221,10 +1221,13 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_blocks = total_count - start_count;
        buf->f_bfree = user_block_count - valid_user_blocks(sbi) -
                                                sbi->current_reserved_blocks;
+
+       spin_lock(&sbi->stat_lock);
        if (unlikely(buf->f_bfree <= sbi->unusable_block_count))
                buf->f_bfree = 0;
        else
                buf->f_bfree -= sbi->unusable_block_count;
+       spin_unlock(&sbi->stat_lock);
 
        if (buf->f_bfree > F2FS_OPTION(sbi).root_reserved_blocks)
                buf->f_bavail = buf->f_bfree -
@@ -1499,9 +1502,15 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi)
        mutex_lock(&sbi->gc_mutex);
        cpc.reason = CP_PAUSE;
        set_sbi_flag(sbi, SBI_CP_DISABLED);
-       f2fs_write_checkpoint(sbi, &cpc);
+       err = f2fs_write_checkpoint(sbi, &cpc);
+       if (err)
+               goto out_unlock;
 
+       spin_lock(&sbi->stat_lock);
        sbi->unusable_block_count = 0;
+       spin_unlock(&sbi->stat_lock);
+
+out_unlock:
        mutex_unlock(&sbi->gc_mutex);
 restore_flag:
        sbi->sb->s_flags = s_flags;     /* Restore MS_RDONLY status */
@@ -2271,7 +2280,7 @@ static const struct export_operations f2fs_export_ops = {
 static loff_t max_file_blocks(void)
 {
        loff_t result = 0;
-       loff_t leaf_count = ADDRS_PER_BLOCK;
+       loff_t leaf_count = DEF_ADDRS_PER_BLOCK;
 
        /*
         * note: previously, result is equal to (DEF_ADDRS_PER_INODE -
@@ -2449,7 +2458,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
        /* Currently, support only 4KB page cache size */
        if (F2FS_BLKSIZE != PAGE_SIZE) {
                f2fs_msg(sb, KERN_INFO,
-                       "Invalid page_cache_size (%lu), supports only 4KB\n",
+                       "Invalid page_cache_size (%lu), supports only 4KB",
                        PAGE_SIZE);
                return 1;
        }
@@ -2458,7 +2467,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
        blocksize = 1 << le32_to_cpu(raw_super->log_blocksize);
        if (blocksize != F2FS_BLKSIZE) {
                f2fs_msg(sb, KERN_INFO,
-                       "Invalid blocksize (%u), supports only 4KB\n",
+                       "Invalid blocksize (%u), supports only 4KB",
                        blocksize);
                return 1;
        }
@@ -2466,7 +2475,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
        /* check log blocks per segment */
        if (le32_to_cpu(raw_super->log_blocks_per_seg) != 9) {
                f2fs_msg(sb, KERN_INFO,
-                       "Invalid log blocks per segment (%u)\n",
+                       "Invalid log blocks per segment (%u)",
                        le32_to_cpu(raw_super->log_blocks_per_seg));
                return 1;
        }
@@ -2587,7 +2596,8 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
        unsigned int log_blocks_per_seg;
        unsigned int segment_count_main;
        unsigned int cp_pack_start_sum, cp_payload;
-       block_t user_block_count;
+       block_t user_block_count, valid_user_blocks;
+       block_t avail_node_count, valid_node_count;
        int i, j;
 
        total = le32_to_cpu(raw_super->segment_count);
@@ -2622,6 +2632,24 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
                return 1;
        }
 
+       valid_user_blocks = le64_to_cpu(ckpt->valid_block_count);
+       if (valid_user_blocks > user_block_count) {
+               f2fs_msg(sbi->sb, KERN_ERR,
+                       "Wrong valid_user_blocks: %u, user_block_count: %u",
+                       valid_user_blocks, user_block_count);
+               return 1;
+       }
+
+       valid_node_count = le32_to_cpu(ckpt->valid_node_count);
+       avail_node_count = sbi->total_node_count - sbi->nquota_files -
+                                               F2FS_RESERVED_NODE_NUM;
+       if (valid_node_count > avail_node_count) {
+               f2fs_msg(sbi->sb, KERN_ERR,
+                       "Wrong valid_node_count: %u, avail_node_count: %u",
+                       valid_node_count, avail_node_count);
+               return 1;
+       }
+
        main_segs = le32_to_cpu(raw_super->segment_count_main);
        blocks_per_seg = sbi->blocks_per_seg;
 
@@ -2793,9 +2821,11 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi)
        if (nr_sectors & (bdev_zone_sectors(bdev) - 1))
                FDEV(devi).nr_blkz++;
 
-       FDEV(devi).blkz_type = f2fs_kmalloc(sbi, FDEV(devi).nr_blkz,
-                                                               GFP_KERNEL);
-       if (!FDEV(devi).blkz_type)
+       FDEV(devi).blkz_seq = f2fs_kzalloc(sbi,
+                                       BITS_TO_LONGS(FDEV(devi).nr_blkz)
+                                       * sizeof(unsigned long),
+                                       GFP_KERNEL);
+       if (!FDEV(devi).blkz_seq)
                return -ENOMEM;
 
 #define F2FS_REPORT_NR_ZONES   4096
@@ -2822,7 +2852,8 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi)
                }
 
                for (i = 0; i < nr_zones; i++) {
-                       FDEV(devi).blkz_type[n] = zones[i].type;
+                       if (zones[i].type != BLK_ZONE_TYPE_CONVENTIONAL)
+                               set_bit(n, FDEV(devi).blkz_seq);
                        sector += zones[i].len;
                        n++;
                }
@@ -3105,7 +3136,7 @@ try_onemore:
 #ifndef CONFIG_BLK_DEV_ZONED
        if (f2fs_sb_has_blkzoned(sbi)) {
                f2fs_msg(sb, KERN_ERR,
-                        "Zoned block device support is not enabled\n");
+                        "Zoned block device support is not enabled");
                err = -EOPNOTSUPP;
                goto free_sb_buf;
        }
@@ -3350,10 +3381,17 @@ try_onemore:
                 * mount should be failed, when device has readonly mode, and
                 * previous checkpoint was not done by clean system shutdown.
                 */
-               if (bdev_read_only(sb->s_bdev) &&
-                               !is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) {
-                       err = -EROFS;
-                       goto free_meta;
+               if (f2fs_hw_is_readonly(sbi)) {
+                       if (!is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) {
+                               err = -EROFS;
+                               f2fs_msg(sb, KERN_ERR,
+                                       "Need to recover fsync data, but "
+                                       "write access unavailable");
+                               goto free_meta;
+                       }
+                       f2fs_msg(sbi->sb, KERN_INFO, "write access "
+                               "unavailable, skipping recovery");
+                       goto reset_checkpoint;
                }
 
                if (need_fsck)
index 848a785..e791741 100644 (file)
@@ -202,12 +202,17 @@ static inline const struct xattr_handler *f2fs_xattr_handler(int index)
        return handler;
 }
 
-static struct f2fs_xattr_entry *__find_xattr(void *base_addr, int index,
-                                       size_t len, const char *name)
+static struct f2fs_xattr_entry *__find_xattr(void *base_addr,
+                               void *last_base_addr, int index,
+                               size_t len, const char *name)
 {
        struct f2fs_xattr_entry *entry;
 
        list_for_each_xattr(entry, base_addr) {
+               if ((void *)(entry) + sizeof(__u32) > last_base_addr ||
+                       (void *)XATTR_NEXT_ENTRY(entry) > last_base_addr)
+                       return NULL;
+
                if (entry->e_name_index != index)
                        continue;
                if (entry->e_name_len != len)
@@ -297,20 +302,22 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage,
                                const char *name, struct f2fs_xattr_entry **xe,
                                void **base_addr, int *base_size)
 {
-       void *cur_addr, *txattr_addr, *last_addr = NULL;
+       void *cur_addr, *txattr_addr, *last_txattr_addr;
+       void *last_addr = NULL;
        nid_t xnid = F2FS_I(inode)->i_xattr_nid;
-       unsigned int size = xnid ? VALID_XATTR_BLOCK_SIZE : 0;
        unsigned int inline_size = inline_xattr_size(inode);
        int err = 0;
 
-       if (!size && !inline_size)
+       if (!xnid && !inline_size)
                return -ENODATA;
 
-       *base_size = inline_size + size + XATTR_PADDING_SIZE;
+       *base_size = XATTR_SIZE(xnid, inode) + XATTR_PADDING_SIZE;
        txattr_addr = f2fs_kzalloc(F2FS_I_SB(inode), *base_size, GFP_NOFS);
        if (!txattr_addr)
                return -ENOMEM;
 
+       last_txattr_addr = (void *)txattr_addr + XATTR_SIZE(xnid, inode);
+
        /* read from inline xattr */
        if (inline_size) {
                err = read_inline_xattr(inode, ipage, txattr_addr);
@@ -337,7 +344,11 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage,
        else
                cur_addr = txattr_addr;
 
-       *xe = __find_xattr(cur_addr, index, len, name);
+       *xe = __find_xattr(cur_addr, last_txattr_addr, index, len, name);
+       if (!*xe) {
+               err = -EFAULT;
+               goto out;
+       }
 check:
        if (IS_XATTR_LAST_ENTRY(*xe)) {
                err = -ENODATA;
@@ -581,7 +592,8 @@ static int __f2fs_setxattr(struct inode *inode, int index,
                        struct page *ipage, int flags)
 {
        struct f2fs_xattr_entry *here, *last;
-       void *base_addr;
+       void *base_addr, *last_base_addr;
+       nid_t xnid = F2FS_I(inode)->i_xattr_nid;
        int found, newsize;
        size_t len;
        __u32 new_hsize;
@@ -605,8 +617,14 @@ static int __f2fs_setxattr(struct inode *inode, int index,
        if (error)
                return error;
 
+       last_base_addr = (void *)base_addr + XATTR_SIZE(xnid, inode);
+
        /* find entry with wanted name. */
-       here = __find_xattr(base_addr, index, len, name);
+       here = __find_xattr(base_addr, last_base_addr, index, len, name);
+       if (!here) {
+               error = -EFAULT;
+               goto exit;
+       }
 
        found = IS_XATTR_LAST_ENTRY(here) ? 0 : 1;
 
index 9172ee0..a90920e 100644 (file)
@@ -71,6 +71,8 @@ struct f2fs_xattr_entry {
                                entry = XATTR_NEXT_ENTRY(entry))
 #define VALID_XATTR_BLOCK_SIZE (PAGE_SIZE - sizeof(struct node_footer))
 #define XATTR_PADDING_SIZE     (sizeof(__u32))
+#define XATTR_SIZE(x,i)                (((x) ? VALID_XATTR_BLOCK_SIZE : 0) +   \
+                                               (inline_xattr_size(i)))
 #define MIN_OFFSET(i)          XATTR_ALIGN(inline_xattr_size(i) +      \
                                                VALID_XATTR_BLOCK_SIZE)
 
index b3bed32..0e3ed79 100644 (file)
@@ -193,12 +193,17 @@ static int fat_file_release(struct inode *inode, struct file *filp)
 int fat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
 {
        struct inode *inode = filp->f_mapping->host;
-       int res, err;
+       int err;
+
+       err = __generic_file_fsync(filp, start, end, datasync);
+       if (err)
+               return err;
 
-       res = generic_file_fsync(filp, start, end, datasync);
        err = sync_mapping_buffers(MSDOS_SB(inode->i_sb)->fat_inode->i_mapping);
+       if (err)
+               return err;
 
-       return res ? res : err;
+       return blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 }
 
 
index fe80bea..14ce1e4 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/fs_context.h>
 
 #define FUSE_CTL_SUPER_MAGIC 0x65735543
 
@@ -317,7 +318,7 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc)
        drop_nlink(d_inode(fuse_control_sb->s_root));
 }
 
-static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent)
+static int fuse_ctl_fill_super(struct super_block *sb, struct fs_context *fctx)
 {
        static const struct tree_descr empty_descr = {""};
        struct fuse_conn *fc;
@@ -343,10 +344,19 @@ static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent)
        return 0;
 }
 
-static struct dentry *fuse_ctl_mount(struct file_system_type *fs_type,
-                       int flags, const char *dev_name, void *raw_data)
+static int fuse_ctl_get_tree(struct fs_context *fc)
 {
-       return mount_single(fs_type, flags, raw_data, fuse_ctl_fill_super);
+       return vfs_get_super(fc, vfs_get_single_super, fuse_ctl_fill_super);
+}
+
+static const struct fs_context_operations fuse_ctl_context_ops = {
+       .get_tree       = fuse_ctl_get_tree,
+};
+
+static int fuse_ctl_init_fs_context(struct fs_context *fc)
+{
+       fc->ops = &fuse_ctl_context_ops;
+       return 0;
 }
 
 static void fuse_ctl_kill_sb(struct super_block *sb)
@@ -365,7 +375,7 @@ static void fuse_ctl_kill_sb(struct super_block *sb)
 static struct file_system_type fuse_ctl_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "fusectl",
-       .mount          = fuse_ctl_mount,
+       .init_fs_context = fuse_ctl_init_fs_context,
        .kill_sb        = fuse_ctl_kill_sb,
 };
 MODULE_ALIAS_FS("fusectl");
index 55a26f3..4b41df1 100644 (file)
@@ -33,6 +33,8 @@
  * closed.
  */
 
+#define pr_fmt(fmt) "CUSE: " fmt
+
 #include <linux/fuse.h>
 #include <linux/cdev.h>
 #include <linux/device.h>
@@ -225,7 +227,7 @@ static int cuse_parse_one(char **pp, char *end, char **keyp, char **valp)
                return 0;
 
        if (end[-1] != '\0') {
-               printk(KERN_ERR "CUSE: info not properly terminated\n");
+               pr_err("info not properly terminated\n");
                return -EINVAL;
        }
 
@@ -242,7 +244,7 @@ static int cuse_parse_one(char **pp, char *end, char **keyp, char **valp)
                key = strstrip(key);
 
        if (!strlen(key)) {
-               printk(KERN_ERR "CUSE: zero length info key specified\n");
+               pr_err("zero length info key specified\n");
                return -EINVAL;
        }
 
@@ -282,12 +284,11 @@ static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo)
                if (strcmp(key, "DEVNAME") == 0)
                        devinfo->name = val;
                else
-                       printk(KERN_WARNING "CUSE: unknown device info \"%s\"\n",
-                              key);
+                       pr_warn("unknown device info \"%s\"\n", key);
        }
 
        if (!devinfo->name || !strlen(devinfo->name)) {
-               printk(KERN_ERR "CUSE: DEVNAME unspecified\n");
+               pr_err("DEVNAME unspecified\n");
                return -EINVAL;
        }
 
@@ -341,7 +342,7 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
        else
                rc = register_chrdev_region(devt, 1, devinfo.name);
        if (rc) {
-               printk(KERN_ERR "CUSE: failed to register chrdev region\n");
+               pr_err("failed to register chrdev region\n");
                goto err;
        }
 
index 9971a35..24ea19c 100644 (file)
@@ -906,8 +906,8 @@ static int fuse_check_page(struct page *page)
               1 << PG_lru |
               1 << PG_active |
               1 << PG_reclaim))) {
-               printk(KERN_WARNING "fuse: trying to steal weird page\n");
-               printk(KERN_WARNING "  page=%p index=%li flags=%08lx, count=%i, mapcount=%i, mapping=%p\n", page, page->index, page->flags, page_count(page), page_mapcount(page), page->mapping);
+               pr_warn("trying to steal weird page\n");
+               pr_warn("  page=%p index=%li flags=%08lx, count=%i, mapcount=%i, mapping=%p\n", page, page->index, page->flags, page_count(page), page_mapcount(page), page->mapping);
                return 1;
        }
        return 0;
@@ -1317,6 +1317,16 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
        unsigned reqsize;
        unsigned int hash;
 
+       /*
+        * Require sane minimum read buffer - that has capacity for fixed part
+        * of any request header + negotated max_write room for data. If the
+        * requirement is not satisfied return EINVAL to the filesystem server
+        * to indicate that it is not following FUSE server/client contract.
+        * Don't dequeue / abort any request.
+        */
+       if (nbytes < max_t(size_t, FUSE_MIN_READ_BUFFER, 4096 + fc->max_write))
+               return -EINVAL;
+
  restart:
        spin_lock(&fiq->waitq.lock);
        err = -EAGAIN;
@@ -1749,7 +1759,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
        offset = outarg->offset & ~PAGE_MASK;
        file_size = i_size_read(inode);
 
-       num = outarg->size;
+       num = min(outarg->size, fc->max_write);
        if (outarg->offset > file_size)
                num = 0;
        else if (outarg->offset + num > file_size)
index 06096b6..3959f08 100644 (file)
@@ -178,7 +178,9 @@ void fuse_finish_open(struct inode *inode, struct file *file)
 
        if (!(ff->open_flags & FOPEN_KEEP_CACHE))
                invalidate_inode_pages2(inode->i_mapping);
-       if (ff->open_flags & FOPEN_NONSEEKABLE)
+       if (ff->open_flags & FOPEN_STREAM)
+               stream_open(inode, file);
+       else if (ff->open_flags & FOPEN_NONSEEKABLE)
                nonseekable_open(inode, file);
        if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) {
                struct fuse_inode *fi = get_fuse_inode(inode);
@@ -462,7 +464,7 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
 
        memset(&inarg, 0, sizeof(inarg));
        inarg.fh = ff->fh;
-       inarg.fsync_flags = datasync ? 1 : 0;
+       inarg.fsync_flags = datasync ? FUSE_FSYNC_FDATASYNC : 0;
        args.in.h.opcode = opcode;
        args.in.h.nodeid = get_node_id(inode);
        args.in.numargs = 1;
@@ -1586,7 +1588,7 @@ __acquires(fi->lock)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_inode *fi = get_fuse_inode(inode);
-       size_t crop = i_size_read(inode);
+       loff_t crop = i_size_read(inode);
        struct fuse_req *req;
 
        while (fi->writectr >= 0 && !list_empty(&fi->queued_writes)) {
@@ -2576,8 +2578,13 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
 #if BITS_PER_LONG == 32
        inarg.flags |= FUSE_IOCTL_32BIT;
 #else
-       if (flags & FUSE_IOCTL_COMPAT)
+       if (flags & FUSE_IOCTL_COMPAT) {
                inarg.flags |= FUSE_IOCTL_32BIT;
+#ifdef CONFIG_X86_X32
+               if (in_x32_syscall())
+                       inarg.flags |= FUSE_IOCTL_COMPAT_X32;
+#endif
+       }
 #endif
 
        /* assume all the iovs returned by client always fits in a page */
@@ -3044,6 +3051,13 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
                }
        }
 
+       if (!(mode & FALLOC_FL_KEEP_SIZE) &&
+           offset + length > i_size_read(inode)) {
+               err = inode_newsize_ok(inode, offset + length);
+               if (err)
+                       return err;
+       }
+
        if (!(mode & FALLOC_FL_KEEP_SIZE))
                set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
 
index 0920c0c..24dbca7 100644 (file)
@@ -9,6 +9,10 @@
 #ifndef _FS_FUSE_I_H
 #define _FS_FUSE_I_H
 
+#ifndef pr_fmt
+# define pr_fmt(fmt) "fuse: " fmt
+#endif
+
 #include <linux/fuse.h>
 #include <linux/fs.h>
 #include <linux/mount.h>
@@ -690,6 +694,9 @@ struct fuse_conn {
        /** Use enhanced/automatic page cache invalidation. */
        unsigned auto_inval_data:1;
 
+       /** Filesystem is fully reponsible for page cache invalidation. */
+       unsigned explicit_inval_data:1;
+
        /** Does the filesystem support readdirplus? */
        unsigned do_readdirplus:1;
 
index f485d09..4bb885b 100644 (file)
@@ -81,14 +81,12 @@ struct fuse_forget_link *fuse_alloc_forget(void)
 
 static struct inode *fuse_alloc_inode(struct super_block *sb)
 {
-       struct inode *inode;
        struct fuse_inode *fi;
 
-       inode = kmem_cache_alloc(fuse_inode_cachep, GFP_KERNEL);
-       if (!inode)
+       fi = kmem_cache_alloc(fuse_inode_cachep, GFP_KERNEL);
+       if (!fi)
                return NULL;
 
-       fi = get_fuse_inode(inode);
        fi->i_time = 0;
        fi->inval_mask = 0;
        fi->nodeid = 0;
@@ -100,11 +98,11 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
        spin_lock_init(&fi->lock);
        fi->forget = fuse_alloc_forget();
        if (!fi->forget) {
-               kmem_cache_free(fuse_inode_cachep, inode);
+               kmem_cache_free(fuse_inode_cachep, fi);
                return NULL;
        }
 
-       return inode;
+       return &fi->inode;
 }
 
 static void fuse_free_inode(struct inode *inode)
@@ -233,7 +231,8 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
 
                if (oldsize != attr->size) {
                        truncate_pagecache(inode, attr->size);
-                       inval = true;
+                       if (!fc->explicit_inval_data)
+                               inval = true;
                } else if (fc->auto_inval_data) {
                        struct timespec64 new_mtime = {
                                .tv_sec = attr->mtime,
@@ -908,6 +907,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
                                fc->dont_mask = 1;
                        if (arg->flags & FUSE_AUTO_INVAL_DATA)
                                fc->auto_inval_data = 1;
+                       else if (arg->flags & FUSE_EXPLICIT_INVAL_DATA)
+                               fc->explicit_inval_data = 1;
                        if (arg->flags & FUSE_DO_READDIRPLUS) {
                                fc->do_readdirplus = 1;
                                if (arg->flags & FUSE_READDIRPLUS_AUTO)
@@ -969,7 +970,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
                FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT |
                FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL |
                FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS |
-               FUSE_NO_OPENDIR_SUPPORT;
+               FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA;
        req->in.h.opcode = FUSE_INIT;
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(*arg);
@@ -1393,8 +1394,8 @@ static int __init fuse_init(void)
 {
        int res;
 
-       printk(KERN_INFO "fuse init (API version %i.%i)\n",
-              FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
+       pr_info("init (API version %i.%i)\n",
+               FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
 
        INIT_LIST_HEAD(&fuse_conn_list);
        res = fuse_fs_init();
@@ -1430,7 +1431,7 @@ static int __init fuse_init(void)
 
 static void __exit fuse_exit(void)
 {
-       printk(KERN_DEBUG "fuse exit\n");
+       pr_debug("exit\n");
 
        fuse_ctl_cleanup();
        fuse_sysfs_cleanup();
index 1787d29..08e4996 100644 (file)
@@ -650,7 +650,6 @@ int gfs2_sys_fs_add(struct gfs2_sbd *sdp)
        char ro[20];
        char spectator[20];
        char *envp[] = { ro, spectator, NULL };
-       int sysfs_frees_sdp = 0;
 
        sprintf(ro, "RDONLY=%d", sb_rdonly(sb));
        sprintf(spectator, "SPECTATOR=%d", sdp->sd_args.ar_spectator ? 1 : 0);
@@ -661,8 +660,6 @@ int gfs2_sys_fs_add(struct gfs2_sbd *sdp)
        if (error)
                goto fail_reg;
 
-       sysfs_frees_sdp = 1; /* Freeing sdp is now done by sysfs calling
-                               function gfs2_sbd_release. */
        error = sysfs_create_group(&sdp->sd_kobj, &tune_group);
        if (error)
                goto fail_reg;
@@ -687,10 +684,7 @@ fail_tune:
 fail_reg:
        free_percpu(sdp->sd_lkstats);
        fs_err(sdp, "error %d adding sysfs files\n", error);
-       if (sysfs_frees_sdp)
-               kobject_put(&sdp->sd_kobj);
-       else
-               kfree(sdp);
+       kobject_put(&sdp->sd_kobj);
        sb->s_fs_info = NULL;
        return error;
 }
index c74ef44..1dcc571 100644 (file)
@@ -440,9 +440,7 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
                        u32 hash;
 
                        index = page->index;
-                       hash = hugetlb_fault_mutex_hash(h, current->mm,
-                                                       &pseudo_vma,
-                                                       mapping, index, 0);
+                       hash = hugetlb_fault_mutex_hash(h, mapping, index, 0);
                        mutex_lock(&hugetlb_fault_mutex_table[hash]);
 
                        /*
@@ -499,8 +497,15 @@ static void hugetlbfs_evict_inode(struct inode *inode)
        struct resv_map *resv_map;
 
        remove_inode_hugepages(inode, 0, LLONG_MAX);
-       resv_map = (struct resv_map *)inode->i_mapping->private_data;
-       /* root inode doesn't have the resv_map, so we should check it */
+
+       /*
+        * Get the resv_map from the address space embedded in the inode.
+        * This is the address space which points to any resv_map allocated
+        * at inode creation time.  If this is a device special inode,
+        * i_mapping may not point to the original address space.
+        */
+       resv_map = (struct resv_map *)(&inode->i_data)->private_data;
+       /* Only regular and link inodes have associated reserve maps */
        if (resv_map)
                resv_map_release(&resv_map->refs);
        clear_inode(inode);
@@ -639,8 +644,7 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset,
                addr = index * hpage_size;
 
                /* mutex taken here, fault path and hole punch */
-               hash = hugetlb_fault_mutex_hash(h, mm, &pseudo_vma, mapping,
-                                               index, addr);
+               hash = hugetlb_fault_mutex_hash(h, mapping, index, addr);
                mutex_lock(&hugetlb_fault_mutex_table[hash]);
 
                /* See if already present in mapping to avoid alloc/free */
index 383d208..310f8d1 100644 (file)
@@ -2671,8 +2671,9 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, void __user *arg,
 
                ret = 0;
                down_read(&current->mm->mmap_sem);
-               pret = get_user_pages_longterm(ubuf, nr_pages, FOLL_WRITE,
-                                               pages, vmas);
+               pret = get_user_pages(ubuf, nr_pages,
+                                     FOLL_WRITE | FOLL_LONGTERM,
+                                     pages, vmas);
                if (pret == nr_pages) {
                        /* don't support file backed memory */
                        for (j = 0; j < nr_pages; j++) {
index 70f520b..5fb4f89 100644 (file)
@@ -56,7 +56,7 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
        u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4;
        int status;
 
-       status = lockd_up(nlm_init->net);
+       status = lockd_up(nlm_init->net, nlm_init->cred);
        if (status < 0)
                return ERR_PTR(status);
 
@@ -241,7 +241,7 @@ reclaimer(void *ptr)
        allow_signal(SIGKILL);
 
        down_write(&host->h_rwsem);
-       lockd_up(net);  /* note: this cannot fail as lockd is already running */
+       lockd_up(net, NULL);    /* note: this cannot fail as lockd is already running */
 
        dprintk("lockd: reclaiming locks for host %s\n", host->h_name);
 
index 346ed16..3056f3a 100644 (file)
@@ -188,28 +188,31 @@ lockd(void *vrqstp)
 
 static int create_lockd_listener(struct svc_serv *serv, const char *name,
                                 struct net *net, const int family,
-                                const unsigned short port)
+                                const unsigned short port,
+                                const struct cred *cred)
 {
        struct svc_xprt *xprt;
 
        xprt = svc_find_xprt(serv, name, net, family, 0);
        if (xprt == NULL)
                return svc_create_xprt(serv, name, net, family, port,
-                                               SVC_SOCK_DEFAULTS);
+                                               SVC_SOCK_DEFAULTS, cred);
        svc_xprt_put(xprt);
        return 0;
 }
 
 static int create_lockd_family(struct svc_serv *serv, struct net *net,
-                              const int family)
+                              const int family, const struct cred *cred)
 {
        int err;
 
-       err = create_lockd_listener(serv, "udp", net, family, nlm_udpport);
+       err = create_lockd_listener(serv, "udp", net, family, nlm_udpport,
+                       cred);
        if (err < 0)
                return err;
 
-       return create_lockd_listener(serv, "tcp", net, family, nlm_tcpport);
+       return create_lockd_listener(serv, "tcp", net, family, nlm_tcpport,
+                       cred);
 }
 
 /*
@@ -222,16 +225,17 @@ static int create_lockd_family(struct svc_serv *serv, struct net *net,
  * Returns zero if all listeners are available; otherwise a
  * negative errno value is returned.
  */
-static int make_socks(struct svc_serv *serv, struct net *net)
+static int make_socks(struct svc_serv *serv, struct net *net,
+               const struct cred *cred)
 {
        static int warned;
        int err;
 
-       err = create_lockd_family(serv, net, PF_INET);
+       err = create_lockd_family(serv, net, PF_INET, cred);
        if (err < 0)
                goto out_err;
 
-       err = create_lockd_family(serv, net, PF_INET6);
+       err = create_lockd_family(serv, net, PF_INET6, cred);
        if (err < 0 && err != -EAFNOSUPPORT)
                goto out_err;
 
@@ -246,7 +250,8 @@ out_err:
        return err;
 }
 
-static int lockd_up_net(struct svc_serv *serv, struct net *net)
+static int lockd_up_net(struct svc_serv *serv, struct net *net,
+               const struct cred *cred)
 {
        struct lockd_net *ln = net_generic(net, lockd_net_id);
        int error;
@@ -258,7 +263,7 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net)
        if (error)
                goto err_bind;
 
-       error = make_socks(serv, net);
+       error = make_socks(serv, net, cred);
        if (error < 0)
                goto err_bind;
        set_grace_period(net);
@@ -461,7 +466,7 @@ static struct svc_serv *lockd_create_svc(void)
 /*
  * Bring up the lockd process if it's not already up.
  */
-int lockd_up(struct net *net)
+int lockd_up(struct net *net, const struct cred *cred)
 {
        struct svc_serv *serv;
        int error;
@@ -474,7 +479,7 @@ int lockd_up(struct net *net)
                goto err_create;
        }
 
-       error = lockd_up_net(serv, net);
+       error = lockd_up_net(serv, net, cred);
        if (error < 0) {
                lockd_unregister_notifiers();
                goto err_put;
@@ -807,5 +812,7 @@ static struct svc_program   nlmsvc_program = {
        .pg_name                = "lockd",              /* service name */
        .pg_class               = "nfsd",               /* share authentication with nfsd */
        .pg_stats               = &nlmsvc_stats,        /* stats table */
-       .pg_authenticate = &lockd_authenticate  /* export authentication */
+       .pg_authenticate        = &lockd_authenticate,  /* export authentication */
+       .pg_init_request        = svc_generic_init_request,
+       .pg_rpcbind_set         = svc_generic_rpcbind_set,
 };
index d7c05dd..8af49f8 100644 (file)
@@ -352,6 +352,12 @@ EXPORT_SYMBOL_GPL(locks_alloc_lock);
 
 void locks_release_private(struct file_lock *fl)
 {
+       BUG_ON(waitqueue_active(&fl->fl_wait));
+       BUG_ON(!list_empty(&fl->fl_list));
+       BUG_ON(!list_empty(&fl->fl_blocked_requests));
+       BUG_ON(!list_empty(&fl->fl_blocked_member));
+       BUG_ON(!hlist_unhashed(&fl->fl_link));
+
        if (fl->fl_ops) {
                if (fl->fl_ops->fl_release_private)
                        fl->fl_ops->fl_release_private(fl);
@@ -371,12 +377,6 @@ EXPORT_SYMBOL_GPL(locks_release_private);
 /* Free a lock which is not in use. */
 void locks_free_lock(struct file_lock *fl)
 {
-       BUG_ON(waitqueue_active(&fl->fl_wait));
-       BUG_ON(!list_empty(&fl->fl_list));
-       BUG_ON(!list_empty(&fl->fl_blocked_requests));
-       BUG_ON(!list_empty(&fl->fl_blocked_member));
-       BUG_ON(!hlist_unhashed(&fl->fl_link));
-
        locks_release_private(fl);
        kmem_cache_free(filelock_cache, fl);
 }
index 0b602a3..7817ad9 100644 (file)
@@ -41,11 +41,13 @@ static struct svc_program nfs4_callback_program;
 
 static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net)
 {
+       const struct cred *cred = current_cred();
        int ret;
        struct nfs_net *nn = net_generic(net, nfs_net_id);
 
        ret = svc_create_xprt(serv, "tcp", net, PF_INET,
-                               nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
+                               nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
+                               cred);
        if (ret <= 0)
                goto out_err;
        nn->nfs_callback_tcpport = ret;
@@ -53,7 +55,8 @@ static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net)
                nn->nfs_callback_tcpport, PF_INET, net->ns.inum);
 
        ret = svc_create_xprt(serv, "tcp", net, PF_INET6,
-                               nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
+                               nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
+                               cred);
        if (ret > 0) {
                nn->nfs_callback_tcpport6 = ret;
                dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
@@ -457,4 +460,6 @@ static struct svc_program nfs4_callback_program = {
        .pg_class = "nfs",                              /* authentication class */
        .pg_stats = &nfs4_callback_stats,
        .pg_authenticate = nfs_callback_authenticate,
+       .pg_init_request = svc_generic_init_request,
+       .pg_rpcbind_set = svc_generic_rpcbind_set,
 };
index 06233bf..73a5a5e 100644 (file)
@@ -983,7 +983,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp)
 
 out_invalidcred:
        pr_warn_ratelimited("NFS: NFSv4 callback contains invalid cred\n");
-       return rpc_autherr_badcred;
+       return svc_return_autherr(rqstp, rpc_autherr_badcred);
 }
 
 /*
index da74c4c..3d04cb0 100644 (file)
@@ -558,6 +558,7 @@ static int nfs_start_lockd(struct nfs_server *server)
                                        1 : 0,
                .net            = clp->cl_net,
                .nlmclnt_ops    = clp->cl_nfs_mod->rpc_ops->nlmclnt_ops,
+               .cred           = current_cred(),
        };
 
        if (nlm_init.nfs_version > 3)
index a7d3df8..e6a700f 100644 (file)
@@ -22,7 +22,7 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen,
        char *ip_addr = NULL;
        int ip_len;
 
-       ip_len = dns_query(NULL, name, namelen, NULL, &ip_addr, NULL);
+       ip_len = dns_query(NULL, name, namelen, NULL, &ip_addr, NULL, false);
        if (ip_len > 0)
                ret = rpc_pton(net, ip_addr, ip_len, sa, salen);
        else
index 802993d..baa0195 100644 (file)
@@ -570,13 +570,13 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
                err = get_int(&mesg, &an_int);
                if (err)
                        goto out3;
-               exp.ex_anon_uid= make_kuid(&init_user_ns, an_int);
+               exp.ex_anon_uid= make_kuid(current_user_ns(), an_int);
 
                /* anon gid */
                err = get_int(&mesg, &an_int);
                if (err)
                        goto out3;
-               exp.ex_anon_gid= make_kgid(&init_user_ns, an_int);
+               exp.ex_anon_gid= make_kgid(current_user_ns(), an_int);
 
                /* fsid */
                err = get_int(&mesg, &an_int);
@@ -1170,15 +1170,17 @@ static void show_secinfo(struct seq_file *m, struct svc_export *exp)
 static void exp_flags(struct seq_file *m, int flag, int fsid,
                kuid_t anonu, kgid_t anong, struct nfsd4_fs_locations *fsloc)
 {
+       struct user_namespace *userns = m->file->f_cred->user_ns;
+
        show_expflags(m, flag, NFSEXP_ALLFLAGS);
        if (flag & NFSEXP_FSID)
                seq_printf(m, ",fsid=%d", fsid);
-       if (!uid_eq(anonu, make_kuid(&init_user_ns, (uid_t)-2)) &&
-           !uid_eq(anonu, make_kuid(&init_user_ns, 0x10000-2)))
-               seq_printf(m, ",anonuid=%u", from_kuid(&init_user_ns, anonu));
-       if (!gid_eq(anong, make_kgid(&init_user_ns, (gid_t)-2)) &&
-           !gid_eq(anong, make_kgid(&init_user_ns, 0x10000-2)))
-               seq_printf(m, ",anongid=%u", from_kgid(&init_user_ns, anong));
+       if (!uid_eq(anonu, make_kuid(userns, (uid_t)-2)) &&
+           !uid_eq(anonu, make_kuid(userns, 0x10000-2)))
+               seq_printf(m, ",anonuid=%u", from_kuid_munged(userns, anonu));
+       if (!gid_eq(anong, make_kgid(userns, (gid_t)-2)) &&
+           !gid_eq(anong, make_kgid(userns, 0x10000-2)))
+               seq_printf(m, ",anongid=%u", from_kgid_munged(userns, anong));
        if (fsloc && fsloc->locations_count > 0) {
                char *loctype = (fsloc->migrated) ? "refer" : "replicas";
                int i;
index 32cb8c0..789abc4 100644 (file)
@@ -104,6 +104,9 @@ struct nfsd_net {
        time_t nfsd4_grace;
        bool somebody_reclaimed;
 
+       bool track_reclaim_completes;
+       atomic_t nr_reclaim_complete;
+
        bool nfsd_net_up;
        bool lockd_up;
 
@@ -131,10 +134,18 @@ struct nfsd_net {
        u32             s2s_cp_cl_id;
        struct idr      s2s_cp_stateids;
        spinlock_t      s2s_cp_lock;
+
+       /*
+        * Version information
+        */
+       bool *nfsd_versions;
+       bool *nfsd4_minorversions;
 };
 
 /* Simple check to find out if a given net was properly initialized */
 #define nfsd_netns_ready(nn) ((nn)->sessionid_hashtbl)
 
+extern void nfsd_netns_free_versions(struct nfsd_net *nn);
+
 extern unsigned int nfsd_net_id;
 #endif /* __NFSD_NETNS_H__ */
index 8d78912..fcf3182 100644 (file)
@@ -96,7 +96,7 @@ decode_filename(__be32 *p, char **namp, unsigned int *lenp)
 }
 
 static __be32 *
-decode_sattr3(__be32 *p, struct iattr *iap)
+decode_sattr3(__be32 *p, struct iattr *iap, struct user_namespace *userns)
 {
        u32     tmp;
 
@@ -107,12 +107,12 @@ decode_sattr3(__be32 *p, struct iattr *iap)
                iap->ia_mode = ntohl(*p++);
        }
        if (*p++) {
-               iap->ia_uid = make_kuid(&init_user_ns, ntohl(*p++));
+               iap->ia_uid = make_kuid(userns, ntohl(*p++));
                if (uid_valid(iap->ia_uid))
                        iap->ia_valid |= ATTR_UID;
        }
        if (*p++) {
-               iap->ia_gid = make_kgid(&init_user_ns, ntohl(*p++));
+               iap->ia_gid = make_kgid(userns, ntohl(*p++));
                if (gid_valid(iap->ia_gid))
                        iap->ia_valid |= ATTR_GID;
        }
@@ -165,12 +165,13 @@ static __be32 *
 encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
              struct kstat *stat)
 {
+       struct user_namespace *userns = nfsd_user_namespace(rqstp);
        struct timespec ts;
        *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
        *p++ = htonl((u32) (stat->mode & S_IALLUGO));
        *p++ = htonl((u32) stat->nlink);
-       *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid));
-       *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid));
+       *p++ = htonl((u32) from_kuid_munged(userns, stat->uid));
+       *p++ = htonl((u32) from_kgid_munged(userns, stat->gid));
        if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) {
                p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
        } else {
@@ -325,7 +326,7 @@ nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
        p = decode_fh(p, &args->fh);
        if (!p)
                return 0;
-       p = decode_sattr3(p, &args->attrs);
+       p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
 
        if ((args->check_guard = ntohl(*p++)) != 0) { 
                struct timespec time; 
@@ -455,7 +456,7 @@ nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
        switch (args->createmode = ntohl(*p++)) {
        case NFS3_CREATE_UNCHECKED:
        case NFS3_CREATE_GUARDED:
-               p = decode_sattr3(p, &args->attrs);
+               p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
                break;
        case NFS3_CREATE_EXCLUSIVE:
                args->verf = p;
@@ -476,7 +477,7 @@ nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p)
        if (!(p = decode_fh(p, &args->fh)) ||
            !(p = decode_filename(p, &args->name, &args->len)))
                return 0;
-       p = decode_sattr3(p, &args->attrs);
+       p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
 
        return xdr_argsize_check(rqstp, p);
 }
@@ -491,7 +492,7 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
        if (!(p = decode_fh(p, &args->ffh)) ||
            !(p = decode_filename(p, &args->fname, &args->flen)))
                return 0;
-       p = decode_sattr3(p, &args->attrs);
+       p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
 
        args->tlen = ntohl(*p++);
 
@@ -519,7 +520,7 @@ nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p)
 
        if (args->ftype == NF3BLK  || args->ftype == NF3CHR
         || args->ftype == NF3SOCK || args->ftype == NF3FIFO)
-               p = decode_sattr3(p, &args->attrs);
+               p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
 
        if (args->ftype == NF3BLK || args->ftype == NF3CHR) {
                args->major = ntohl(*p++);
index 9b93e7a..397eb78 100644 (file)
@@ -1123,10 +1123,11 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
                rpc_restart_call_prepare(task);
                return;
        case 1:
-               break;
-       case -1:
-               /* Network partition? */
-               nfsd4_mark_cb_down(clp, task->tk_status);
+               switch (task->tk_status) {
+               case -EIO:
+               case -ETIMEDOUT:
+                       nfsd4_mark_cb_down(clp, task->tk_status);
+               }
                break;
        default:
                BUG();
index bf137fe..2961016 100644 (file)
@@ -634,7 +634,7 @@ nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
                return nfserr_inval;
 
        status = do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, &id);
-       *uid = make_kuid(&init_user_ns, id);
+       *uid = make_kuid(nfsd_user_namespace(rqstp), id);
        if (!uid_valid(*uid))
                status = nfserr_badowner;
        return status;
@@ -651,7 +651,7 @@ nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
                return nfserr_inval;
 
        status = do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, &id);
-       *gid = make_kgid(&init_user_ns, id);
+       *gid = make_kgid(nfsd_user_namespace(rqstp), id);
        if (!gid_valid(*gid))
                status = nfserr_badowner;
        return status;
@@ -660,13 +660,13 @@ nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
 __be32 nfsd4_encode_user(struct xdr_stream *xdr, struct svc_rqst *rqstp,
                         kuid_t uid)
 {
-       u32 id = from_kuid(&init_user_ns, uid);
+       u32 id = from_kuid_munged(nfsd_user_namespace(rqstp), uid);
        return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_USER, id);
 }
 
 __be32 nfsd4_encode_group(struct xdr_stream *xdr, struct svc_rqst *rqstp,
                          kgid_t gid)
 {
-       u32 id = from_kgid(&init_user_ns, gid);
+       u32 id = from_kgid_munged(nfsd_user_namespace(rqstp), gid);
        return encode_name_from_id(xdr, rqstp, IDMAP_TYPE_GROUP, id);
 }
index 44517fb..a79e24b 100644 (file)
@@ -693,7 +693,7 @@ nfsd4_cb_layout_done(struct nfsd4_callback *cb, struct rpc_task *task)
                        ops->fence_client(ls);
                else
                        nfsd4_cb_layout_fail(ls);
-               return -1;
+               return 1;
        case -NFS4ERR_NOMATCHING_LAYOUT:
                trace_nfsd_layout_recall_done(&ls->ls_stid.sc_stateid);
                task->tk_status = 0;
index 4680ad3..8beda99 100644 (file)
@@ -1927,6 +1927,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
        struct nfsd4_compound_state *cstate = &resp->cstate;
        struct svc_fh *current_fh = &cstate->current_fh;
        struct svc_fh *save_fh = &cstate->save_fh;
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
        __be32          status;
 
        svcxdr_init_encode(rqstp, resp);
@@ -1949,7 +1950,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
         * According to RFC3010, this takes precedence over all other errors.
         */
        status = nfserr_minor_vers_mismatch;
-       if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0)
+       if (nfsd_minorversion(nn, args->minorversion, NFSD_TEST) <= 0)
                goto out;
        status = nfserr_resource;
        if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
index 8c85634..8767955 100644 (file)
@@ -168,13 +168,34 @@ legacy_recdir_name_error(struct nfs4_client *clp, int error)
        }
 }
 
+static void
+__nfsd4_create_reclaim_record_grace(struct nfs4_client *clp,
+               const char *dname, int len, struct nfsd_net *nn)
+{
+       struct xdr_netobj name;
+       struct nfs4_client_reclaim *crp;
+
+       name.data = kmemdup(dname, len, GFP_KERNEL);
+       if (!name.data) {
+               dprintk("%s: failed to allocate memory for name.data!\n",
+                       __func__);
+               return;
+       }
+       name.len = len;
+       crp = nfs4_client_to_reclaim(name, nn);
+       if (!crp) {
+               kfree(name.data);
+               return;
+       }
+       crp->cr_clp = clp;
+}
+
 static void
 nfsd4_create_clid_dir(struct nfs4_client *clp)
 {
        const struct cred *original_cred;
        char dname[HEXDIR_LEN];
        struct dentry *dir, *dentry;
-       struct nfs4_client_reclaim *crp;
        int status;
        struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
@@ -220,11 +241,9 @@ out_put:
 out_unlock:
        inode_unlock(d_inode(dir));
        if (status == 0) {
-               if (nn->in_grace) {
-                       crp = nfs4_client_to_reclaim(dname, nn);
-                       if (crp)
-                               crp->cr_clp = clp;
-               }
+               if (nn->in_grace)
+                       __nfsd4_create_reclaim_record_grace(clp, dname,
+                                       HEXDIR_LEN, nn);
                vfs_fsync(nn->rec_file, 0);
        } else {
                printk(KERN_ERR "NFSD: failed to write recovery record"
@@ -344,11 +363,30 @@ out_unlock:
        return status;
 }
 
+static void
+__nfsd4_remove_reclaim_record_grace(const char *dname, int len,
+               struct nfsd_net *nn)
+{
+       struct xdr_netobj name;
+       struct nfs4_client_reclaim *crp;
+
+       name.data = kmemdup(dname, len, GFP_KERNEL);
+       if (!name.data) {
+               dprintk("%s: failed to allocate memory for name.data!\n",
+                       __func__);
+               return;
+       }
+       name.len = len;
+       crp = nfsd4_find_reclaim_client(name, nn);
+       kfree(name.data);
+       if (crp)
+               nfs4_remove_reclaim_record(crp, nn);
+}
+
 static void
 nfsd4_remove_clid_dir(struct nfs4_client *clp)
 {
        const struct cred *original_cred;
-       struct nfs4_client_reclaim *crp;
        char dname[HEXDIR_LEN];
        int status;
        struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
@@ -373,12 +411,9 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
        nfs4_reset_creds(original_cred);
        if (status == 0) {
                vfs_fsync(nn->rec_file, 0);
-               if (nn->in_grace) {
-                       /* remove reclaim record */
-                       crp = nfsd4_find_reclaim_client(dname, nn);
-                       if (crp)
-                               nfs4_remove_reclaim_record(crp, nn);
-               }
+               if (nn->in_grace)
+                       __nfsd4_remove_reclaim_record_grace(dname,
+                                       HEXDIR_LEN, nn);
        }
 out_drop_write:
        mnt_drop_write_file(nn->rec_file);
@@ -392,14 +427,31 @@ static int
 purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
 {
        int status;
+       struct xdr_netobj name;
 
-       if (nfs4_has_reclaimed_state(child->d_name.name, nn))
+       if (child->d_name.len != HEXDIR_LEN - 1) {
+               printk("%s: illegal name %pd in recovery directory\n",
+                               __func__, child);
+               /* Keep trying; maybe the others are OK: */
                return 0;
+       }
+       name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL);
+       if (!name.data) {
+               dprintk("%s: failed to allocate memory for name.data!\n",
+                       __func__);
+               goto out;
+       }
+       name.len = HEXDIR_LEN;
+       if (nfs4_has_reclaimed_state(name, nn))
+               goto out_free;
 
        status = vfs_rmdir(d_inode(parent), child);
        if (status)
                printk("failed to remove client recovery directory %pd\n",
                                child);
+out_free:
+       kfree(name.data);
+out:
        /* Keep trying, success or failure: */
        return 0;
 }
@@ -429,13 +481,24 @@ out:
 static int
 load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
 {
+       struct xdr_netobj name;
+
        if (child->d_name.len != HEXDIR_LEN - 1) {
-               printk("nfsd4: illegal name %pd in recovery directory\n",
-                               child);
+               printk("%s: illegal name %pd in recovery directory\n",
+                               __func__, child);
                /* Keep trying; maybe the others are OK: */
                return 0;
        }
-       nfs4_client_to_reclaim(child->d_name.name, nn);
+       name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL);
+       if (!name.data) {
+               dprintk("%s: failed to allocate memory for name.data!\n",
+                       __func__);
+               goto out;
+       }
+       name.len = HEXDIR_LEN;
+       if (!nfs4_client_to_reclaim(name, nn))
+               kfree(name.data);
+out:
        return 0;
 }
 
@@ -564,6 +627,7 @@ nfsd4_legacy_tracking_init(struct net *net)
        status = nfsd4_load_reboot_recovery_data(net);
        if (status)
                goto err;
+       printk("NFSD: Using legacy client tracking operations.\n");
        return 0;
 
 err:
@@ -615,6 +679,7 @@ nfsd4_check_legacy_client(struct nfs4_client *clp)
        char dname[HEXDIR_LEN];
        struct nfs4_client_reclaim *crp;
        struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+       struct xdr_netobj name;
 
        /* did we already find that this client is stable? */
        if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
@@ -627,13 +692,22 @@ nfsd4_check_legacy_client(struct nfs4_client *clp)
        }
 
        /* look for it in the reclaim hashtable otherwise */
-       crp = nfsd4_find_reclaim_client(dname, nn);
+       name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
+       if (!name.data) {
+               dprintk("%s: failed to allocate memory for name.data!\n",
+                       __func__);
+               goto out_enoent;
+       }
+       name.len = HEXDIR_LEN;
+       crp = nfsd4_find_reclaim_client(name, nn);
+       kfree(name.data);
        if (crp) {
                set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
                crp->cr_clp = clp;
                return 0;
        }
 
+out_enoent:
        return -ENOENT;
 }
 
@@ -656,6 +730,7 @@ struct cld_net {
        spinlock_t               cn_lock;
        struct list_head         cn_list;
        unsigned int             cn_xid;
+       bool                     cn_has_legacy;
 };
 
 struct cld_upcall {
@@ -705,6 +780,40 @@ cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg)
        return ret;
 }
 
+static ssize_t
+__cld_pipe_inprogress_downcall(const struct cld_msg __user *cmsg,
+               struct nfsd_net *nn)
+{
+       uint8_t cmd;
+       struct xdr_netobj name;
+       uint16_t namelen;
+       struct cld_net *cn = nn->cld_net;
+
+       if (get_user(cmd, &cmsg->cm_cmd)) {
+               dprintk("%s: error when copying cmd from userspace", __func__);
+               return -EFAULT;
+       }
+       if (cmd == Cld_GraceStart) {
+               if (get_user(namelen, &cmsg->cm_u.cm_name.cn_len))
+                       return -EFAULT;
+               name.data = memdup_user(&cmsg->cm_u.cm_name.cn_id, namelen);
+               if (IS_ERR_OR_NULL(name.data))
+                       return -EFAULT;
+               name.len = namelen;
+               if (name.len > 5 && memcmp(name.data, "hash:", 5) == 0) {
+                       name.len = name.len - 5;
+                       memmove(name.data, name.data + 5, name.len);
+                       cn->cn_has_legacy = true;
+               }
+               if (!nfs4_client_to_reclaim(name, nn)) {
+                       kfree(name.data);
+                       return -EFAULT;
+               }
+               return sizeof(*cmsg);
+       }
+       return -EFAULT;
+}
+
 static ssize_t
 cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
 {
@@ -714,6 +823,7 @@ cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
        struct nfsd_net *nn = net_generic(file_inode(filp)->i_sb->s_fs_info,
                                                nfsd_net_id);
        struct cld_net *cn = nn->cld_net;
+       int16_t status;
 
        if (mlen != sizeof(*cmsg)) {
                dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen,
@@ -727,13 +837,24 @@ cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
                return -EFAULT;
        }
 
+       /*
+        * copy the status so we know whether to remove the upcall from the
+        * list (for -EINPROGRESS, we just want to make sure the xid is
+        * valid, not remove the upcall from the list)
+        */
+       if (get_user(status, &cmsg->cm_status)) {
+               dprintk("%s: error when copying status from userspace", __func__);
+               return -EFAULT;
+       }
+
        /* walk the list and find corresponding xid */
        cup = NULL;
        spin_lock(&cn->cn_lock);
        list_for_each_entry(tmp, &cn->cn_list, cu_list) {
                if (get_unaligned(&tmp->cu_msg.cm_xid) == xid) {
                        cup = tmp;
-                       list_del_init(&cup->cu_list);
+                       if (status != -EINPROGRESS)
+                               list_del_init(&cup->cu_list);
                        break;
                }
        }
@@ -745,6 +866,9 @@ cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
                return -EINVAL;
        }
 
+       if (status == -EINPROGRESS)
+               return __cld_pipe_inprogress_downcall(cmsg, nn);
+
        if (copy_from_user(&cup->cu_msg, src, mlen) != 0)
                return -EFAULT;
 
@@ -820,7 +944,7 @@ nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe)
 
 /* Initialize rpc_pipefs pipe for communication with client tracking daemon */
 static int
-nfsd4_init_cld_pipe(struct net *net)
+__nfsd4_init_cld_pipe(struct net *net)
 {
        int ret;
        struct dentry *dentry;
@@ -851,6 +975,7 @@ nfsd4_init_cld_pipe(struct net *net)
        }
 
        cn->cn_pipe->dentry = dentry;
+       cn->cn_has_legacy = false;
        nn->cld_net = cn;
        return 0;
 
@@ -863,6 +988,17 @@ err:
        return ret;
 }
 
+static int
+nfsd4_init_cld_pipe(struct net *net)
+{
+       int status;
+
+       status = __nfsd4_init_cld_pipe(net);
+       if (!status)
+               printk("NFSD: Using old nfsdcld client tracking operations.\n");
+       return status;
+}
+
 static void
 nfsd4_remove_cld_pipe(struct net *net)
 {
@@ -991,9 +1127,14 @@ out_err:
                                "record from stable storage: %d\n", ret);
 }
 
-/* Check for presence of a record, and update its timestamp */
+/*
+ * For older nfsdcld's that do not allow us to "slurp" the clients
+ * from the tracking database during startup.
+ *
+ * Check for presence of a record, and update its timestamp
+ */
 static int
-nfsd4_cld_check(struct nfs4_client *clp)
+nfsd4_cld_check_v0(struct nfs4_client *clp)
 {
        int ret;
        struct cld_upcall *cup;
@@ -1026,8 +1167,84 @@ nfsd4_cld_check(struct nfs4_client *clp)
        return ret;
 }
 
+/*
+ * For newer nfsdcld's that allow us to "slurp" the clients
+ * from the tracking database during startup.
+ *
+ * Check for presence of a record in the reclaim_str_hashtbl
+ */
+static int
+nfsd4_cld_check(struct nfs4_client *clp)
+{
+       struct nfs4_client_reclaim *crp;
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+       struct cld_net *cn = nn->cld_net;
+       int status;
+       char dname[HEXDIR_LEN];
+       struct xdr_netobj name;
+
+       /* did we already find that this client is stable? */
+       if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
+               return 0;
+
+       /* look for it in the reclaim hashtable otherwise */
+       crp = nfsd4_find_reclaim_client(clp->cl_name, nn);
+       if (crp)
+               goto found;
+
+       if (cn->cn_has_legacy) {
+               status = nfs4_make_rec_clidname(dname, &clp->cl_name);
+               if (status)
+                       return -ENOENT;
+
+               name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
+               if (!name.data) {
+                       dprintk("%s: failed to allocate memory for name.data!\n",
+                               __func__);
+                       return -ENOENT;
+               }
+               name.len = HEXDIR_LEN;
+               crp = nfsd4_find_reclaim_client(name, nn);
+               kfree(name.data);
+               if (crp)
+                       goto found;
+
+       }
+       return -ENOENT;
+found:
+       crp->cr_clp = clp;
+       return 0;
+}
+
+static int
+nfsd4_cld_grace_start(struct nfsd_net *nn)
+{
+       int ret;
+       struct cld_upcall *cup;
+       struct cld_net *cn = nn->cld_net;
+
+       cup = alloc_cld_upcall(cn);
+       if (!cup) {
+               ret = -ENOMEM;
+               goto out_err;
+       }
+
+       cup->cu_msg.cm_cmd = Cld_GraceStart;
+       ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
+       if (!ret)
+               ret = cup->cu_msg.cm_status;
+
+       free_cld_upcall(cup);
+out_err:
+       if (ret)
+               dprintk("%s: Unable to get clients from userspace: %d\n",
+                       __func__, ret);
+       return ret;
+}
+
+/* For older nfsdcld's that need cm_gracetime */
 static void
-nfsd4_cld_grace_done(struct nfsd_net *nn)
+nfsd4_cld_grace_done_v0(struct nfsd_net *nn)
 {
        int ret;
        struct cld_upcall *cup;
@@ -1051,11 +1268,149 @@ out_err:
                printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
 }
 
-static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
+/*
+ * For newer nfsdcld's that do not need cm_gracetime.  We also need to call
+ * nfs4_release_reclaim() to clear out the reclaim_str_hashtbl.
+ */
+static void
+nfsd4_cld_grace_done(struct nfsd_net *nn)
+{
+       int ret;
+       struct cld_upcall *cup;
+       struct cld_net *cn = nn->cld_net;
+
+       cup = alloc_cld_upcall(cn);
+       if (!cup) {
+               ret = -ENOMEM;
+               goto out_err;
+       }
+
+       cup->cu_msg.cm_cmd = Cld_GraceDone;
+       ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
+       if (!ret)
+               ret = cup->cu_msg.cm_status;
+
+       free_cld_upcall(cup);
+out_err:
+       nfs4_release_reclaim(nn);
+       if (ret)
+               printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
+}
+
+static int
+nfs4_cld_state_init(struct net *net)
+{
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       int i;
+
+       nn->reclaim_str_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
+                                               sizeof(struct list_head),
+                                               GFP_KERNEL);
+       if (!nn->reclaim_str_hashtbl)
+               return -ENOMEM;
+
+       for (i = 0; i < CLIENT_HASH_SIZE; i++)
+               INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]);
+       nn->reclaim_str_hashtbl_size = 0;
+       nn->track_reclaim_completes = true;
+       atomic_set(&nn->nr_reclaim_complete, 0);
+
+       return 0;
+}
+
+static void
+nfs4_cld_state_shutdown(struct net *net)
+{
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+       nn->track_reclaim_completes = false;
+       kfree(nn->reclaim_str_hashtbl);
+}
+
+static bool
+cld_running(struct nfsd_net *nn)
+{
+       struct cld_net *cn = nn->cld_net;
+       struct rpc_pipe *pipe = cn->cn_pipe;
+
+       return pipe->nreaders || pipe->nwriters;
+}
+
+static int
+nfsd4_cld_tracking_init(struct net *net)
+{
+       int status;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       bool running;
+       int retries = 10;
+
+       status = nfs4_cld_state_init(net);
+       if (status)
+               return status;
+
+       status = __nfsd4_init_cld_pipe(net);
+       if (status)
+               goto err_shutdown;
+
+       /*
+        * rpc pipe upcalls take 30 seconds to time out, so we don't want to
+        * queue an upcall unless we know that nfsdcld is running (because we
+        * want this to fail fast so that nfsd4_client_tracking_init() can try
+        * the next client tracking method).  nfsdcld should already be running
+        * before nfsd is started, so the wait here is for nfsdcld to open the
+        * pipefs file we just created.
+        */
+       while (!(running = cld_running(nn)) && retries--)
+               msleep(100);
+
+       if (!running) {
+               status = -ETIMEDOUT;
+               goto err_remove;
+       }
+
+       status = nfsd4_cld_grace_start(nn);
+       if (status) {
+               if (status == -EOPNOTSUPP)
+                       printk(KERN_WARNING "NFSD: Please upgrade nfsdcld.\n");
+               nfs4_release_reclaim(nn);
+               goto err_remove;
+       } else
+               printk("NFSD: Using nfsdcld client tracking operations.\n");
+       return 0;
+
+err_remove:
+       nfsd4_remove_cld_pipe(net);
+err_shutdown:
+       nfs4_cld_state_shutdown(net);
+       return status;
+}
+
+static void
+nfsd4_cld_tracking_exit(struct net *net)
+{
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+       nfs4_release_reclaim(nn);
+       nfsd4_remove_cld_pipe(net);
+       nfs4_cld_state_shutdown(net);
+}
+
+/* For older nfsdcld's */
+static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v0 = {
        .init           = nfsd4_init_cld_pipe,
        .exit           = nfsd4_remove_cld_pipe,
        .create         = nfsd4_cld_create,
        .remove         = nfsd4_cld_remove,
+       .check          = nfsd4_cld_check_v0,
+       .grace_done     = nfsd4_cld_grace_done_v0,
+};
+
+/* For newer nfsdcld's */
+static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
+       .init           = nfsd4_cld_tracking_init,
+       .exit           = nfsd4_cld_tracking_exit,
+       .create         = nfsd4_cld_create,
+       .remove         = nfsd4_cld_remove,
        .check          = nfsd4_cld_check,
        .grace_done     = nfsd4_cld_grace_done,
 };
@@ -1267,6 +1622,8 @@ nfsd4_umh_cltrack_init(struct net *net)
 
        ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL);
        kfree(grace_start);
+       if (!ret)
+               printk("NFSD: Using UMH upcall client tracking operations.\n");
        return ret;
 }
 
@@ -1416,9 +1773,20 @@ nfsd4_client_tracking_init(struct net *net)
        if (nn->client_tracking_ops)
                goto do_init;
 
+       /* First, try to use nfsdcld */
+       nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
+       status = nn->client_tracking_ops->init(net);
+       if (!status)
+               return status;
+       if (status != -ETIMEDOUT) {
+               nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v0;
+               status = nn->client_tracking_ops->init(net);
+               if (!status)
+                       return status;
+       }
+
        /*
-        * First, try a UMH upcall. It should succeed or fail quickly, so
-        * there's little harm in trying that first.
+        * Next, try the UMH upcall.
         */
        nn->client_tracking_ops = &nfsd4_umh_tracking_ops;
        status = nn->client_tracking_ops->init(net);
@@ -1426,25 +1794,23 @@ nfsd4_client_tracking_init(struct net *net)
                return status;
 
        /*
-        * See if the recoverydir exists and is a directory. If it is,
-        * then use the legacy ops.
+        * Finally, See if the recoverydir exists and is a directory.
+        * If it is, then use the legacy ops.
         */
        nn->client_tracking_ops = &nfsd4_legacy_tracking_ops;
        status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path);
        if (!status) {
                status = d_is_dir(path.dentry);
                path_put(&path);
-               if (status)
-                       goto do_init;
+               if (!status) {
+                       status = -EINVAL;
+                       goto out;
+               }
        }
 
-       /* Finally, try to use nfsdcld */
-       nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
-       printk(KERN_WARNING "NFSD: the nfsdcld client tracking upcall will be "
-                       "removed in 3.10. Please transition to using "
-                       "nfsdcltrack.\n");
 do_init:
        status = nn->client_tracking_ops->init(net);
+out:
        if (status) {
                printk(KERN_WARNING "NFSD: Unable to initialize client "
                                    "recovery tracking! (%d)\n", status);
index eca4a23..618e660 100644 (file)
@@ -77,6 +77,7 @@ static u64 current_sessionid = 1;
 /* forward declarations */
 static bool check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner);
 static void nfs4_free_ol_stateid(struct nfs4_stid *stid);
+void nfsd4_end_grace(struct nfsd_net *nn);
 
 /* Locking: */
 
@@ -1067,9 +1068,9 @@ static unsigned int clientid_hashval(u32 id)
        return id & CLIENT_HASH_MASK;
 }
 
-static unsigned int clientstr_hashval(const char *name)
+static unsigned int clientstr_hashval(struct xdr_netobj name)
 {
-       return opaque_hashval(name, 8) & CLIENT_HASH_MASK;
+       return opaque_hashval(name.data, 8) & CLIENT_HASH_MASK;
 }
 
 /*
@@ -1997,6 +1998,22 @@ destroy_client(struct nfs4_client *clp)
        __destroy_client(clp);
 }
 
+static void inc_reclaim_complete(struct nfs4_client *clp)
+{
+       struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+       if (!nn->track_reclaim_completes)
+               return;
+       if (!nfsd4_find_reclaim_client(clp->cl_name, nn))
+               return;
+       if (atomic_inc_return(&nn->nr_reclaim_complete) ==
+                       nn->reclaim_str_hashtbl_size) {
+               printk(KERN_INFO "NFSD: all clients done reclaiming, ending NFSv4 grace period (net %x)\n",
+                               clp->net->ns.inum);
+               nfsd4_end_grace(nn);
+       }
+}
+
 static void expire_client(struct nfs4_client *clp)
 {
        unhash_client(clp);
@@ -2048,11 +2065,6 @@ compare_blob(const struct xdr_netobj *o1, const struct xdr_netobj *o2)
        return memcmp(o1->data, o2->data, o1->len);
 }
 
-static int same_name(const char *n1, const char *n2)
-{
-       return 0 == memcmp(n1, n2, HEXDIR_LEN);
-}
-
 static int
 same_verf(nfs4_verifier *v1, nfs4_verifier *v2)
 {
@@ -3354,6 +3366,7 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp,
 
        status = nfs_ok;
        nfsd4_client_record_create(cstate->session->se_client);
+       inc_reclaim_complete(cstate->session->se_client);
 out:
        return status;
 }
@@ -3958,6 +3971,9 @@ static int nfsd4_cb_recall_done(struct nfsd4_callback *cb,
        switch (task->tk_status) {
        case 0:
                return 1;
+       case -NFS4ERR_DELAY:
+               rpc_delay(task, 2 * HZ);
+               return 0;
        case -EBADHANDLE:
        case -NFS4ERR_BAD_STATEID:
                /*
@@ -3970,7 +3986,7 @@ static int nfsd4_cb_recall_done(struct nfsd4_callback *cb,
                }
                /*FALLTHRU*/
        default:
-               return -1;
+               return 1;
        }
 }
 
@@ -4713,7 +4729,6 @@ nfsd4_end_grace(struct nfsd_net *nn)
        if (nn->grace_ended)
                return;
 
-       dprintk("NFSD: end of grace period\n");
        nn->grace_ended = true;
        /*
         * If the server goes down again right now, an NFSv4
@@ -4749,6 +4764,10 @@ static bool clients_still_reclaiming(struct nfsd_net *nn)
        unsigned long double_grace_period_end = nn->boot_time +
                                                2 * nn->nfsd4_lease;
 
+       if (nn->track_reclaim_completes &&
+                       atomic_read(&nn->nr_reclaim_complete) ==
+                       nn->reclaim_str_hashtbl_size)
+               return false;
        if (!nn->somebody_reclaimed)
                return false;
        nn->somebody_reclaimed = false;
@@ -4779,6 +4798,7 @@ nfs4_laundromat(struct nfsd_net *nn)
                new_timeo = 0;
                goto out;
        }
+       dprintk("NFSD: end of grace period\n");
        nfsd4_end_grace(nn);
        INIT_LIST_HEAD(&reaplist);
        spin_lock(&nn->client_lock);
@@ -6458,7 +6478,7 @@ alloc_reclaim(void)
 }
 
 bool
-nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn)
+nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn)
 {
        struct nfs4_client_reclaim *crp;
 
@@ -6468,20 +6488,24 @@ nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn)
 
 /*
  * failure => all reset bets are off, nfserr_no_grace...
+ *
+ * The caller is responsible for freeing name.data if NULL is returned (it
+ * will be freed in nfs4_remove_reclaim_record in the normal case).
  */
 struct nfs4_client_reclaim *
-nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn)
+nfs4_client_to_reclaim(struct xdr_netobj name, struct nfsd_net *nn)
 {
        unsigned int strhashval;
        struct nfs4_client_reclaim *crp;
 
-       dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name);
+       dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", name.len, name.data);
        crp = alloc_reclaim();
        if (crp) {
                strhashval = clientstr_hashval(name);
                INIT_LIST_HEAD(&crp->cr_strhash);
                list_add(&crp->cr_strhash, &nn->reclaim_str_hashtbl[strhashval]);
-               memcpy(crp->cr_recdir, name, HEXDIR_LEN);
+               crp->cr_name.data = name.data;
+               crp->cr_name.len = name.len;
                crp->cr_clp = NULL;
                nn->reclaim_str_hashtbl_size++;
        }
@@ -6492,6 +6516,7 @@ void
 nfs4_remove_reclaim_record(struct nfs4_client_reclaim *crp, struct nfsd_net *nn)
 {
        list_del(&crp->cr_strhash);
+       kfree(crp->cr_name.data);
        kfree(crp);
        nn->reclaim_str_hashtbl_size--;
 }
@@ -6515,16 +6540,16 @@ nfs4_release_reclaim(struct nfsd_net *nn)
 /*
  * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
 struct nfs4_client_reclaim *
-nfsd4_find_reclaim_client(const char *recdir, struct nfsd_net *nn)
+nfsd4_find_reclaim_client(struct xdr_netobj name, struct nfsd_net *nn)
 {
        unsigned int strhashval;
        struct nfs4_client_reclaim *crp = NULL;
 
-       dprintk("NFSD: nfs4_find_reclaim_client for recdir %s\n", recdir);
+       dprintk("NFSD: nfs4_find_reclaim_client for name %.*s\n", name.len, name.data);
 
-       strhashval = clientstr_hashval(recdir);
+       strhashval = clientstr_hashval(name);
        list_for_each_entry(crp, &nn->reclaim_str_hashtbl[strhashval], cr_strhash) {
-               if (same_name(crp->cr_recdir, recdir)) {
+               if (compare_blob(&crp->cr_name, &name) == 0) {
                        return crp;
                }
        }
@@ -7262,10 +7287,19 @@ nfs4_state_start_net(struct net *net)
                return ret;
        locks_start_grace(net, &nn->nfsd4_manager);
        nfsd4_client_tracking_init(net);
+       if (nn->track_reclaim_completes && nn->reclaim_str_hashtbl_size == 0)
+               goto skip_grace;
        printk(KERN_INFO "NFSD: starting %ld-second grace period (net %x)\n",
               nn->nfsd4_grace, net->ns.inum);
        queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_grace * HZ);
        return 0;
+
+skip_grace:
+       printk(KERN_INFO "NFSD: no clients to reclaim, skipping NFSv4 grace period (net %x)\n",
+                       net->ns.inum);
+       queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_lease * HZ);
+       nfsd4_end_grace(nn);
+       return 0;
 }
 
 /* initialization to perform when the nfsd service is started: */
index 3de42a7..52c4f6d 100644 (file)
@@ -521,6 +521,7 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access
 static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs)
 {
        DECODE_HEAD;
+       struct user_namespace *userns = nfsd_user_namespace(argp->rqstp);
        u32 dummy, uid, gid;
        char *machine_name;
        int i;
@@ -563,8 +564,8 @@ static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_
                        dummy = be32_to_cpup(p++);
                        READ_BUF(dummy * 4);
                        if (cbs->flavor == (u32)(-1)) {
-                               kuid_t kuid = make_kuid(&init_user_ns, uid);
-                               kgid_t kgid = make_kgid(&init_user_ns, gid);
+                               kuid_t kuid = make_kuid(userns, uid);
+                               kgid_t kgid = make_kgid(userns, gid);
                                if (uid_valid(kuid) && gid_valid(kgid)) {
                                        cbs->uid = kuid;
                                        cbs->gid = kgid;
@@ -2420,8 +2421,10 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
        __be32 status;
        int err;
        struct nfs4_acl *acl = NULL;
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
        void *context = NULL;
        int contextlen;
+#endif
        bool contextsupport = false;
        struct nfsd4_compoundres *resp = rqstp->rq_resp;
        u32 minorversion = resp->cstate.minorversion;
@@ -2906,12 +2909,14 @@ out_acl:
                        *p++ = cpu_to_be32(NFS4_CHANGE_TYPE_IS_TIME_METADATA);
        }
 
+#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
        if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
                status = nfsd4_encode_security_label(xdr, rqstp, context,
                                                                contextlen);
                if (status)
                        goto out;
        }
+#endif
 
        attrlen = htonl(xdr->buf->len - attrlen_offset - 4);
        write_bytes_to_xdr_buf(xdr->buf, attrlen_offset, &attrlen, 4);
index f2feb2d..90972e1 100644 (file)
@@ -439,7 +439,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
                        return rv;
                if (newthreads < 0)
                        return -EINVAL;
-               rv = nfsd_svc(newthreads, net);
+               rv = nfsd_svc(newthreads, net, file->f_cred);
                if (rv < 0)
                        return rv;
        } else
@@ -537,14 +537,14 @@ out_free:
 }
 
 static ssize_t
-nfsd_print_version_support(char *buf, int remaining, const char *sep,
-               unsigned vers, int minor)
+nfsd_print_version_support(struct nfsd_net *nn, char *buf, int remaining,
+               const char *sep, unsigned vers, int minor)
 {
        const char *format = minor < 0 ? "%s%c%u" : "%s%c%u.%u";
-       bool supported = !!nfsd_vers(vers, NFSD_TEST);
+       bool supported = !!nfsd_vers(nn, vers, NFSD_TEST);
 
        if (vers == 4 && minor >= 0 &&
-           !nfsd_minorversion(minor, NFSD_TEST))
+           !nfsd_minorversion(nn, minor, NFSD_TEST))
                supported = false;
        if (minor == 0 && supported)
                /*
@@ -599,20 +599,20 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
                        switch(num) {
                        case 2:
                        case 3:
-                               nfsd_vers(num, cmd);
+                               nfsd_vers(nn, num, cmd);
                                break;
                        case 4:
                                if (*minorp == '.') {
-                                       if (nfsd_minorversion(minor, cmd) < 0)
+                                       if (nfsd_minorversion(nn, minor, cmd) < 0)
                                                return -EINVAL;
-                               } else if ((cmd == NFSD_SET) != nfsd_vers(num, NFSD_TEST)) {
+                               } else if ((cmd == NFSD_SET) != nfsd_vers(nn, num, NFSD_TEST)) {
                                        /*
                                         * Either we have +4 and no minors are enabled,
                                         * or we have -4 and at least one minor is enabled.
                                         * In either case, propagate 'cmd' to all minors.
                                         */
                                        minor = 0;
-                                       while (nfsd_minorversion(minor, cmd) >= 0)
+                                       while (nfsd_minorversion(nn, minor, cmd) >= 0)
                                                minor++;
                                }
                                break;
@@ -624,7 +624,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
                /* If all get turned off, turn them back on, as
                 * having no versions is BAD
                 */
-               nfsd_reset_versions();
+               nfsd_reset_versions(nn);
        }
 
        /* Now write current state into reply buffer */
@@ -633,12 +633,12 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
        remaining = SIMPLE_TRANSACTION_LIMIT;
        for (num=2 ; num <= 4 ; num++) {
                int minor;
-               if (!nfsd_vers(num, NFSD_AVAIL))
+               if (!nfsd_vers(nn, num, NFSD_AVAIL))
                        continue;
 
                minor = -1;
                do {
-                       len = nfsd_print_version_support(buf, remaining,
+                       len = nfsd_print_version_support(nn, buf, remaining,
                                        sep, num, minor);
                        if (len >= remaining)
                                goto out;
@@ -717,7 +717,7 @@ static ssize_t __write_ports_names(char *buf, struct net *net)
  * a socket of a supported family/protocol, and we use it as an
  * nfsd listener.
  */
-static ssize_t __write_ports_addfd(char *buf, struct net *net)
+static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred *cred)
 {
        char *mesg = buf;
        int fd, err;
@@ -736,7 +736,7 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net)
        if (err != 0)
                return err;
 
-       err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
+       err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT, cred);
        if (err < 0) {
                nfsd_destroy(net);
                return err;
@@ -751,7 +751,7 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net)
  * A transport listener is added by writing it's transport name and
  * a port number.
  */
-static ssize_t __write_ports_addxprt(char *buf, struct net *net)
+static ssize_t __write_ports_addxprt(char *buf, struct net *net, const struct cred *cred)
 {
        char transport[16];
        struct svc_xprt *xprt;
@@ -769,12 +769,12 @@ static ssize_t __write_ports_addxprt(char *buf, struct net *net)
                return err;
 
        err = svc_create_xprt(nn->nfsd_serv, transport, net,
-                               PF_INET, port, SVC_SOCK_ANONYMOUS);
+                               PF_INET, port, SVC_SOCK_ANONYMOUS, cred);
        if (err < 0)
                goto out_err;
 
        err = svc_create_xprt(nn->nfsd_serv, transport, net,
-                               PF_INET6, port, SVC_SOCK_ANONYMOUS);
+                               PF_INET6, port, SVC_SOCK_ANONYMOUS, cred);
        if (err < 0 && err != -EAFNOSUPPORT)
                goto out_close;
 
@@ -799,10 +799,10 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size,
                return __write_ports_names(buf, net);
 
        if (isdigit(buf[0]))
-               return __write_ports_addfd(buf, net);
+               return __write_ports_addfd(buf, net, file->f_cred);
 
        if (isalpha(buf[0]))
-               return __write_ports_addxprt(buf, net);
+               return __write_ports_addxprt(buf, net, file->f_cred);
 
        return -EINVAL;
 }
@@ -1239,9 +1239,12 @@ static __net_init int nfsd_init_net(struct net *net)
        retval = nfsd_idmap_init(net);
        if (retval)
                goto out_idmap_error;
+       nn->nfsd_versions = NULL;
+       nn->nfsd4_minorversions = NULL;
        nn->nfsd4_lease = 90;   /* default lease time */
        nn->nfsd4_grace = 90;
        nn->somebody_reclaimed = false;
+       nn->track_reclaim_completes = false;
        nn->clverifier_counter = prandom_u32();
        nn->clientid_counter = prandom_u32();
        nn->s2s_cp_cl_id = nn->clientid_counter++;
@@ -1260,6 +1263,7 @@ static __net_exit void nfsd_exit_net(struct net *net)
 {
        nfsd_idmap_shutdown(net);
        nfsd_export_shutdown(net);
+       nfsd_netns_free_versions(net_generic(net, nfsd_net_id));
 }
 
 static struct pernet_operations nfsd_net_ops = {
index 0668999..24187b5 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/nfs3.h>
 #include <linux/nfs4.h>
 #include <linux/sunrpc/svc.h>
+#include <linux/sunrpc/svc_xprt.h>
 #include <linux/sunrpc/msg_prot.h>
 
 #include <uapi/linux/nfsd/debug.h>
@@ -73,7 +74,7 @@ extern const struct seq_operations nfs_exports_op;
 /*
  * Function prototypes.
  */
-int            nfsd_svc(int nrservs, struct net *net);
+int            nfsd_svc(int nrservs, struct net *net, const struct cred *cred);
 int            nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp);
 
 int            nfsd_nrthreads(struct net *);
@@ -98,10 +99,12 @@ extern const struct svc_version nfsd_acl_version3;
 #endif
 #endif
 
+struct nfsd_net;
+
 enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
-int nfsd_vers(int vers, enum vers_op change);
-int nfsd_minorversion(u32 minorversion, enum vers_op change);
-void nfsd_reset_versions(void);
+int nfsd_vers(struct nfsd_net *nn, int vers, enum vers_op change);
+int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op change);
+void nfsd_reset_versions(struct nfsd_net *nn);
 int nfsd_create_serv(struct net *net);
 
 extern int nfsd_max_blksize;
@@ -110,6 +113,12 @@ static inline int nfsd_v4client(struct svc_rqst *rq)
 {
        return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4;
 }
+static inline struct user_namespace *
+nfsd_user_namespace(const struct svc_rqst *rqstp)
+{
+       const struct cred *cred = rqstp->rq_xprt->xpt_cred;
+       return cred ? cred->user_ns : &init_user_ns;
+}
 
 /* 
  * NFSv4 State
index 89cb484..18d94ea 100644 (file)
 
 extern struct svc_program      nfsd_program;
 static int                     nfsd(void *vrqstp);
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+static int                     nfsd_acl_rpcbind_set(struct net *,
+                                                    const struct svc_program *,
+                                                    u32, int,
+                                                    unsigned short,
+                                                    unsigned short);
+static __be32                  nfsd_acl_init_request(struct svc_rqst *,
+                                               const struct svc_program *,
+                                               struct svc_process_info *);
+#endif
+static int                     nfsd_rpcbind_set(struct net *,
+                                                const struct svc_program *,
+                                                u32, int,
+                                                unsigned short,
+                                                unsigned short);
+static __be32                  nfsd_init_request(struct svc_rqst *,
+                                               const struct svc_program *,
+                                               struct svc_process_info *);
 
 /*
  * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members
@@ -86,6 +104,8 @@ static struct svc_program    nfsd_acl_program = {
        .pg_class               = "nfsd",
        .pg_stats               = &nfsd_acl_svcstats,
        .pg_authenticate        = &svc_set_client,
+       .pg_init_request        = nfsd_acl_init_request,
+       .pg_rpcbind_set         = nfsd_acl_rpcbind_set,
 };
 
 static struct svc_stat nfsd_acl_svcstats = {
@@ -105,7 +125,6 @@ static const struct svc_version *nfsd_version[] = {
 
 #define NFSD_MINVERS           2
 #define NFSD_NRVERS            ARRAY_SIZE(nfsd_version)
-static const struct svc_version *nfsd_versions[NFSD_NRVERS];
 
 struct svc_program             nfsd_program = {
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
@@ -113,77 +132,136 @@ struct svc_program               nfsd_program = {
 #endif
        .pg_prog                = NFS_PROGRAM,          /* program number */
        .pg_nvers               = NFSD_NRVERS,          /* nr of entries in nfsd_version */
-       .pg_vers                = nfsd_versions,        /* version table */
+       .pg_vers                = nfsd_version        /* version table */
        .pg_name                = "nfsd",               /* program name */
        .pg_class               = "nfsd",               /* authentication class */
        .pg_stats               = &nfsd_svcstats,       /* version table */
        .pg_authenticate        = &svc_set_client,      /* export authentication */
-
+       .pg_init_request        = nfsd_init_request,
+       .pg_rpcbind_set         = nfsd_rpcbind_set,
 };
 
-static bool nfsd_supported_minorversions[NFSD_SUPPORTED_MINOR_VERSION + 1] = {
-       [0] = 1,
-       [1] = 1,
-       [2] = 1,
-};
+static bool
+nfsd_support_version(int vers)
+{
+       if (vers >= NFSD_MINVERS && vers < NFSD_NRVERS)
+               return nfsd_version[vers] != NULL;
+       return false;
+}
+
+static bool *
+nfsd_alloc_versions(void)
+{
+       bool *vers = kmalloc_array(NFSD_NRVERS, sizeof(bool), GFP_KERNEL);
+       unsigned i;
+
+       if (vers) {
+               /* All compiled versions are enabled by default */
+               for (i = 0; i < NFSD_NRVERS; i++)
+                       vers[i] = nfsd_support_version(i);
+       }
+       return vers;
+}
+
+static bool *
+nfsd_alloc_minorversions(void)
+{
+       bool *vers = kmalloc_array(NFSD_SUPPORTED_MINOR_VERSION + 1,
+                       sizeof(bool), GFP_KERNEL);
+       unsigned i;
+
+       if (vers) {
+               /* All minor versions are enabled by default */
+               for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++)
+                       vers[i] = nfsd_support_version(4);
+       }
+       return vers;
+}
 
-int nfsd_vers(int vers, enum vers_op change)
+void
+nfsd_netns_free_versions(struct nfsd_net *nn)
+{
+       kfree(nn->nfsd_versions);
+       kfree(nn->nfsd4_minorversions);
+       nn->nfsd_versions = NULL;
+       nn->nfsd4_minorversions = NULL;
+}
+
+static void
+nfsd_netns_init_versions(struct nfsd_net *nn)
+{
+       if (!nn->nfsd_versions) {
+               nn->nfsd_versions = nfsd_alloc_versions();
+               nn->nfsd4_minorversions = nfsd_alloc_minorversions();
+               if (!nn->nfsd_versions || !nn->nfsd4_minorversions)
+                       nfsd_netns_free_versions(nn);
+       }
+}
+
+int nfsd_vers(struct nfsd_net *nn, int vers, enum vers_op change)
 {
        if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
                return 0;
        switch(change) {
        case NFSD_SET:
-               nfsd_versions[vers] = nfsd_version[vers];
-#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
-               if (vers < NFSD_ACL_NRVERS)
-                       nfsd_acl_versions[vers] = nfsd_acl_version[vers];
-#endif
+               if (nn->nfsd_versions)
+                       nn->nfsd_versions[vers] = nfsd_support_version(vers);
                break;
        case NFSD_CLEAR:
-               nfsd_versions[vers] = NULL;
-#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
-               if (vers < NFSD_ACL_NRVERS)
-                       nfsd_acl_versions[vers] = NULL;
-#endif
+               nfsd_netns_init_versions(nn);
+               if (nn->nfsd_versions)
+                       nn->nfsd_versions[vers] = false;
                break;
        case NFSD_TEST:
-               return nfsd_versions[vers] != NULL;
+               if (nn->nfsd_versions)
+                       return nn->nfsd_versions[vers];
+               /* Fallthrough */
        case NFSD_AVAIL:
-               return nfsd_version[vers] != NULL;
+               return nfsd_support_version(vers);
        }
        return 0;
 }
 
 static void
-nfsd_adjust_nfsd_versions4(void)
+nfsd_adjust_nfsd_versions4(struct nfsd_net *nn)
 {
        unsigned i;
 
        for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++) {
-               if (nfsd_supported_minorversions[i])
+               if (nn->nfsd4_minorversions[i])
                        return;
        }
-       nfsd_vers(4, NFSD_CLEAR);
+       nfsd_vers(nn, 4, NFSD_CLEAR);
 }
 
-int nfsd_minorversion(u32 minorversion, enum vers_op change)
+int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op change)
 {
        if (minorversion > NFSD_SUPPORTED_MINOR_VERSION &&
            change != NFSD_AVAIL)
                return -1;
+
        switch(change) {
        case NFSD_SET:
-               nfsd_supported_minorversions[minorversion] = true;
-               nfsd_vers(4, NFSD_SET);
+               if (nn->nfsd4_minorversions) {
+                       nfsd_vers(nn, 4, NFSD_SET);
+                       nn->nfsd4_minorversions[minorversion] =
+                               nfsd_vers(nn, 4, NFSD_TEST);
+               }
                break;
        case NFSD_CLEAR:
-               nfsd_supported_minorversions[minorversion] = false;
-               nfsd_adjust_nfsd_versions4();
+               nfsd_netns_init_versions(nn);
+               if (nn->nfsd4_minorversions) {
+                       nn->nfsd4_minorversions[minorversion] = false;
+                       nfsd_adjust_nfsd_versions4(nn);
+               }
                break;
        case NFSD_TEST:
-               return nfsd_supported_minorversions[minorversion];
+               if (nn->nfsd4_minorversions)
+                       return nn->nfsd4_minorversions[minorversion];
+               return nfsd_vers(nn, 4, NFSD_TEST);
        case NFSD_AVAIL:
-               return minorversion <= NFSD_SUPPORTED_MINOR_VERSION;
+               return minorversion <= NFSD_SUPPORTED_MINOR_VERSION &&
+                       nfsd_vers(nn, 4, NFSD_AVAIL);
        }
        return 0;
 }
@@ -205,7 +283,7 @@ int nfsd_nrthreads(struct net *net)
        return rv;
 }
 
-static int nfsd_init_socks(struct net *net)
+static int nfsd_init_socks(struct net *net, const struct cred *cred)
 {
        int error;
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
@@ -214,12 +292,12 @@ static int nfsd_init_socks(struct net *net)
                return 0;
 
        error = svc_create_xprt(nn->nfsd_serv, "udp", net, PF_INET, NFS_PORT,
-                                       SVC_SOCK_DEFAULTS);
+                                       SVC_SOCK_DEFAULTS, cred);
        if (error < 0)
                return error;
 
        error = svc_create_xprt(nn->nfsd_serv, "tcp", net, PF_INET, NFS_PORT,
-                                       SVC_SOCK_DEFAULTS);
+                                       SVC_SOCK_DEFAULTS, cred);
        if (error < 0)
                return error;
 
@@ -265,16 +343,12 @@ static void nfsd_shutdown_generic(void)
        nfsd_racache_shutdown();
 }
 
-static bool nfsd_needs_lockd(void)
+static bool nfsd_needs_lockd(struct nfsd_net *nn)
 {
-#if defined(CONFIG_NFSD_V3)
-       return (nfsd_versions[2] != NULL) || (nfsd_versions[3] != NULL);
-#else
-       return (nfsd_versions[2] != NULL);
-#endif
+       return nfsd_vers(nn, 2, NFSD_TEST) || nfsd_vers(nn, 3, NFSD_TEST);
 }
 
-static int nfsd_startup_net(int nrservs, struct net *net)
+static int nfsd_startup_net(int nrservs, struct net *net, const struct cred *cred)
 {
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
        int ret;
@@ -285,12 +359,12 @@ static int nfsd_startup_net(int nrservs, struct net *net)
        ret = nfsd_startup_generic(nrservs);
        if (ret)
                return ret;
-       ret = nfsd_init_socks(net);
+       ret = nfsd_init_socks(net, cred);
        if (ret)
                goto out_socks;
 
-       if (nfsd_needs_lockd() && !nn->lockd_up) {
-               ret = lockd_up(net);
+       if (nfsd_needs_lockd(nn) && !nn->lockd_up) {
+               ret = lockd_up(net, cred);
                if (ret)
                        goto out_socks;
                nn->lockd_up = 1;
@@ -422,20 +496,20 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
        nfsd_export_flush(net);
 }
 
-void nfsd_reset_versions(void)
+void nfsd_reset_versions(struct nfsd_net *nn)
 {
        int i;
 
        for (i = 0; i < NFSD_NRVERS; i++)
-               if (nfsd_vers(i, NFSD_TEST))
+               if (nfsd_vers(nn, i, NFSD_TEST))
                        return;
 
        for (i = 0; i < NFSD_NRVERS; i++)
                if (i != 4)
-                       nfsd_vers(i, NFSD_SET);
+                       nfsd_vers(nn, i, NFSD_SET);
                else {
                        int minor = 0;
-                       while (nfsd_minorversion(minor, NFSD_SET) >= 0)
+                       while (nfsd_minorversion(nn, minor, NFSD_SET) >= 0)
                                minor++;
                }
 }
@@ -503,7 +577,7 @@ int nfsd_create_serv(struct net *net)
        }
        if (nfsd_max_blksize == 0)
                nfsd_max_blksize = nfsd_get_default_max_blksize();
-       nfsd_reset_versions();
+       nfsd_reset_versions(nn);
        nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
                                                &nfsd_thread_sv_ops);
        if (nn->nfsd_serv == NULL)
@@ -623,7 +697,7 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
  * this is the first time nrservs is nonzero.
  */
 int
-nfsd_svc(int nrservs, struct net *net)
+nfsd_svc(int nrservs, struct net *net, const struct cred *cred)
 {
        int     error;
        bool    nfsd_up_before;
@@ -645,7 +719,7 @@ nfsd_svc(int nrservs, struct net *net)
 
        nfsd_up_before = nn->nfsd_net_up;
 
-       error = nfsd_startup_net(nrservs, net);
+       error = nfsd_startup_net(nrservs, net, cred);
        if (error)
                goto out_destroy;
        error = nn->nfsd_serv->sv_ops->svo_setup(nn->nfsd_serv,
@@ -667,6 +741,101 @@ out:
        return error;
 }
 
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+static bool
+nfsd_support_acl_version(int vers)
+{
+       if (vers >= NFSD_ACL_MINVERS && vers < NFSD_ACL_NRVERS)
+               return nfsd_acl_version[vers] != NULL;
+       return false;
+}
+
+static int
+nfsd_acl_rpcbind_set(struct net *net, const struct svc_program *progp,
+                    u32 version, int family, unsigned short proto,
+                    unsigned short port)
+{
+       if (!nfsd_support_acl_version(version) ||
+           !nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST))
+               return 0;
+       return svc_generic_rpcbind_set(net, progp, version, family,
+                       proto, port);
+}
+
+static __be32
+nfsd_acl_init_request(struct svc_rqst *rqstp,
+                     const struct svc_program *progp,
+                     struct svc_process_info *ret)
+{
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+       int i;
+
+       if (likely(nfsd_support_acl_version(rqstp->rq_vers) &&
+           nfsd_vers(nn, rqstp->rq_vers, NFSD_TEST)))
+               return svc_generic_init_request(rqstp, progp, ret);
+
+       ret->mismatch.lovers = NFSD_ACL_NRVERS;
+       for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) {
+               if (nfsd_support_acl_version(rqstp->rq_vers) &&
+                   nfsd_vers(nn, i, NFSD_TEST)) {
+                       ret->mismatch.lovers = i;
+                       break;
+               }
+       }
+       if (ret->mismatch.lovers == NFSD_ACL_NRVERS)
+               return rpc_prog_unavail;
+       ret->mismatch.hivers = NFSD_ACL_MINVERS;
+       for (i = NFSD_ACL_NRVERS - 1; i >= NFSD_ACL_MINVERS; i--) {
+               if (nfsd_support_acl_version(rqstp->rq_vers) &&
+                   nfsd_vers(nn, i, NFSD_TEST)) {
+                       ret->mismatch.hivers = i;
+                       break;
+               }
+       }
+       return rpc_prog_mismatch;
+}
+#endif
+
+static int
+nfsd_rpcbind_set(struct net *net, const struct svc_program *progp,
+                u32 version, int family, unsigned short proto,
+                unsigned short port)
+{
+       if (!nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST))
+               return 0;
+       return svc_generic_rpcbind_set(net, progp, version, family,
+                       proto, port);
+}
+
+static __be32
+nfsd_init_request(struct svc_rqst *rqstp,
+                 const struct svc_program *progp,
+                 struct svc_process_info *ret)
+{
+       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+       int i;
+
+       if (likely(nfsd_vers(nn, rqstp->rq_vers, NFSD_TEST)))
+               return svc_generic_init_request(rqstp, progp, ret);
+
+       ret->mismatch.lovers = NFSD_NRVERS;
+       for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
+               if (nfsd_vers(nn, i, NFSD_TEST)) {
+                       ret->mismatch.lovers = i;
+                       break;
+               }
+       }
+       if (ret->mismatch.lovers == NFSD_NRVERS)
+               return rpc_prog_unavail;
+       ret->mismatch.hivers = NFSD_MINVERS;
+       for (i = NFSD_NRVERS - 1; i >= NFSD_MINVERS; i--) {
+               if (nfsd_vers(nn, i, NFSD_TEST)) {
+                       ret->mismatch.hivers = i;
+                       break;
+               }
+       }
+       return rpc_prog_mismatch;
+}
 
 /*
  * This is the NFS server kernel thread
index 6b2e8b7..b51fe51 100644 (file)
@@ -71,7 +71,7 @@ decode_filename(__be32 *p, char **namp, unsigned int *lenp)
 }
 
 static __be32 *
-decode_sattr(__be32 *p, struct iattr *iap)
+decode_sattr(__be32 *p, struct iattr *iap, struct user_namespace *userns)
 {
        u32     tmp, tmp1;
 
@@ -86,12 +86,12 @@ decode_sattr(__be32 *p, struct iattr *iap)
                iap->ia_mode = tmp;
        }
        if ((tmp = ntohl(*p++)) != (u32)-1) {
-               iap->ia_uid = make_kuid(&init_user_ns, tmp);
+               iap->ia_uid = make_kuid(userns, tmp);
                if (uid_valid(iap->ia_uid))
                        iap->ia_valid |= ATTR_UID;
        }
        if ((tmp = ntohl(*p++)) != (u32)-1) {
-               iap->ia_gid = make_kgid(&init_user_ns, tmp);
+               iap->ia_gid = make_kgid(userns, tmp);
                if (gid_valid(iap->ia_gid))
                        iap->ia_valid |= ATTR_GID;
        }
@@ -129,6 +129,7 @@ static __be32 *
 encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
             struct kstat *stat)
 {
+       struct user_namespace *userns = nfsd_user_namespace(rqstp);
        struct dentry   *dentry = fhp->fh_dentry;
        int type;
        struct timespec64 time;
@@ -139,8 +140,8 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
        *p++ = htonl(nfs_ftypes[type >> 12]);
        *p++ = htonl((u32) stat->mode);
        *p++ = htonl((u32) stat->nlink);
-       *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid));
-       *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid));
+       *p++ = htonl((u32) from_kuid_munged(userns, stat->uid));
+       *p++ = htonl((u32) from_kgid_munged(userns, stat->gid));
 
        if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) {
                *p++ = htonl(NFS_MAXPATHLEN);
@@ -216,7 +217,7 @@ nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
        p = decode_fh(p, &args->fh);
        if (!p)
                return 0;
-       p = decode_sattr(p, &args->attrs);
+       p = decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp));
 
        return xdr_argsize_check(rqstp, p);
 }
@@ -319,7 +320,7 @@ nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
        if (   !(p = decode_fh(p, &args->fh))
            || !(p = decode_filename(p, &args->name, &args->len)))
                return 0;
-       p = decode_sattr(p, &args->attrs);
+       p = decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp));
 
        return xdr_argsize_check(rqstp, p);
 }
@@ -398,7 +399,7 @@ nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
                        return 0;
                p += xdrlen;
        }
-       decode_sattr(p, &args->attrs);
+       decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp));
 
        return 1;
 }
index 9d6cb24..0b74d37 100644 (file)
@@ -368,7 +368,7 @@ struct nfs4_client {
 struct nfs4_client_reclaim {
        struct list_head        cr_strhash;     /* hash by cr_name */
        struct nfs4_client      *cr_clp;        /* pointer to associated clp */
-       char                    cr_recdir[HEXDIR_LEN]; /* recover dir */
+       struct xdr_netobj       cr_name;        /* recovery dir name */
 };
 
 /* A reasonable value for REPLAY_ISIZE was estimated as follows:  
@@ -620,7 +620,7 @@ void nfs4_put_stid(struct nfs4_stid *s);
 void nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid);
 void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *, struct nfsd_net *);
 extern void nfs4_release_reclaim(struct nfsd_net *);
-extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir,
+extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct xdr_netobj name,
                                                        struct nfsd_net *nn);
 extern __be32 nfs4_check_open_reclaim(clientid_t *clid,
                struct nfsd4_compound_state *cstate, struct nfsd_net *nn);
@@ -635,9 +635,9 @@ extern void nfsd4_destroy_callback_queue(void);
 extern void nfsd4_shutdown_callback(struct nfs4_client *);
 extern void nfsd4_shutdown_copy(struct nfs4_client *clp);
 extern void nfsd4_prepare_cb_recall(struct nfs4_delegation *dp);
-extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name,
+extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(struct xdr_netobj name,
                                                        struct nfsd_net *nn);
-extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn);
+extern bool nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn);
 
 struct nfs4_file *find_file(struct knfsd_fh *fh);
 void put_nfs4_file(struct nfs4_file *fi);
index 7dc98e1..fc24ee4 100644 (file)
@@ -1786,12 +1786,12 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
        rdentry = lookup_one_len(fname, dentry, flen);
        host_err = PTR_ERR(rdentry);
        if (IS_ERR(rdentry))
-               goto out_nfserr;
+               goto out_drop_write;
 
        if (d_really_is_negative(rdentry)) {
                dput(rdentry);
-               err = nfserr_noent;
-               goto out;
+               host_err = -ENOENT;
+               goto out_drop_write;
        }
 
        if (!type)
@@ -1805,6 +1805,8 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
                host_err = commit_metadata(fhp);
        dput(rdentry);
 
+out_drop_write:
+       fh_drop_write(fhp);
 out_nfserr:
        err = nfserrno(host_err);
 out:
index a7e1073..db35124 100644 (file)
@@ -120,8 +120,11 @@ void               nfsd_put_raparams(struct file *file, struct raparms *ra);
 
 static inline int fh_want_write(struct svc_fh *fh)
 {
-       int ret = mnt_want_write(fh->fh_export->ex_path.mnt);
+       int ret;
 
+       if (fh->fh_want_write)
+               return 0;
+       ret = mnt_want_write(fh->fh_export->ex_path.mnt);
        if (!ret)
                fh->fh_want_write = true;
        return ret;
index 5433e37..8c7cbac 100644 (file)
@@ -107,6 +107,47 @@ void fsnotify_sb_delete(struct super_block *sb)
        fsnotify_clear_marks_by_sb(sb);
 }
 
+/*
+ * fsnotify_nameremove - a filename was removed from a directory
+ *
+ * This is mostly called under parent vfs inode lock so name and
+ * dentry->d_parent should be stable. However there are some corner cases where
+ * inode lock is not held. So to be on the safe side and be reselient to future
+ * callers and out of tree users of d_delete(), we do not assume that d_parent
+ * and d_name are stable and we use dget_parent() and
+ * take_dentry_name_snapshot() to grab stable references.
+ */
+void fsnotify_nameremove(struct dentry *dentry, int isdir)
+{
+       struct dentry *parent;
+       struct name_snapshot name;
+       __u32 mask = FS_DELETE;
+
+       /* d_delete() of pseudo inode? (e.g. __ns_get_path() playing tricks) */
+       if (IS_ROOT(dentry))
+               return;
+
+       if (isdir)
+               mask |= FS_ISDIR;
+
+       parent = dget_parent(dentry);
+       /* Avoid unneeded take_dentry_name_snapshot() */
+       if (!(d_inode(parent)->i_fsnotify_mask & FS_DELETE) &&
+           !(dentry->d_sb->s_fsnotify_mask & FS_DELETE))
+               goto out_dput;
+
+       take_dentry_name_snapshot(&name, dentry);
+
+       fsnotify(d_inode(parent), mask, d_inode(dentry), FSNOTIFY_EVENT_INODE,
+                &name.name, 0);
+
+       release_dentry_name_snapshot(&name);
+
+out_dput:
+       dput(parent);
+}
+EXPORT_SYMBOL(fsnotify_nameremove);
+
 /*
  * Given an inode, first check if we care what happens to our children.  Inotify
  * and dnotify both tell their parents about events.  If we care about any event
index 22acb0a..b251105 100644 (file)
@@ -619,6 +619,11 @@ restart:
        /* mark should be the last entry.  last is the current last entry */
        hlist_add_behind_rcu(&mark->obj_list, &last->obj_list);
 added:
+       /*
+        * Since connector is attached to object using cmpxchg() we are
+        * guaranteed that connector initialization is fully visible by anyone
+        * seeing mark->connector set.
+        */
        WRITE_ONCE(mark->connector, conn);
 out_err:
        spin_unlock(&conn->lock);
index c121abb..85f21ca 100644 (file)
 #define NAMEI_RA_BLOCKS  4
 #define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
 
-static unsigned char ocfs2_filetype_table[] = {
-       DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
-};
-
 static int ocfs2_do_extend_dir(struct super_block *sb,
                               handle_t *handle,
                               struct inode *dir,
@@ -1718,7 +1714,7 @@ int __ocfs2_add_entry(handle_t *handle,
                                de->rec_len = cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
                                de = de1;
                        }
-                       de->file_type = OCFS2_FT_UNKNOWN;
+                       de->file_type = FT_UNKNOWN;
                        if (blkno) {
                                de->inode = cpu_to_le64(blkno);
                                ocfs2_set_de_type(de, inode->i_mode);
@@ -1803,13 +1799,9 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode,
                }
                offset += le16_to_cpu(de->rec_len);
                if (le64_to_cpu(de->inode)) {
-                       unsigned char d_type = DT_UNKNOWN;
-
-                       if (de->file_type < OCFS2_FT_MAX)
-                               d_type = ocfs2_filetype_table[de->file_type];
-
                        if (!dir_emit(ctx, de->name, de->name_len,
-                                     le64_to_cpu(de->inode), d_type))
+                                     le64_to_cpu(de->inode),
+                                     fs_ftype_to_dtype(de->file_type)))
                                goto out;
                }
                ctx->pos += le16_to_cpu(de->rec_len);
@@ -1900,14 +1892,10 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
                                break;
                        }
                        if (le64_to_cpu(de->inode)) {
-                               unsigned char d_type = DT_UNKNOWN;
-
-                               if (de->file_type < OCFS2_FT_MAX)
-                                       d_type = ocfs2_filetype_table[de->file_type];
                                if (!dir_emit(ctx, de->name,
                                                de->name_len,
                                                le64_to_cpu(de->inode),
-                                               d_type)) {
+                                       fs_ftype_to_dtype(de->file_type))) {
                                        brelse(bh);
                                        return 0;
                                }
index 4bf8d58..af2888d 100644 (file)
@@ -148,16 +148,24 @@ static struct dentry *ocfs2_get_parent(struct dentry *child)
        u64 blkno;
        struct dentry *parent;
        struct inode *dir = d_inode(child);
+       int set;
 
        trace_ocfs2_get_parent(child, child->d_name.len, child->d_name.name,
                               (unsigned long long)OCFS2_I(dir)->ip_blkno);
 
+       status = ocfs2_nfs_sync_lock(OCFS2_SB(dir->i_sb), 1);
+       if (status < 0) {
+               mlog(ML_ERROR, "getting nfs sync lock(EX) failed %d\n", status);
+               parent = ERR_PTR(status);
+               goto bail;
+       }
+
        status = ocfs2_inode_lock(dir, NULL, 0);
        if (status < 0) {
                if (status != -ENOENT)
                        mlog_errno(status);
                parent = ERR_PTR(status);
-               goto bail;
+               goto unlock_nfs_sync;
        }
 
        status = ocfs2_lookup_ino_from_name(dir, "..", 2, &blkno);
@@ -166,11 +174,31 @@ static struct dentry *ocfs2_get_parent(struct dentry *child)
                goto bail_unlock;
        }
 
+       status = ocfs2_test_inode_bit(OCFS2_SB(dir->i_sb), blkno, &set);
+       if (status < 0) {
+               if (status == -EINVAL) {
+                       status = -ESTALE;
+               } else
+                       mlog(ML_ERROR, "test inode bit failed %d\n", status);
+               parent = ERR_PTR(status);
+               goto bail_unlock;
+       }
+
+       trace_ocfs2_get_dentry_test_bit(status, set);
+       if (!set) {
+               status = -ESTALE;
+               parent = ERR_PTR(status);
+               goto bail_unlock;
+       }
+
        parent = d_obtain_alias(ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0, 0));
 
 bail_unlock:
        ocfs2_inode_unlock(dir, 0);
 
+unlock_nfs_sync:
+       ocfs2_nfs_sync_unlock(OCFS2_SB(dir->i_sb), 1);
+
 bail:
        trace_ocfs2_get_parent_end(parent);
 
index 7071ad0..b86bf5e 100644 (file)
@@ -391,21 +391,6 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
 #define OCFS2_HB_LOCAL                 "heartbeat=local"
 #define OCFS2_HB_GLOBAL                        "heartbeat=global"
 
-/*
- * OCFS2 directory file types.  Only the low 3 bits are used.  The
- * other bits are reserved for now.
- */
-#define OCFS2_FT_UNKNOWN       0
-#define OCFS2_FT_REG_FILE      1
-#define OCFS2_FT_DIR           2
-#define OCFS2_FT_CHRDEV                3
-#define OCFS2_FT_BLKDEV                4
-#define OCFS2_FT_FIFO          5
-#define OCFS2_FT_SOCK          6
-#define OCFS2_FT_SYMLINK       7
-
-#define OCFS2_FT_MAX           8
-
 /*
  * OCFS2_DIR_PAD defines the directory entries boundaries
  *
@@ -424,17 +409,6 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
 #define        OCFS2_LINKS_HI_SHIFT    16
 #define        OCFS2_DX_ENTRIES_MAX    (0xffffffffU)
 
-#define S_SHIFT                        12
-static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = {
-       [S_IFREG >> S_SHIFT]  = OCFS2_FT_REG_FILE,
-       [S_IFDIR >> S_SHIFT]  = OCFS2_FT_DIR,
-       [S_IFCHR >> S_SHIFT]  = OCFS2_FT_CHRDEV,
-       [S_IFBLK >> S_SHIFT]  = OCFS2_FT_BLKDEV,
-       [S_IFIFO >> S_SHIFT]  = OCFS2_FT_FIFO,
-       [S_IFSOCK >> S_SHIFT] = OCFS2_FT_SOCK,
-       [S_IFLNK >> S_SHIFT]  = OCFS2_FT_SYMLINK,
-};
-
 
 /*
  * Convenience casts
@@ -1629,7 +1603,7 @@ static inline int ocfs2_sprintf_system_inode_name(char *buf, int len,
 static inline void ocfs2_set_de_type(struct ocfs2_dir_entry *de,
                                    umode_t mode)
 {
-       de->file_type = ocfs2_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
+       de->file_type = fs_umode_to_ftype(mode);
 }
 
 static inline int ocfs2_gd_is_discontig(struct ocfs2_group_desc *gd)
index d4811f9..2bb916d 100644 (file)
@@ -269,7 +269,7 @@ orangefs_bufmap_map(struct orangefs_bufmap *bufmap,
 
        /* map the pages */
        ret = get_user_pages_fast((unsigned long)user_desc->ptr,
-                            bufmap->page_count, 1, bufmap->page_array);
+                            bufmap->page_count, FOLL_WRITE, bufmap->page_array);
 
        if (ret < 0)
                return ret;
index 68b3303..56feaa7 100644 (file)
@@ -909,14 +909,14 @@ static bool ovl_open_need_copy_up(struct dentry *dentry, int flags)
        return true;
 }
 
-int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags)
+int ovl_maybe_copy_up(struct dentry *dentry, int flags)
 {
        int err = 0;
 
-       if (ovl_open_need_copy_up(dentry, file_flags)) {
+       if (ovl_open_need_copy_up(dentry, flags)) {
                err = ovl_want_write(dentry);
                if (!err) {
-                       err = ovl_copy_up_flags(dentry, file_flags);
+                       err = ovl_copy_up_flags(dentry, flags);
                        ovl_drop_write(dentry);
                }
        }
index 82c129b..93872bb 100644 (file)
@@ -260,7 +260,7 @@ static int ovl_instantiate(struct dentry *dentry, struct inode *inode,
                 * hashed directory inode aliases.
                 */
                inode = ovl_get_inode(dentry->d_sb, &oip);
-               if (WARN_ON(IS_ERR(inode)))
+               if (IS_ERR(inode))
                        return PTR_ERR(inode);
        } else {
                WARN_ON(ovl_inode_real(inode) != d_inode(newdentry));
index 84dd957..540a8b8 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/mount.h>
 #include <linux/xattr.h>
 #include <linux/uio.h>
+#include <linux/uaccess.h>
 #include "overlayfs.h"
 
 static char ovl_whatisit(struct inode *inode, struct inode *realinode)
@@ -29,10 +30,11 @@ static struct file *ovl_open_realfile(const struct file *file,
        struct inode *inode = file_inode(file);
        struct file *realfile;
        const struct cred *old_cred;
+       int flags = file->f_flags | O_NOATIME | FMODE_NONOTIFY;
 
        old_cred = ovl_override_creds(inode->i_sb);
-       realfile = open_with_fake_path(&file->f_path, file->f_flags | O_NOATIME,
-                                      realinode, current_cred());
+       realfile = open_with_fake_path(&file->f_path, flags, realinode,
+                                      current_cred());
        revert_creds(old_cred);
 
        pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n",
@@ -50,7 +52,7 @@ static int ovl_change_flags(struct file *file, unsigned int flags)
        int err;
 
        /* No atime modificaton on underlying */
-       flags |= O_NOATIME;
+       flags |= O_NOATIME | FMODE_NONOTIFY;
 
        /* If some flag changed that cannot be changed then something's amiss */
        if (WARN_ON((file->f_flags ^ flags) & ~OVL_SETFL_MASK))
@@ -116,11 +118,10 @@ static int ovl_real_fdget(const struct file *file, struct fd *real)
 
 static int ovl_open(struct inode *inode, struct file *file)
 {
-       struct dentry *dentry = file_dentry(file);
        struct file *realfile;
        int err;
 
-       err = ovl_open_maybe_copy_up(dentry, file->f_flags);
+       err = ovl_maybe_copy_up(file_dentry(file), file->f_flags);
        if (err)
                return err;
 
@@ -145,11 +146,47 @@ static int ovl_release(struct inode *inode, struct file *file)
 
 static loff_t ovl_llseek(struct file *file, loff_t offset, int whence)
 {
-       struct inode *realinode = ovl_inode_real(file_inode(file));
+       struct inode *inode = file_inode(file);
+       struct fd real;
+       const struct cred *old_cred;
+       ssize_t ret;
+
+       /*
+        * The two special cases below do not need to involve real fs,
+        * so we can optimizing concurrent callers.
+        */
+       if (offset == 0) {
+               if (whence == SEEK_CUR)
+                       return file->f_pos;
+
+               if (whence == SEEK_SET)
+                       return vfs_setpos(file, 0, 0);
+       }
+
+       ret = ovl_real_fdget(file, &real);
+       if (ret)
+               return ret;
+
+       /*
+        * Overlay file f_pos is the master copy that is preserved
+        * through copy up and modified on read/write, but only real
+        * fs knows how to SEEK_HOLE/SEEK_DATA and real fs may impose
+        * limitations that are more strict than ->s_maxbytes for specific
+        * files, so we use the real file to perform seeks.
+        */
+       inode_lock(inode);
+       real.file->f_pos = file->f_pos;
+
+       old_cred = ovl_override_creds(inode->i_sb);
+       ret = vfs_llseek(real.file, offset, whence);
+       revert_creds(old_cred);
+
+       file->f_pos = real.file->f_pos;
+       inode_unlock(inode);
+
+       fdput(real);
 
-       return generic_file_llseek_size(file, offset, whence,
-                                       realinode->i_sb->s_maxbytes,
-                                       i_size_read(realinode));
+       return ret;
 }
 
 static void ovl_file_accessed(struct file *file)
@@ -372,10 +409,68 @@ static long ovl_real_ioctl(struct file *file, unsigned int cmd,
        return ret;
 }
 
-static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static unsigned int ovl_get_inode_flags(struct inode *inode)
+{
+       unsigned int flags = READ_ONCE(inode->i_flags);
+       unsigned int ovl_iflags = 0;
+
+       if (flags & S_SYNC)
+               ovl_iflags |= FS_SYNC_FL;
+       if (flags & S_APPEND)
+               ovl_iflags |= FS_APPEND_FL;
+       if (flags & S_IMMUTABLE)
+               ovl_iflags |= FS_IMMUTABLE_FL;
+       if (flags & S_NOATIME)
+               ovl_iflags |= FS_NOATIME_FL;
+
+       return ovl_iflags;
+}
+
+static long ovl_ioctl_set_flags(struct file *file, unsigned long arg)
 {
        long ret;
        struct inode *inode = file_inode(file);
+       unsigned int flags;
+       unsigned int old_flags;
+
+       if (!inode_owner_or_capable(inode))
+               return -EACCES;
+
+       if (get_user(flags, (int __user *) arg))
+               return -EFAULT;
+
+       ret = mnt_want_write_file(file);
+       if (ret)
+               return ret;
+
+       inode_lock(inode);
+
+       /* Check the capability before cred override */
+       ret = -EPERM;
+       old_flags = ovl_get_inode_flags(inode);
+       if (((flags ^ old_flags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
+           !capable(CAP_LINUX_IMMUTABLE))
+               goto unlock;
+
+       ret = ovl_maybe_copy_up(file_dentry(file), O_WRONLY);
+       if (ret)
+               goto unlock;
+
+       ret = ovl_real_ioctl(file, FS_IOC_SETFLAGS, arg);
+
+       ovl_copyflags(ovl_inode_real(inode), inode);
+unlock:
+       inode_unlock(inode);
+
+       mnt_drop_write_file(file);
+
+       return ret;
+
+}
+
+static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       long ret;
 
        switch (cmd) {
        case FS_IOC_GETFLAGS:
@@ -383,23 +478,7 @@ static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                break;
 
        case FS_IOC_SETFLAGS:
-               if (!inode_owner_or_capable(inode))
-                       return -EACCES;
-
-               ret = mnt_want_write_file(file);
-               if (ret)
-                       return ret;
-
-               ret = ovl_copy_up_with_data(file_dentry(file));
-               if (!ret) {
-                       ret = ovl_real_ioctl(file, cmd, arg);
-
-                       inode_lock(inode);
-                       ovl_copyflags(ovl_inode_real(inode), inode);
-                       inode_unlock(inode);
-               }
-
-               mnt_drop_write_file(file);
+               ret = ovl_ioctl_set_flags(file, arg);
                break;
 
        default:
index 3b7ed5d..b48273e 100644 (file)
@@ -832,7 +832,7 @@ struct inode *ovl_get_inode(struct super_block *sb,
        int fsid = bylower ? oip->lowerpath->layer->fsid : 0;
        bool is_dir, metacopy = false;
        unsigned long ino = 0;
-       int err = -ENOMEM;
+       int err = oip->newinode ? -EEXIST : -ENOMEM;
 
        if (!realinode)
                realinode = d_inode(lowerdentry);
@@ -917,6 +917,7 @@ out:
        return inode;
 
 out_err:
+       pr_warn_ratelimited("overlayfs: failed to get inode (%i)\n", err);
        inode = ERR_PTR(err);
        goto out;
 }
index 9c60182..d26efed 100644 (file)
@@ -421,7 +421,7 @@ extern const struct file_operations ovl_file_operations;
 int ovl_copy_up(struct dentry *dentry);
 int ovl_copy_up_with_data(struct dentry *dentry);
 int ovl_copy_up_flags(struct dentry *dentry, int flags);
-int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags);
+int ovl_maybe_copy_up(struct dentry *dentry, int flags);
 int ovl_copy_xattr(struct dentry *old, struct dentry *new);
 int ovl_set_attr(struct dentry *upper, struct kstat *stat);
 struct ovl_fh *ovl_encode_real_fh(struct dentry *real, bool is_upper);
index b6ccb6c..9c8ca6c 100644 (file)
@@ -510,7 +510,7 @@ static ssize_t lstats_write(struct file *file, const char __user *buf,
 
        if (!task)
                return -ESRCH;
-       clear_all_latency_tracing(task);
+       clear_tsk_latency_tracing(task);
        put_task_struct(task);
 
        return count;
index 95ca1fe..01d4eb0 100644 (file)
@@ -1169,7 +1169,8 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
                                break;
                        }
 
-                       mmu_notifier_range_init(&range, mm, 0, -1UL);
+                       mmu_notifier_range_init(&range, MMU_NOTIFY_SOFT_DIRTY,
+                                               0, NULL, mm, 0, -1UL);
                        mmu_notifier_invalidate_range_start(&range);
                }
                walk_page_range(0, mm->highest_vm_end, &clear_refs_walk);
index fc20e06..9ad72ea 100644 (file)
@@ -9,7 +9,7 @@
  * on the Melbourne quota system as used on BSD derived systems. The internal
  * implementation is based on one of the several variants of the LINUX
  * inode-subsystem with added complexity of the diskquota system.
- * 
+ *
  * Author:     Marco van Wieringen <mvw@planets.elm.net>
  *
  * Fixes:   Dmitry Gorodchanin <pgmdsg@ibi.com>, 11 Feb 96
@@ -51,7 +51,7 @@
  *             Added journalled quota support, fix lock inversion problems
  *             Jan Kara, <jack@suse.cz>, 2003,2004
  *
- * (C) Copyright 1994 - 1997 Marco van Wieringen 
+ * (C) Copyright 1994 - 1997 Marco van Wieringen
  */
 
 #include <linux/errno.h>
@@ -197,7 +197,7 @@ static struct quota_format_type *find_quota_format(int id)
                int qm;
 
                spin_unlock(&dq_list_lock);
-               
+
                for (qm = 0; module_names[qm].qm_fmt_id &&
                             module_names[qm].qm_fmt_id != id; qm++)
                        ;
@@ -424,10 +424,11 @@ int dquot_acquire(struct dquot *dquot)
        struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
 
        mutex_lock(&dquot->dq_lock);
-       if (!test_bit(DQ_READ_B, &dquot->dq_flags))
+       if (!test_bit(DQ_READ_B, &dquot->dq_flags)) {
                ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot);
-       if (ret < 0)
-               goto out_iolock;
+               if (ret < 0)
+                       goto out_iolock;
+       }
        /* Make sure flags update is visible after dquot has been filled */
        smp_mb__before_atomic();
        set_bit(DQ_READ_B, &dquot->dq_flags);
@@ -1049,7 +1050,9 @@ static void remove_dquot_ref(struct super_block *sb, int type,
                struct list_head *tofree_head)
 {
        struct inode *inode;
+#ifdef CONFIG_QUOTA_DEBUG
        int reserved = 0;
+#endif
 
        spin_lock(&sb->s_inode_list_lock);
        list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
@@ -1061,8 +1064,10 @@ static void remove_dquot_ref(struct super_block *sb, int type,
                 */
                spin_lock(&dq_data_lock);
                if (!IS_NOQUOTA(inode)) {
+#ifdef CONFIG_QUOTA_DEBUG
                        if (unlikely(inode_get_rsv_space(inode) > 0))
                                reserved = 1;
+#endif
                        remove_inode_dquot_ref(inode, type, tofree_head);
                }
                spin_unlock(&dq_data_lock);
@@ -1663,7 +1668,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                if (!dquots[cnt])
                        continue;
-               if (flags & DQUOT_SPACE_RESERVE) {
+               if (reserve) {
                        ret = dquot_add_space(dquots[cnt], 0, number, flags,
                                              &warn[cnt]);
                } else {
@@ -1676,13 +1681,11 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
                                if (!dquots[cnt])
                                        continue;
                                spin_lock(&dquots[cnt]->dq_dqb_lock);
-                               if (flags & DQUOT_SPACE_RESERVE) {
-                                       dquots[cnt]->dq_dqb.dqb_rsvspace -=
-                                                                       number;
-                               } else {
-                                       dquots[cnt]->dq_dqb.dqb_curspace -=
-                                                                       number;
-                               }
+                               if (reserve)
+                                       dquot_free_reserved_space(dquots[cnt],
+                                                                 number);
+                               else
+                                       dquot_decr_space(dquots[cnt], number);
                                spin_unlock(&dquots[cnt]->dq_dqb_lock);
                        }
                        spin_unlock(&inode->i_lock);
@@ -1733,7 +1736,7 @@ int dquot_alloc_inode(struct inode *inode)
                                        continue;
                                /* Back out changes we already did */
                                spin_lock(&dquots[cnt]->dq_dqb_lock);
-                               dquots[cnt]->dq_dqb.dqb_curinodes--;
+                               dquot_decr_inodes(dquots[cnt], 1);
                                spin_unlock(&dquots[cnt]->dq_dqb_lock);
                        }
                        goto warn_put_all;
@@ -2397,7 +2400,7 @@ out_file_flags:
 out_fmt:
        put_quota_format(fmt);
 
-       return error; 
+       return error;
 }
 
 /* Reenable quotas on remount RW */
@@ -2775,7 +2778,7 @@ int dquot_get_state(struct super_block *sb, struct qc_state *state)
        struct qc_type_state *tstate;
        struct quota_info *dqopt = sb_dqopt(sb);
        int type;
-  
+
        memset(state, 0, sizeof(*state));
        for (type = 0; type < MAXQUOTAS; type++) {
                if (!sb_has_quota_active(sb, type))
index 7ac5298..9f2b257 100644 (file)
@@ -127,7 +127,7 @@ static int v1_check_quota_file(struct super_block *sb, int type)
 {
        struct inode *inode = sb_dqopt(sb)->files[type];
        ulong blocks;
-       size_t off; 
+       size_t off;
        struct v2_disk_dqheader dqhead;
        ssize_t size;
        loff_t isize;
index a73e5b3..3c30034 100644 (file)
@@ -78,7 +78,7 @@ static int v2_check_quota_file(struct super_block *sb, int type)
        struct v2_disk_dqheader dqhead;
        static const uint quota_magics[] = V2_INITQMAGICS;
        static const uint quota_versions[] = V2_INITQVERSIONS;
+
        if (v2_read_header(sb, type, &dqhead))
                return 0;
        if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
index 8a76f9d..36346dc 100644 (file)
@@ -1844,7 +1844,7 @@ static int flush_used_journal_lists(struct super_block *s,
  * removes any nodes in table with name block and dev as bh.
  * only touchs the hnext and hprev pointers.
  */
-void remove_journal_hash(struct super_block *sb,
+static void remove_journal_hash(struct super_block *sb,
                         struct reiserfs_journal_cnode **table,
                         struct reiserfs_journal_list *jl,
                         unsigned long block, int remove_freed)
index 32d8986..b5b26d8 100644 (file)
@@ -450,6 +450,15 @@ fail:
 
 static inline __u32 xattr_hash(const char *msg, int len)
 {
+       /*
+        * csum_partial() gives different results for little-endian and
+        * big endian hosts. Images created on little-endian hosts and
+        * mounted on big-endian hosts(and vice versa) will see csum mismatches
+        * when trying to fetch xattrs. Treating the hash as __wsum_t would
+        * lower the frequency of mismatch.  This is an endianness bug in
+        * reiserfs.  The return statement would result in a sparse warning. Do
+        * not fix the sparse warning so as to not hide a reminder of the bug.
+        */
        return csum_partial(msg, len, 0);
 }
 
index 01e8217..4d1ff01 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -292,8 +292,14 @@ int sync_file_range(struct file *file, loff_t offset, loff_t nbytes,
        }
 
        if (flags & SYNC_FILE_RANGE_WRITE) {
+               int sync_mode = WB_SYNC_NONE;
+
+               if ((flags & SYNC_FILE_RANGE_WRITE_AND_WAIT) ==
+                            SYNC_FILE_RANGE_WRITE_AND_WAIT)
+                       sync_mode = WB_SYNC_ALL;
+
                ret = __filemap_fdatawrite_range(mapping, offset, endbyte,
-                                                WB_SYNC_NONE);
+                                                sync_mode);
                if (ret < 0)
                        goto out;
        }
@@ -306,9 +312,9 @@ out:
 }
 
 /*
- * sys_sync_file_range() permits finely controlled syncing over a segment of
+ * ksys_sync_file_range() permits finely controlled syncing over a segment of
  * a file in the range offset .. (offset+nbytes-1) inclusive.  If nbytes is
- * zero then sys_sync_file_range() will operate from offset out to EOF.
+ * zero then ksys_sync_file_range() will operate from offset out to EOF.
  *
  * The flag bits are:
  *
@@ -325,7 +331,7 @@ out:
  * Useful combinations of the flag bits are:
  *
  * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE: ensures that all pages
- * in the range which were dirty on entry to sys_sync_file_range() are placed
+ * in the range which were dirty on entry to ksys_sync_file_range() are placed
  * under writeout.  This is a start-write-for-data-integrity operation.
  *
  * SYNC_FILE_RANGE_WRITE: start writeout of all dirty pages in the range which
@@ -337,10 +343,13 @@ out:
  * earlier SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE operation to wait
  * for that operation to complete and to return the result.
  *
- * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER:
+ * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER
+ * (a.k.a. SYNC_FILE_RANGE_WRITE_AND_WAIT):
  * a traditional sync() operation.  This is a write-for-data-integrity operation
  * which will ensure that all pages in the range which were dirty on entry to
- * sys_sync_file_range() are committed to disk.
+ * ksys_sync_file_range() are written to disk.  It should be noted that disk
+ * caches are not flushed by this call, so there are no guarantees here that the
+ * data will be available on disk after a crash.
  *
  *
  * SYNC_FILE_RANGE_WAIT_BEFORE and SYNC_FILE_RANGE_WAIT_AFTER will detect any
index 58cc241..77b6d89 100644 (file)
@@ -304,21 +304,6 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
        if (dentry->d_name.len > UDF_NAME_LEN)
                return ERR_PTR(-ENAMETOOLONG);
 
-#ifdef UDF_RECOVERY
-       /* temporary shorthand for specifying files by inode number */
-       if (!strncmp(dentry->d_name.name, ".B=", 3)) {
-               struct kernel_lb_addr lb = {
-                       .logicalBlockNum = 0,
-                       .partitionReferenceNum =
-                               simple_strtoul(dentry->d_name.name + 3,
-                                               NULL, 0),
-               };
-               inode = udf_iget(dir->i_sb, lb);
-               if (IS_ERR(inode))
-                       return inode;
-       } else
-#endif /* UDF_RECOVERY */
-
        fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
        if (IS_ERR(fi))
                return ERR_CAST(fi);
index f64691f..a143461 100644 (file)
@@ -566,6 +566,11 @@ static int udf_parse_options(char *options, struct udf_options *uopt,
                        if (!remount) {
                                if (uopt->nls_map)
                                        unload_nls(uopt->nls_map);
+                               /*
+                                * load_nls() failure is handled later in
+                                * udf_fill_super() after all options are
+                                * parsed.
+                                */
                                uopt->nls_map = load_nls(args[0].from);
                                uopt->flags |= (1 << UDF_FLAG_NLS_MAP);
                        }
index f5de1e7..3b30301 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/security.h>
 #include <linux/hugetlb.h>
 
+int sysctl_unprivileged_userfaultfd __read_mostly = 1;
+
 static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly;
 
 enum userfaultfd_state {
@@ -1930,6 +1932,9 @@ SYSCALL_DEFINE1(userfaultfd, int, flags)
        struct userfaultfd_ctx *ctx;
        int fd;
 
+       if (!sysctl_unprivileged_userfaultfd && !capable(CAP_SYS_PTRACE))
+               return -EPERM;
+
        BUG_ON(!current->mm);
 
        /* Check the UFFD_* constants for consistency.  */
index 2a462cf..52d4375 100644 (file)
@@ -230,7 +230,7 @@ struct acpi_device_dir {
 /* Plug and Play */
 
 typedef char acpi_bus_id[8];
-typedef unsigned long acpi_bus_address;
+typedef u64 acpi_bus_address;
 typedef char acpi_device_name[40];
 typedef char acpi_device_class[20];
 
index 3b1b1d0..4a8a054 100644 (file)
@@ -12,7 +12,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20190405
+#define ACPI_CA_VERSION                 0x20190509
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
index 624b90b..3105019 100644 (file)
 
 #define ACPI_INIT_FUNCTION __init
 
+/* Use a specific bugging default separate from ACPICA */
+
+#undef ACPI_DEBUG_DEFAULT
+#define ACPI_DEBUG_DEFAULT          (ACPI_LV_INFO | ACPI_LV_REPAIR)
+
 #ifndef CONFIG_ACPI
 
 /* External globals for __KERNEL__, stubs is needed */
 #define ACPI_NO_ERROR_MESSAGES
 #undef ACPI_DEBUG_OUTPUT
 
-/* Use a specific bugging default separate from ACPICA */
-
-#undef ACPI_DEBUG_DEFAULT
-#define ACPI_DEBUG_DEFAULT          (ACPI_LV_INFO | ACPI_LV_REPAIR)
-
 /* External interface for __KERNEL__, stub is needed */
 
 #define ACPI_EXTERNAL_RETURN_STATUS(prototype) \
index 71d7b77..822f433 100644 (file)
@@ -126,4 +126,11 @@ static inline pte_t huge_ptep_get(pte_t *ptep)
 }
 #endif
 
+#ifndef __HAVE_ARCH_GIGANTIC_PAGE_RUNTIME_SUPPORTED
+static inline bool gigantic_page_runtime_supported(void)
+{
+       return IS_ENABLED(CONFIG_ARCH_HAS_GIGANTIC_PAGE);
+}
+#endif /* __HAVE_ARCH_GIGANTIC_PAGE_RUNTIME_SUPPORTED */
+
 #endif /* _ASM_GENERIC_HUGETLB_H */
diff --git a/include/asm-generic/segment.h b/include/asm-generic/segment.h
deleted file mode 100644 (file)
index 5580eac..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __ASM_GENERIC_SEGMENT_H
-#define __ASM_GENERIC_SEGMENT_H
-/*
- * Only here because we have some old header files that expect it...
- *
- * New architectures probably don't want to have their own version.
- */
-
-#endif /* __ASM_GENERIC_SEGMENT_H */
index 8b78c0b..b8f9035 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __ASM_GENERIC_SHMPARAM_H
 #define __ASM_GENERIC_SHMPARAM_H
 
diff --git a/include/asm-generic/sizes.h b/include/asm-generic/sizes.h
deleted file mode 100644 (file)
index 1dcfad9..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/* This is a placeholder, to be removed over time */
-#include <linux/sizes.h>
index b3d2241..e935318 100644 (file)
@@ -9,7 +9,63 @@
  */
 #include <linux/string.h>
 
-#include <asm/segment.h>
+#ifdef CONFIG_UACCESS_MEMCPY
+static inline __must_check unsigned long
+raw_copy_from_user(void *to, const void __user * from, unsigned long n)
+{
+       if (__builtin_constant_p(n)) {
+               switch(n) {
+               case 1:
+                       *(u8 *)to = *(u8 __force *)from;
+                       return 0;
+               case 2:
+                       *(u16 *)to = *(u16 __force *)from;
+                       return 0;
+               case 4:
+                       *(u32 *)to = *(u32 __force *)from;
+                       return 0;
+#ifdef CONFIG_64BIT
+               case 8:
+                       *(u64 *)to = *(u64 __force *)from;
+                       return 0;
+#endif
+               }
+       }
+
+       memcpy(to, (const void __force *)from, n);
+       return 0;
+}
+
+static inline __must_check unsigned long
+raw_copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+       if (__builtin_constant_p(n)) {
+               switch(n) {
+               case 1:
+                       *(u8 __force *)to = *(u8 *)from;
+                       return 0;
+               case 2:
+                       *(u16 __force *)to = *(u16 *)from;
+                       return 0;
+               case 4:
+                       *(u32 __force *)to = *(u32 *)from;
+                       return 0;
+#ifdef CONFIG_64BIT
+               case 8:
+                       *(u64 __force *)to = *(u64 *)from;
+                       return 0;
+#endif
+               default:
+                       break;
+               }
+       }
+
+       memcpy((void __force *)to, from, n);
+       return 0;
+}
+#define INLINE_COPY_FROM_USER
+#define INLINE_COPY_TO_USER
+#endif /* CONFIG_UACCESS_MEMCPY */
 
 #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
 
index bbb9e33..088987e 100644 (file)
                __start_rodata = .;                                     \
                *(.rodata) *(.rodata.*)                                 \
                RO_AFTER_INIT_DATA      /* Read only after init */      \
-               KEEP(*(__vermagic))     /* Kernel version magic */      \
                . = ALIGN(8);                                           \
                __start___tracepoints_ptrs = .;                         \
                KEEP(*(__tracepoints_ptrs)) /* Tracepoints: pointer array */ \
diff --git a/include/dt-bindings/clock/xlnx,zynqmp-clk.h b/include/dt-bindings/clock/xlnx,zynqmp-clk.h
deleted file mode 100644 (file)
index 4aebe6e..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Xilinx Zynq MPSoC Firmware layer
- *
- *  Copyright (C) 2014-2018 Xilinx, Inc.
- *
- */
-
-#ifndef _DT_BINDINGS_CLK_ZYNQMP_H
-#define _DT_BINDINGS_CLK_ZYNQMP_H
-
-#define IOPLL                  0
-#define RPLL                   1
-#define APLL                   2
-#define DPLL                   3
-#define VPLL                   4
-#define IOPLL_TO_FPD           5
-#define RPLL_TO_FPD            6
-#define APLL_TO_LPD            7
-#define DPLL_TO_LPD            8
-#define VPLL_TO_LPD            9
-#define ACPU                   10
-#define ACPU_HALF              11
-#define DBF_FPD                        12
-#define DBF_LPD                        13
-#define DBG_TRACE              14
-#define DBG_TSTMP              15
-#define DP_VIDEO_REF           16
-#define DP_AUDIO_REF           17
-#define DP_STC_REF             18
-#define GDMA_REF               19
-#define DPDMA_REF              20
-#define DDR_REF                        21
-#define SATA_REF               22
-#define PCIE_REF               23
-#define GPU_REF                        24
-#define GPU_PP0_REF            25
-#define GPU_PP1_REF            26
-#define TOPSW_MAIN             27
-#define TOPSW_LSBUS            28
-#define GTGREF0_REF            29
-#define LPD_SWITCH             30
-#define LPD_LSBUS              31
-#define USB0_BUS_REF           32
-#define USB1_BUS_REF           33
-#define USB3_DUAL_REF          34
-#define USB0                   35
-#define USB1                   36
-#define CPU_R5                 37
-#define CPU_R5_CORE            38
-#define CSU_SPB                        39
-#define CSU_PLL                        40
-#define PCAP                   41
-#define IOU_SWITCH             42
-#define GEM_TSU_REF            43
-#define GEM_TSU                        44
-#define GEM0_REF               45
-#define GEM1_REF               46
-#define GEM2_REF               47
-#define GEM3_REF               48
-#define GEM0_TX                        49
-#define GEM1_TX                        50
-#define GEM2_TX                        51
-#define GEM3_TX                        52
-#define QSPI_REF               53
-#define SDIO0_REF              54
-#define SDIO1_REF              55
-#define UART0_REF              56
-#define UART1_REF              57
-#define SPI0_REF               58
-#define SPI1_REF               59
-#define NAND_REF               60
-#define I2C0_REF               61
-#define I2C1_REF               62
-#define CAN0_REF               63
-#define CAN1_REF               64
-#define CAN0                   65
-#define CAN1                   66
-#define DLL_REF                        67
-#define ADMA_REF               68
-#define TIMESTAMP_REF          69
-#define AMS_REF                        70
-#define PL0_REF                        71
-#define PL1_REF                        72
-#define PL2_REF                        73
-#define PL3_REF                        74
-#define WDT                    75
-#define IOPLL_INT              76
-#define IOPLL_PRE_SRC          77
-#define IOPLL_HALF             78
-#define IOPLL_INT_MUX          79
-#define IOPLL_POST_SRC         80
-#define RPLL_INT               81
-#define RPLL_PRE_SRC           82
-#define RPLL_HALF              83
-#define RPLL_INT_MUX           84
-#define RPLL_POST_SRC          85
-#define APLL_INT               86
-#define APLL_PRE_SRC           87
-#define APLL_HALF              88
-#define APLL_INT_MUX           89
-#define APLL_POST_SRC          90
-#define DPLL_INT               91
-#define DPLL_PRE_SRC           92
-#define DPLL_HALF              93
-#define DPLL_INT_MUX           94
-#define DPLL_POST_SRC          95
-#define VPLL_INT               96
-#define VPLL_PRE_SRC           97
-#define VPLL_HALF              98
-#define VPLL_INT_MUX           99
-#define VPLL_POST_SRC          100
-#define CAN0_MIO               101
-#define CAN1_MIO               102
-
-#endif
diff --git a/include/dt-bindings/clock/xlnx-zynqmp-clk.h b/include/dt-bindings/clock/xlnx-zynqmp-clk.h
new file mode 100644 (file)
index 0000000..cdc4c0b
--- /dev/null
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Xilinx Zynq MPSoC Firmware layer
+ *
+ *  Copyright (C) 2014-2018 Xilinx, Inc.
+ *
+ */
+
+#ifndef _DT_BINDINGS_CLK_ZYNQMP_H
+#define _DT_BINDINGS_CLK_ZYNQMP_H
+
+#define IOPLL                  0
+#define RPLL                   1
+#define APLL                   2
+#define DPLL                   3
+#define VPLL                   4
+#define IOPLL_TO_FPD           5
+#define RPLL_TO_FPD            6
+#define APLL_TO_LPD            7
+#define DPLL_TO_LPD            8
+#define VPLL_TO_LPD            9
+#define ACPU                   10
+#define ACPU_HALF              11
+#define DBF_FPD                        12
+#define DBF_LPD                        13
+#define DBG_TRACE              14
+#define DBG_TSTMP              15
+#define DP_VIDEO_REF           16
+#define DP_AUDIO_REF           17
+#define DP_STC_REF             18
+#define GDMA_REF               19
+#define DPDMA_REF              20
+#define DDR_REF                        21
+#define SATA_REF               22
+#define PCIE_REF               23
+#define GPU_REF                        24
+#define GPU_PP0_REF            25
+#define GPU_PP1_REF            26
+#define TOPSW_MAIN             27
+#define TOPSW_LSBUS            28
+#define GTGREF0_REF            29
+#define LPD_SWITCH             30
+#define LPD_LSBUS              31
+#define USB0_BUS_REF           32
+#define USB1_BUS_REF           33
+#define USB3_DUAL_REF          34
+#define USB0                   35
+#define USB1                   36
+#define CPU_R5                 37
+#define CPU_R5_CORE            38
+#define CSU_SPB                        39
+#define CSU_PLL                        40
+#define PCAP                   41
+#define IOU_SWITCH             42
+#define GEM_TSU_REF            43
+#define GEM_TSU                        44
+#define GEM0_TX                        45
+#define GEM1_TX                        46
+#define GEM2_TX                        47
+#define GEM3_TX                        48
+#define GEM0_RX                        49
+#define GEM1_RX                        50
+#define GEM2_RX                        51
+#define GEM3_RX                        52
+#define QSPI_REF               53
+#define SDIO0_REF              54
+#define SDIO1_REF              55
+#define UART0_REF              56
+#define UART1_REF              57
+#define SPI0_REF               58
+#define SPI1_REF               59
+#define NAND_REF               60
+#define I2C0_REF               61
+#define I2C1_REF               62
+#define CAN0_REF               63
+#define CAN1_REF               64
+#define CAN0                   65
+#define CAN1                   66
+#define DLL_REF                        67
+#define ADMA_REF               68
+#define TIMESTAMP_REF          69
+#define AMS_REF                        70
+#define PL0_REF                        71
+#define PL1_REF                        72
+#define PL2_REF                        73
+#define PL3_REF                        74
+#define WDT                    75
+#define IOPLL_INT              76
+#define IOPLL_PRE_SRC          77
+#define IOPLL_HALF             78
+#define IOPLL_INT_MUX          79
+#define IOPLL_POST_SRC         80
+#define RPLL_INT               81
+#define RPLL_PRE_SRC           82
+#define RPLL_HALF              83
+#define RPLL_INT_MUX           84
+#define RPLL_POST_SRC          85
+#define APLL_INT               86
+#define APLL_PRE_SRC           87
+#define APLL_HALF              88
+#define APLL_INT_MUX           89
+#define APLL_POST_SRC          90
+#define DPLL_INT               91
+#define DPLL_PRE_SRC           92
+#define DPLL_HALF              93
+#define DPLL_INT_MUX           94
+#define DPLL_POST_SRC          95
+#define VPLL_INT               96
+#define VPLL_PRE_SRC           97
+#define VPLL_HALF              98
+#define VPLL_INT_MUX           99
+#define VPLL_POST_SRC          100
+#define CAN0_MIO               101
+#define CAN1_MIO               102
+#define ACPU_FULL              103
+#define GEM0_REF               104
+#define GEM1_REF               105
+#define GEM2_REF               106
+#define GEM3_REF               107
+#define GEM0_REF_UNG           108
+#define GEM1_REF_UNG           109
+#define GEM2_REF_UNG           110
+#define GEM3_REF_UNG           111
+#define LPD_WDT                        112
+
+#endif
index 4481f2d..4e61f64 100644 (file)
 #define IMX_SC_R_DC_0_BLIT1            20
 #define IMX_SC_R_DC_0_BLIT2            21
 #define IMX_SC_R_DC_0_BLIT_OUT         22
-#define IMX_SC_R_DC_0_CAPTURE0         23
-#define IMX_SC_R_DC_0_CAPTURE1         24
+#define IMX_SC_R_PERF                  23
 #define IMX_SC_R_DC_0_WARP             25
-#define IMX_SC_R_DC_0_INTEGRAL0                26
-#define IMX_SC_R_DC_0_INTEGRAL1                27
 #define IMX_SC_R_DC_0_VIDEO0           28
 #define IMX_SC_R_DC_0_VIDEO1           29
 #define IMX_SC_R_DC_0_FRAC0            30
-#define IMX_SC_R_DC_0_FRAC1            31
 #define IMX_SC_R_DC_0                  32
 #define IMX_SC_R_GPU_2_PID0            33
 #define IMX_SC_R_DC_0_PLL_0            34
 #define IMX_SC_R_DC_1_BLIT1            37
 #define IMX_SC_R_DC_1_BLIT2            38
 #define IMX_SC_R_DC_1_BLIT_OUT         39
-#define IMX_SC_R_DC_1_CAPTURE0         40
-#define IMX_SC_R_DC_1_CAPTURE1         41
 #define IMX_SC_R_DC_1_WARP             42
-#define IMX_SC_R_DC_1_INTEGRAL0                43
-#define IMX_SC_R_DC_1_INTEGRAL1                44
 #define IMX_SC_R_DC_1_VIDEO0           45
 #define IMX_SC_R_DC_1_VIDEO1           46
 #define IMX_SC_R_DC_1_FRAC0            47
-#define IMX_SC_R_DC_1_FRAC1            48
 #define IMX_SC_R_DC_1                  49
-#define IMX_SC_R_GPU_3_PID0            50
 #define IMX_SC_R_DC_1_PLL_0            51
 #define IMX_SC_R_DC_1_PLL_1            52
 #define IMX_SC_R_SPI_0                 53
 #define IMX_SC_R_M4_0_UART             287
 #define IMX_SC_R_M4_0_I2C              288
 #define IMX_SC_R_M4_0_INTMUX           289
-#define IMX_SC_R_M4_0_SIM              290
-#define IMX_SC_R_M4_0_WDOG             291
 #define IMX_SC_R_M4_0_MU_0B            292
 #define IMX_SC_R_M4_0_MU_0A0           293
 #define IMX_SC_R_M4_0_MU_0A1           294
 #define IMX_SC_R_M4_1_UART             307
 #define IMX_SC_R_M4_1_I2C              308
 #define IMX_SC_R_M4_1_INTMUX           309
-#define IMX_SC_R_M4_1_SIM              310
-#define IMX_SC_R_M4_1_WDOG             311
 #define IMX_SC_R_M4_1_MU_0B            312
 #define IMX_SC_R_M4_1_MU_0A0           313
 #define IMX_SC_R_M4_1_MU_0A1           314
 #define IMX_SC_R_IRQSTR_SCU2           321
 #define IMX_SC_R_IRQSTR_DSP            322
 #define IMX_SC_R_ELCDIF_PLL            323
-#define IMX_SC_R_UNUSED6               324
+#define IMX_SC_R_OCRAM                 324
 #define IMX_SC_R_AUDIO_PLL_0           325
 #define IMX_SC_R_PI_0                  326
 #define IMX_SC_R_PI_0_PWM_0            327
 #define IMX_SC_R_VPU_MU_3              538
 #define IMX_SC_R_VPU_ENC_1             539
 #define IMX_SC_R_VPU                   540
-#define IMX_SC_R_LAST                  541
+#define IMX_SC_R_DMA_5_CH0             541
+#define IMX_SC_R_DMA_5_CH1             542
+#define IMX_SC_R_DMA_5_CH2             543
+#define IMX_SC_R_DMA_5_CH3             544
+#define IMX_SC_R_ATTESTATION           545
+#define IMX_SC_R_LAST                  546
 
 #endif /* __DT_BINDINGS_RSCRC_IMX_H */
index 7d947a5..17877e8 100644 (file)
 #undef PIN_OFF_INPUT_PULLDOWN
 #undef PIN_OFF_WAKEUPENABLE
 
-#endif
+#define AM335X_PIN_OFFSET_MIN                  0x0800U
+
+#define AM335X_PIN_GPMC_AD0                    0x800
+#define AM335X_PIN_GPMC_AD1                    0x804
+#define AM335X_PIN_GPMC_AD2                    0x808
+#define AM335X_PIN_GPMC_AD3                    0x80c
+#define AM335X_PIN_GPMC_AD4                    0x810
+#define AM335X_PIN_GPMC_AD5                    0x814
+#define AM335X_PIN_GPMC_AD6                    0x818
+#define AM335X_PIN_GPMC_AD7                    0x81c
+#define AM335X_PIN_GPMC_AD8                    0x820
+#define AM335X_PIN_GPMC_AD9                    0x824
+#define AM335X_PIN_GPMC_AD10                   0x828
+#define AM335X_PIN_GPMC_AD11                   0x82c
+#define AM335X_PIN_GPMC_AD12                   0x830
+#define AM335X_PIN_GPMC_AD13                   0x834
+#define AM335X_PIN_GPMC_AD14                   0x838
+#define AM335X_PIN_GPMC_AD15                   0x83c
+#define AM335X_PIN_GPMC_A0                     0x840
+#define AM335X_PIN_GPMC_A1                     0x844
+#define AM335X_PIN_GPMC_A2                     0x848
+#define AM335X_PIN_GPMC_A3                     0x84c
+#define AM335X_PIN_GPMC_A4                     0x850
+#define AM335X_PIN_GPMC_A5                     0x854
+#define AM335X_PIN_GPMC_A6                     0x858
+#define AM335X_PIN_GPMC_A7                     0x85c
+#define AM335X_PIN_GPMC_A8                     0x860
+#define AM335X_PIN_GPMC_A9                     0x864
+#define AM335X_PIN_GPMC_A10                    0x868
+#define AM335X_PIN_GPMC_A11                    0x86c
+#define AM335X_PIN_GPMC_WAIT0                  0x870
+#define AM335X_PIN_GPMC_WPN                    0x874
+#define AM335X_PIN_GPMC_BEN1                   0x878
+#define AM335X_PIN_GPMC_CSN0                   0x87c
+#define AM335X_PIN_GPMC_CSN1                   0x880
+#define AM335X_PIN_GPMC_CSN2                   0x884
+#define AM335X_PIN_GPMC_CSN3                   0x888
+#define AM335X_PIN_GPMC_CLK                    0x88c
+#define AM335X_PIN_GPMC_ADVN_ALE               0x890
+#define AM335X_PIN_GPMC_OEN_REN                        0x894
+#define AM335X_PIN_GPMC_WEN                    0x898
+#define AM335X_PIN_GPMC_BEN0_CLE               0x89c
+#define AM335X_PIN_LCD_DATA0                   0x8a0
+#define AM335X_PIN_LCD_DATA1                   0x8a4
+#define AM335X_PIN_LCD_DATA2                   0x8a8
+#define AM335X_PIN_LCD_DATA3                   0x8ac
+#define AM335X_PIN_LCD_DATA4                   0x8b0
+#define AM335X_PIN_LCD_DATA5                   0x8b4
+#define AM335X_PIN_LCD_DATA6                   0x8b8
+#define AM335X_PIN_LCD_DATA7                   0x8bc
+#define AM335X_PIN_LCD_DATA8                   0x8c0
+#define AM335X_PIN_LCD_DATA9                   0x8c4
+#define AM335X_PIN_LCD_DATA10                  0x8c8
+#define AM335X_PIN_LCD_DATA11                  0x8cc
+#define AM335X_PIN_LCD_DATA12                  0x8d0
+#define AM335X_PIN_LCD_DATA13                  0x8d4
+#define AM335X_PIN_LCD_DATA14                  0x8d8
+#define AM335X_PIN_LCD_DATA15                  0x8dc
+#define AM335X_PIN_LCD_VSYNC                   0x8e0
+#define AM335X_PIN_LCD_HSYNC                   0x8e4
+#define AM335X_PIN_LCD_PCLK                    0x8e8
+#define AM335X_PIN_LCD_AC_BIAS_EN              0x8ec
+#define AM335X_PIN_MMC0_DAT3                   0x8f0
+#define AM335X_PIN_MMC0_DAT2                   0x8f4
+#define AM335X_PIN_MMC0_DAT1                   0x8f8
+#define AM335X_PIN_MMC0_DAT0                   0x8fc
+#define AM335X_PIN_MMC0_CLK                    0x900
+#define AM335X_PIN_MMC0_CMD                    0x904
+#define AM335X_PIN_MII1_COL                    0x908
+#define AM335X_PIN_MII1_CRS                    0x90c
+#define AM335X_PIN_MII1_RX_ER                  0x910
+#define AM335X_PIN_MII1_TX_EN                  0x914
+#define AM335X_PIN_MII1_RX_DV                  0x918
+#define AM335X_PIN_MII1_TXD3                   0x91c
+#define AM335X_PIN_MII1_TXD2                   0x920
+#define AM335X_PIN_MII1_TXD1                   0x924
+#define AM335X_PIN_MII1_TXD0                   0x928
+#define AM335X_PIN_MII1_TX_CLK                 0x92c
+#define AM335X_PIN_MII1_RX_CLK                 0x930
+#define AM335X_PIN_MII1_RXD3                   0x934
+#define AM335X_PIN_MII1_RXD2                   0x938
+#define AM335X_PIN_MII1_RXD1                   0x93c
+#define AM335X_PIN_MII1_RXD0                   0x940
+#define AM335X_PIN_RMII1_REF_CLK               0x944
+#define AM335X_PIN_MDIO                                0x948
+#define AM335X_PIN_MDC                         0x94c
+#define AM335X_PIN_SPI0_SCLK                   0x950
+#define AM335X_PIN_SPI0_D0                     0x954
+#define AM335X_PIN_SPI0_D1                     0x958
+#define AM335X_PIN_SPI0_CS0                    0x95c
+#define AM335X_PIN_SPI0_CS1                    0x960
+#define AM335X_PIN_ECAP0_IN_PWM0_OUT           0x964
+#define AM335X_PIN_UART0_CTSN                  0x968
+#define AM335X_PIN_UART0_RTSN                  0x96c
+#define AM335X_PIN_UART0_RXD                   0x970
+#define AM335X_PIN_UART0_TXD                   0x974
+#define AM335X_PIN_UART1_CTSN                  0x978
+#define AM335X_PIN_UART1_RTSN                  0x97c
+#define AM335X_PIN_UART1_RXD                   0x980
+#define AM335X_PIN_UART1_TXD                   0x984
+#define AM335X_PIN_I2C0_SDA                    0x988
+#define AM335X_PIN_I2C0_SCL                    0x98c
+#define AM335X_PIN_MCASP0_ACLKX                        0x990
+#define AM335X_PIN_MCASP0_FSX                  0x994
+#define AM335X_PIN_MCASP0_AXR0                 0x998
+#define AM335X_PIN_MCASP0_AHCLKR               0x99c
+#define AM335X_PIN_MCASP0_ACLKR                        0x9a0
+#define AM335X_PIN_MCASP0_FSR                  0x9a4
+#define AM335X_PIN_MCASP0_AXR1                 0x9a8
+#define AM335X_PIN_MCASP0_AHCLKX               0x9ac
+#define AM335X_PIN_XDMA_EVENT_INTR0            0x9b0
+#define AM335X_PIN_XDMA_EVENT_INTR1            0x9b4
+#define AM335X_PIN_WARMRSTN                    0x9b8
+#define AM335X_PIN_NNMI                                0x9c0
+#define AM335X_PIN_TMS                         0x9d0
+#define AM335X_PIN_TDI                         0x9d4
+#define AM335X_PIN_TDO                         0x9d8
+#define AM335X_PIN_TCK                         0x9dc
+#define AM335X_PIN_TRSTN                       0x9e0
+#define AM335X_PIN_EMU0                                0x9e4
+#define AM335X_PIN_EMU1                                0x9e8
+#define AM335X_PIN_RTC_PWRONRSTN               0x9f8
+#define AM335X_PIN_PMIC_POWER_EN               0x9fc
+#define AM335X_PIN_EXT_WAKEUP                  0xa00
+#define AM335X_PIN_USB0_DRVVBUS                        0xa1c
+#define AM335X_PIN_USB1_DRVVBUS                        0xa34
 
+#define AM335X_PIN_OFFSET_MAX                  0x0a34U
+
+#endif
index 49b5dea..6257180 100644 (file)
@@ -65,6 +65,7 @@
 #define DM814X_IOPAD(pa, val)          OMAP_IOPAD_OFFSET((pa), 0x0800) (val)
 #define DM816X_IOPAD(pa, val)          OMAP_IOPAD_OFFSET((pa), 0x0800) (val)
 #define AM33XX_IOPAD(pa, val)          OMAP_IOPAD_OFFSET((pa), 0x0800) (val)
+#define AM33XX_PADCONF(pa, dir, mux)   OMAP_IOPAD_OFFSET((pa), 0x0800) ((dir) | (mux))
 
 /*
  * Macros to allow using the offset from the padconf physical address
index 05a4b59..de82d8a 100644 (file)
@@ -21,7 +21,6 @@
 #define R8A77965_PD_A3VC               14
 #define R8A77965_PD_3DG_A              17
 #define R8A77965_PD_3DG_B              18
-#define R8A77965_PD_A3IR               24
 #define R8A77965_PD_A2VC1              26
 
 /* Always-on power area */
index c15e8b7..444c7bd 100644 (file)
@@ -12,9 +12,9 @@
 #define TEGRA124_SOCTHERM_SENSOR_PLLX 3
 #define TEGRA124_SOCTHERM_SENSOR_NUM 4
 
-#define TEGRA_SOCTHERM_THROT_LEVEL_LOW  0
-#define TEGRA_SOCTHERM_THROT_LEVEL_MED  1
-#define TEGRA_SOCTHERM_THROT_LEVEL_HIGH 2
-#define TEGRA_SOCTHERM_THROT_LEVEL_NONE -1
+#define TEGRA_SOCTHERM_THROT_LEVEL_NONE 0
+#define TEGRA_SOCTHERM_THROT_LEVEL_LOW  1
+#define TEGRA_SOCTHERM_THROT_LEVEL_MED  2
+#define TEGRA_SOCTHERM_THROT_LEVEL_HIGH 3
 
 #endif
index e22c237..98440df 100644 (file)
@@ -517,7 +517,8 @@ extern bool osc_pc_lpi_support_confirmed;
 #define OSC_PCI_CLOCK_PM_SUPPORT               0x00000004
 #define OSC_PCI_SEGMENT_GROUPS_SUPPORT         0x00000008
 #define OSC_PCI_MSI_SUPPORT                    0x00000010
-#define OSC_PCI_SUPPORT_MASKS                  0x0000001f
+#define OSC_PCI_HPX_TYPE_3_SUPPORT             0x00000100
+#define OSC_PCI_SUPPORT_MASKS                  0x0000011f
 
 /* PCI Host Bridge _OSC: Capabilities DWORD 3: Control Field */
 #define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL      0x00000001
index f111c78..f31521d 100644 (file)
@@ -151,21 +151,6 @@ static inline void balloon_page_delete(struct page *page)
        list_del(&page->lru);
 }
 
-static inline bool __is_movable_balloon_page(struct page *page)
-{
-       return false;
-}
-
-static inline bool balloon_page_movable(struct page *page)
-{
-       return false;
-}
-
-static inline bool isolated_balloon_page(struct page *page)
-{
-       return false;
-}
-
 static inline bool balloon_page_isolate(struct page *page)
 {
        return false;
index 688ab0d..b40fc63 100644 (file)
@@ -15,7 +15,6 @@ struct filename;
  * This structure is used to hold the arguments that are used when loading binaries.
  */
 struct linux_binprm {
-       char buf[BINPRM_BUF_SIZE];
 #ifdef CONFIG_MMU
        struct vm_area_struct *vma;
        unsigned long vma_pages;
@@ -64,6 +63,8 @@ struct linux_binprm {
        unsigned long loader, exec;
 
        struct rlimit rlim_stack; /* Saved RLIMIT_STACK used during exec. */
+
+       char buf[BINPRM_BUF_SIZE];
 } __randomize_layout;
 
 #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
index 602af23..cf074bc 100644 (file)
@@ -60,7 +60,7 @@ static __always_inline unsigned long hweight_long(unsigned long w)
  */
 static inline __u64 rol64(__u64 word, unsigned int shift)
 {
-       return (word << shift) | (word >> (64 - shift));
+       return (word << (shift & 63)) | (word >> ((-shift) & 63));
 }
 
 /**
@@ -70,7 +70,7 @@ static inline __u64 rol64(__u64 word, unsigned int shift)
  */
 static inline __u64 ror64(__u64 word, unsigned int shift)
 {
-       return (word >> shift) | (word << (64 - shift));
+       return (word >> (shift & 63)) | (word << ((-shift) & 63));
 }
 
 /**
@@ -80,7 +80,7 @@ static inline __u64 ror64(__u64 word, unsigned int shift)
  */
 static inline __u32 rol32(__u32 word, unsigned int shift)
 {
-       return (word << shift) | (word >> ((-shift) & 31));
+       return (word << (shift & 31)) | (word >> ((-shift) & 31));
 }
 
 /**
@@ -90,7 +90,7 @@ static inline __u32 rol32(__u32 word, unsigned int shift)
  */
 static inline __u32 ror32(__u32 word, unsigned int shift)
 {
-       return (word >> shift) | (word << (32 - shift));
+       return (word >> (shift & 31)) | (word << ((-shift) & 31));
 }
 
 /**
@@ -100,7 +100,7 @@ static inline __u32 ror32(__u32 word, unsigned int shift)
  */
 static inline __u16 rol16(__u16 word, unsigned int shift)
 {
-       return (word << shift) | (word >> (16 - shift));
+       return (word << (shift & 15)) | (word >> ((-shift) & 15));
 }
 
 /**
@@ -110,7 +110,7 @@ static inline __u16 rol16(__u16 word, unsigned int shift)
  */
 static inline __u16 ror16(__u16 word, unsigned int shift)
 {
-       return (word >> shift) | (word << (16 - shift));
+       return (word >> (shift & 15)) | (word << ((-shift) & 15));
 }
 
 /**
@@ -120,7 +120,7 @@ static inline __u16 ror16(__u16 word, unsigned int shift)
  */
 static inline __u8 rol8(__u8 word, unsigned int shift)
 {
-       return (word << shift) | (word >> (8 - shift));
+       return (word << (shift & 7)) | (word >> ((-shift) & 7));
 }
 
 /**
@@ -130,7 +130,7 @@ static inline __u8 rol8(__u8 word, unsigned int shift)
  */
 static inline __u8 ror8(__u8 word, unsigned int shift)
 {
-       return (word >> shift) | (word << (8 - shift));
+       return (word >> (shift & 7)) | (word << ((-shift) & 7));
 }
 
 /**
index 4903deb..3ac0fea 100644 (file)
@@ -436,6 +436,12 @@ union ceph_mds_request_args {
                __le64 length; /* num bytes to lock from start */
                __u8 wait; /* will caller wait for lock to become available? */
        } __attribute__ ((packed)) filelock_change;
+       struct {
+               __le32 mask;                 /* CEPH_CAP_* */
+               __le64 snapid;
+               __le64 parent;
+               __le32 hash;
+       } __attribute__ ((packed)) lookupino;
 } __attribute__ ((packed));
 
 #define CEPH_MDS_FLAG_REPLAY        1  /* this is a replayed op */
index 800a212..23895d1 100644 (file)
@@ -323,7 +323,8 @@ struct ceph_connection {
 };
 
 
-extern const char *ceph_pr_addr(const struct sockaddr_storage *ss);
+extern const char *ceph_pr_addr(const struct ceph_entity_addr *addr);
+
 extern int ceph_parse_ips(const char *c, const char *end,
                          struct ceph_entity_addr *addr,
                          int max_count, int *count);
index 5675b1f..e081b56 100644 (file)
@@ -110,17 +110,16 @@ struct ceph_object_id {
        int name_len;
 };
 
+#define __CEPH_OID_INITIALIZER(oid) { .name = (oid).inline_name }
+
+#define CEPH_DEFINE_OID_ONSTACK(oid)                           \
+       struct ceph_object_id oid = __CEPH_OID_INITIALIZER(oid)
+
 static inline void ceph_oid_init(struct ceph_object_id *oid)
 {
-       oid->name = oid->inline_name;
-       oid->name_len = 0;
+       *oid = (struct ceph_object_id) __CEPH_OID_INITIALIZER(*oid);
 }
 
-#define CEPH_OID_INIT_ONSTACK(oid)                                     \
-    ({ ceph_oid_init(&oid); oid; })
-#define CEPH_DEFINE_OID_ONSTACK(oid)                                   \
-       struct ceph_object_id oid = CEPH_OID_INIT_ONSTACK(oid)
-
 static inline bool ceph_oid_empty(const struct ceph_object_id *oid)
 {
        return oid->name == oid->inline_name && !oid->name_len;
index 491d992..bb6118f 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef __LINUX_CLK_PROVIDER_H
 #define __LINUX_CLK_PROVIDER_H
 
-#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_clk.h>
 
index d58aa0d..8aaf7cd 100644 (file)
@@ -53,23 +53,24 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
  * "Define 'is'", Bill Clinton
  * "Define 'if'", Steven Rostedt
  */
-#define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
-#define __trace_if(cond) \
-       if (__builtin_constant_p(!!(cond)) ? !!(cond) :                 \
-       ({                                                              \
-               int ______r;                                            \
-               static struct ftrace_branch_data                        \
-                       __aligned(4)                                    \
-                       __section("_ftrace_branch")                     \
-                       ______f = {                                     \
-                               .func = __func__,                       \
-                               .file = __FILE__,                       \
-                               .line = __LINE__,                       \
-                       };                                              \
-               ______r = !!(cond);                                     \
-               ______r ? ______f.miss_hit[1]++ : ______f.miss_hit[0]++;\
-               ______r;                                                \
-       }))
+#define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
+
+#define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
+
+#define __trace_if_value(cond) ({                      \
+       static struct ftrace_branch_data                \
+               __aligned(4)                            \
+               __section("_ftrace_branch")             \
+               __if_trace = {                          \
+                       .func = __func__,               \
+                       .file = __FILE__,               \
+                       .line = __LINE__,               \
+               };                                      \
+       (cond) ?                                        \
+               (__if_trace.miss_hit[1]++,1) :          \
+               (__if_trace.miss_hit[0]++,0);           \
+})
+
 #endif /* CONFIG_PROFILE_ALL_BRANCHES */
 
 #else
index ba814f1..19e58b9 100644 (file)
@@ -140,8 +140,7 @@ struct ftrace_likely_data {
  * Do not use __always_inline here, since currently it expands to inline again
  * (which would break users of __always_inline).
  */
-#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
-       !defined(CONFIG_OPTIMIZE_INLINING)
+#if !defined(CONFIG_OPTIMIZE_INLINING)
 #define inline inline __attribute__((__always_inline__)) __gnu_inline \
        __maybe_unused notrace
 #else
index 9c703a0..cc4980b 100644 (file)
@@ -44,7 +44,7 @@
  */
 #define CPER_REC_LEN                                   256
 /*
- * Severity difinition for error_severity in struct cper_record_header
+ * Severity definition for error_severity in struct cper_record_header
  * and section_severity in struct cper_section_descriptor
  */
 enum {
@@ -55,24 +55,21 @@ enum {
 };
 
 /*
- * Validation bits difinition for validation_bits in struct
+ * Validation bits definition for validation_bits in struct
  * cper_record_header. If set, corresponding fields in struct
  * cper_record_header contain valid information.
- *
- * corresponds platform_id
  */
 #define CPER_VALID_PLATFORM_ID                 0x0001
-/* corresponds timestamp */
 #define CPER_VALID_TIMESTAMP                   0x0002
-/* corresponds partition_id */
 #define CPER_VALID_PARTITION_ID                        0x0004
 
 /*
  * Notification type used to generate error record, used in
- * notification_type in struct cper_record_header
- *
- * Corrected Machine Check
+ * notification_type in struct cper_record_header.  These UUIDs are defined
+ * in the UEFI spec v2.7, sec N.2.1.
  */
+
+/* Corrected Machine Check */
 #define CPER_NOTIFY_CMC                                                        \
        GUID_INIT(0x2DCE8BB1, 0xBDD7, 0x450e, 0xB9, 0xAD, 0x9C, 0xF4,   \
                  0xEB, 0xD4, 0xF8, 0x90)
@@ -122,14 +119,11 @@ enum {
 #define CPER_SEC_REV                           0x0100
 
 /*
- * Validation bits difinition for validation_bits in struct
+ * Validation bits definition for validation_bits in struct
  * cper_section_descriptor. If set, corresponding fields in struct
  * cper_section_descriptor contain valid information.
- *
- * corresponds fru_id
  */
 #define CPER_SEC_VALID_FRU_ID                  0x1
-/* corresponds fru_text */
 #define CPER_SEC_VALID_FRU_TEXT                        0x2
 
 /*
@@ -165,10 +159,11 @@ enum {
 
 /*
  * Section type definitions, used in section_type field in struct
- * cper_section_descriptor
- *
- * Processor Generic
+ * cper_section_descriptor.  These UUIDs are defined in the UEFI spec
+ * v2.7, sec N.2.2.
  */
+
+/* Processor Generic */
 #define CPER_SEC_PROC_GENERIC                                          \
        GUID_INIT(0x9876CCAD, 0x47B4, 0x4bdb, 0xB6, 0x5E, 0x16, 0xF1,   \
                  0x93, 0xC4, 0xF3, 0xDB)
@@ -325,220 +320,223 @@ enum {
  */
 #pragma pack(1)
 
+/* Record Header, UEFI v2.7 sec N.2.1 */
 struct cper_record_header {
        char    signature[CPER_SIG_SIZE];       /* must be CPER_SIG_RECORD */
-       __u16   revision;                       /* must be CPER_RECORD_REV */
-       __u32   signature_end;                  /* must be CPER_SIG_END */
-       __u16   section_count;
-       __u32   error_severity;
-       __u32   validation_bits;
-       __u32   record_length;
-       __u64   timestamp;
+       u16     revision;                       /* must be CPER_RECORD_REV */
+       u32     signature_end;                  /* must be CPER_SIG_END */
+       u16     section_count;
+       u32     error_severity;
+       u32     validation_bits;
+       u32     record_length;
+       u64     timestamp;
        guid_t  platform_id;
        guid_t  partition_id;
        guid_t  creator_id;
        guid_t  notification_type;
-       __u64   record_id;
-       __u32   flags;
-       __u64   persistence_information;
-       __u8    reserved[12];                   /* must be zero */
+       u64     record_id;
+       u32     flags;
+       u64     persistence_information;
+       u8      reserved[12];                   /* must be zero */
 };
 
+/* Section Descriptor, UEFI v2.7 sec N.2.2 */
 struct cper_section_descriptor {
-       __u32   section_offset;         /* Offset in bytes of the
+       u32     section_offset;         /* Offset in bytes of the
                                         *  section body from the base
                                         *  of the record header */
-       __u32   section_length;
-       __u16   revision;               /* must be CPER_RECORD_REV */
-       __u8    validation_bits;
-       __u8    reserved;               /* must be zero */
-       __u32   flags;
+       u32     section_length;
+       u16     revision;               /* must be CPER_RECORD_REV */
+       u8      validation_bits;
+       u8      reserved;               /* must be zero */
+       u32     flags;
        guid_t  section_type;
        guid_t  fru_id;
-       __u32   section_severity;
-       __u8    fru_text[20];
+       u32     section_severity;
+       u8      fru_text[20];
 };
 
-/* Generic Processor Error Section */
+/* Generic Processor Error Section, UEFI v2.7 sec N.2.4.1 */
 struct cper_sec_proc_generic {
-       __u64   validation_bits;
-       __u8    proc_type;
-       __u8    proc_isa;
-       __u8    proc_error_type;
-       __u8    operation;
-       __u8    flags;
-       __u8    level;
-       __u16   reserved;
-       __u64   cpu_version;
+       u64     validation_bits;
+       u8      proc_type;
+       u8      proc_isa;
+       u8      proc_error_type;
+       u8      operation;
+       u8      flags;
+       u8      level;
+       u16     reserved;
+       u64     cpu_version;
        char    cpu_brand[128];
-       __u64   proc_id;
-       __u64   target_addr;
-       __u64   requestor_id;
-       __u64   responder_id;
-       __u64   ip;
+       u64     proc_id;
+       u64     target_addr;
+       u64     requestor_id;
+       u64     responder_id;
+       u64     ip;
 };
 
-/* IA32/X64 Processor Error Section */
+/* IA32/X64 Processor Error Section, UEFI v2.7 sec N.2.4.2 */
 struct cper_sec_proc_ia {
-       __u64   validation_bits;
-       __u64   lapic_id;
-       __u8    cpuid[48];
+       u64     validation_bits;
+       u64     lapic_id;
+       u8      cpuid[48];
 };
 
-/* IA32/X64 Processor Error Information Structure */
+/* IA32/X64 Processor Error Information Structure, UEFI v2.7 sec N.2.4.2.1 */
 struct cper_ia_err_info {
        guid_t  err_type;
-       __u64   validation_bits;
-       __u64   check_info;
-       __u64   target_id;
-       __u64   requestor_id;
-       __u64   responder_id;
-       __u64   ip;
+       u64     validation_bits;
+       u64     check_info;
+       u64     target_id;
+       u64     requestor_id;
+       u64     responder_id;
+       u64     ip;
 };
 
-/* IA32/X64 Processor Context Information Structure */
+/* IA32/X64 Processor Context Information Structure, UEFI v2.7 sec N.2.4.2.2 */
 struct cper_ia_proc_ctx {
-       __u16   reg_ctx_type;
-       __u16   reg_arr_size;
-       __u32   msr_addr;
-       __u64   mm_reg_addr;
+       u16     reg_ctx_type;
+       u16     reg_arr_size;
+       u32     msr_addr;
+       u64     mm_reg_addr;
 };
 
-/* ARM Processor Error Section */
+/* ARM Processor Error Section, UEFI v2.7 sec N.2.4.4 */
 struct cper_sec_proc_arm {
-       __u32   validation_bits;
-       __u16   err_info_num;           /* Number of Processor Error Info */
-       __u16   context_info_num;       /* Number of Processor Context Info Records*/
-       __u32   section_length;
-       __u8    affinity_level;
-       __u8    reserved[3];            /* must be zero */
-       __u64   mpidr;
-       __u64   midr;
-       __u32   running_state;          /* Bit 0 set - Processor running. PSCI = 0 */
-       __u32   psci_state;
+       u32     validation_bits;
+       u16     err_info_num;           /* Number of Processor Error Info */
+       u16     context_info_num;       /* Number of Processor Context Info Records*/
+       u32     section_length;
+       u8      affinity_level;
+       u8      reserved[3];            /* must be zero */
+       u64     mpidr;
+       u64     midr;
+       u32     running_state;          /* Bit 0 set - Processor running. PSCI = 0 */
+       u32     psci_state;
 };
 
-/* ARM Processor Error Information Structure */
+/* ARM Processor Error Information Structure, UEFI v2.7 sec N.2.4.4.1 */
 struct cper_arm_err_info {
-       __u8    version;
-       __u8    length;
-       __u16   validation_bits;
-       __u8    type;
-       __u16   multiple_error;
-       __u8    flags;
-       __u64   error_info;
-       __u64   virt_fault_addr;
-       __u64   physical_fault_addr;
+       u8      version;
+       u8      length;
+       u16     validation_bits;
+       u8      type;
+       u16     multiple_error;
+       u8      flags;
+       u64     error_info;
+       u64     virt_fault_addr;
+       u64     physical_fault_addr;
 };
 
-/* ARM Processor Context Information Structure */
+/* ARM Processor Context Information Structure, UEFI v2.7 sec N.2.4.4.2 */
 struct cper_arm_ctx_info {
-       __u16   version;
-       __u16   type;
-       __u32   size;
+       u16     version;
+       u16     type;
+       u32     size;
 };
 
-/* Old Memory Error Section UEFI 2.1, 2.2 */
+/* Old Memory Error Section, UEFI v2.1, v2.2 */
 struct cper_sec_mem_err_old {
-       __u64   validation_bits;
-       __u64   error_status;
-       __u64   physical_addr;
-       __u64   physical_addr_mask;
-       __u16   node;
-       __u16   card;
-       __u16   module;
-       __u16   bank;
-       __u16   device;
-       __u16   row;
-       __u16   column;
-       __u16   bit_pos;
-       __u64   requestor_id;
-       __u64   responder_id;
-       __u64   target_id;
-       __u8    error_type;
+       u64     validation_bits;
+       u64     error_status;
+       u64     physical_addr;
+       u64     physical_addr_mask;
+       u16     node;
+       u16     card;
+       u16     module;
+       u16     bank;
+       u16     device;
+       u16     row;
+       u16     column;
+       u16     bit_pos;
+       u64     requestor_id;
+       u64     responder_id;
+       u64     target_id;
+       u8      error_type;
 };
 
-/* Memory Error Section UEFI >= 2.3 */
+/* Memory Error Section (UEFI >= v2.3), UEFI v2.7 sec N.2.5 */
 struct cper_sec_mem_err {
-       __u64   validation_bits;
-       __u64   error_status;
-       __u64   physical_addr;
-       __u64   physical_addr_mask;
-       __u16   node;
-       __u16   card;
-       __u16   module;
-       __u16   bank;
-       __u16   device;
-       __u16   row;
-       __u16   column;
-       __u16   bit_pos;
-       __u64   requestor_id;
-       __u64   responder_id;
-       __u64   target_id;
-       __u8    error_type;
-       __u8    reserved;
-       __u16   rank;
-       __u16   mem_array_handle;       /* card handle in UEFI 2.4 */
-       __u16   mem_dev_handle;         /* module handle in UEFI 2.4 */
+       u64     validation_bits;
+       u64     error_status;
+       u64     physical_addr;
+       u64     physical_addr_mask;
+       u16     node;
+       u16     card;
+       u16     module;
+       u16     bank;
+       u16     device;
+       u16     row;
+       u16     column;
+       u16     bit_pos;
+       u64     requestor_id;
+       u64     responder_id;
+       u64     target_id;
+       u8      error_type;
+       u8      reserved;
+       u16     rank;
+       u16     mem_array_handle;       /* "card handle" in UEFI 2.4 */
+       u16     mem_dev_handle;         /* "module handle" in UEFI 2.4 */
 };
 
 struct cper_mem_err_compact {
-       __u64   validation_bits;
-       __u16   node;
-       __u16   card;
-       __u16   module;
-       __u16   bank;
-       __u16   device;
-       __u16   row;
-       __u16   column;
-       __u16   bit_pos;
-       __u64   requestor_id;
-       __u64   responder_id;
-       __u64   target_id;
-       __u16   rank;
-       __u16   mem_array_handle;
-       __u16   mem_dev_handle;
+       u64     validation_bits;
+       u16     node;
+       u16     card;
+       u16     module;
+       u16     bank;
+       u16     device;
+       u16     row;
+       u16     column;
+       u16     bit_pos;
+       u64     requestor_id;
+       u64     responder_id;
+       u64     target_id;
+       u16     rank;
+       u16     mem_array_handle;
+       u16     mem_dev_handle;
 };
 
+/* PCI Express Error Section, UEFI v2.7 sec N.2.7 */
 struct cper_sec_pcie {
-       __u64           validation_bits;
-       __u32           port_type;
+       u64             validation_bits;
+       u32             port_type;
        struct {
-               __u8    minor;
-               __u8    major;
-               __u8    reserved[2];
+               u8      minor;
+               u8      major;
+               u8      reserved[2];
        }               version;
-       __u16           command;
-       __u16           status;
-       __u32           reserved;
+       u16             command;
+       u16             status;
+       u32             reserved;
        struct {
-               __u16   vendor_id;
-               __u16   device_id;
-               __u8    class_code[3];
-               __u8    function;
-               __u8    device;
-               __u16   segment;
-               __u8    bus;
-               __u8    secondary_bus;
-               __u16   slot;
-               __u8    reserved;
+               u16     vendor_id;
+               u16     device_id;
+               u8      class_code[3];
+               u8      function;
+               u8      device;
+               u16     segment;
+               u8      bus;
+               u8      secondary_bus;
+               u16     slot;
+               u8      reserved;
        }               device_id;
        struct {
-               __u32   lower;
-               __u32   upper;
+               u32     lower;
+               u32     upper;
        }               serial_number;
        struct {
-               __u16   secondary_status;
-               __u16   control;
+               u16     secondary_status;
+               u16     control;
        }               bridge;
-       __u8    capability[60];
-       __u8    aer_info[96];
+       u8      capability[60];
+       u8      aer_info[96];
 };
 
 /* Reset to default packing */
 #pragma pack()
 
-extern const char * const cper_proc_error_type_strs[4];
+extern const char *const cper_proc_error_type_strs[4];
 
 u64 cper_next_record_id(void);
 const char *cper_severity_str(unsigned int);
index 732745f..3813fe4 100644 (file)
@@ -57,6 +57,8 @@ extern ssize_t cpu_show_spec_store_bypass(struct device *dev,
                                          struct device_attribute *attr, char *buf);
 extern ssize_t cpu_show_l1tf(struct device *dev,
                             struct device_attribute *attr, char *buf);
+extern ssize_t cpu_show_mds(struct device *dev,
+                           struct device_attribute *attr, char *buf);
 
 extern __printf(4, 5)
 struct device *cpu_device_create(struct device *parent, void *drvdata,
index 684caf0..d01a74f 100644 (file)
@@ -42,13 +42,6 @@ enum cpufreq_table_sorting {
        CPUFREQ_TABLE_SORTED_DESCENDING
 };
 
-struct cpufreq_freqs {
-       unsigned int cpu;       /* cpu nr */
-       unsigned int old;
-       unsigned int new;
-       u8 flags;               /* flags of cpufreq_driver, see below. */
-};
-
 struct cpufreq_cpuinfo {
        unsigned int            max_freq;
        unsigned int            min_freq;
@@ -156,6 +149,13 @@ struct cpufreq_policy {
        struct thermal_cooling_device *cdev;
 };
 
+struct cpufreq_freqs {
+       struct cpufreq_policy *policy;
+       unsigned int old;
+       unsigned int new;
+       u8 flags;               /* flags of cpufreq_driver, see below. */
+};
+
 /* Only for ACPI */
 #define CPUFREQ_SHARED_TYPE_NONE (0) /* None */
 #define CPUFREQ_SHARED_TYPE_HW  (1) /* HW does needed coordination */
index 147bdec..2175547 100644 (file)
@@ -633,8 +633,7 @@ static inline int cpumask_parselist_user(const char __user *buf, int len,
  */
 static inline int cpumask_parse(const char *buf, struct cpumask *dstp)
 {
-       char *nl = strchr(buf, '\n');
-       unsigned int len = nl ? (unsigned int)(nl - buf) : strlen(buf);
+       unsigned int len = strchrnul(buf, '\n') - buf;
 
        return bitmap_parse(buf, len, cpumask_bits(dstp), nr_cpumask_bits);
 }
index b067275..e1f51d6 100644 (file)
@@ -62,7 +62,8 @@ typedef int (*dm_clone_and_map_request_fn) (struct dm_target *ti,
                                            struct request *rq,
                                            union map_info *map_context,
                                            struct request **clone);
-typedef void (*dm_release_clone_request_fn) (struct request *clone);
+typedef void (*dm_release_clone_request_fn) (struct request *clone,
+                                            union map_info *map_context);
 
 /*
  * Returns:
index 34a744a..f2b3ae2 100644 (file)
@@ -27,6 +27,7 @@
 #include <uapi/linux/dns_resolver.h>
 
 extern int dns_query(const char *type, const char *name, size_t namelen,
-                    const char *options, char **_result, time64_t *_expiry);
+                    const char *options, char **_result, time64_t *_expiry,
+                    bool invalidate);
 
 #endif /* _LINUX_DNS_RESOLVER_H */
index f574042..6555990 100644 (file)
@@ -164,6 +164,10 @@ struct f2fs_checkpoint {
        unsigned char sit_nat_version_bitmap[1];
 } __packed;
 
+#define CP_CHKSUM_OFFSET       4092    /* default chksum offset in checkpoint */
+#define CP_MIN_CHKSUM_OFFSET                                           \
+       (offsetof(struct f2fs_checkpoint, sit_nat_version_bitmap))
+
 /*
  * For orphan inode management
  */
@@ -198,11 +202,12 @@ struct f2fs_extent {
                                        get_extra_isize(inode))
 #define DEF_NIDS_PER_INODE     5       /* Node IDs in an Inode */
 #define ADDRS_PER_INODE(inode) addrs_per_inode(inode)
-#define ADDRS_PER_BLOCK                1018    /* Address Pointers in a Direct Block */
+#define DEF_ADDRS_PER_BLOCK    1018    /* Address Pointers in a Direct Block */
+#define ADDRS_PER_BLOCK(inode) addrs_per_block(inode)
 #define NIDS_PER_BLOCK         1018    /* Node IDs in an Indirect Block */
 
 #define ADDRS_PER_PAGE(page, inode)    \
-       (IS_INODE(page) ? ADDRS_PER_INODE(inode) : ADDRS_PER_BLOCK)
+       (IS_INODE(page) ? ADDRS_PER_INODE(inode) : ADDRS_PER_BLOCK(inode))
 
 #define        NODE_DIR1_BLOCK         (DEF_ADDRS_PER_INODE + 1)
 #define        NODE_DIR2_BLOCK         (DEF_ADDRS_PER_INODE + 2)
@@ -267,7 +272,7 @@ struct f2fs_inode {
 } __packed;
 
 struct direct_node {
-       __le32 addr[ADDRS_PER_BLOCK];   /* array of data block address */
+       __le32 addr[DEF_ADDRS_PER_BLOCK];       /* array of data block address */
 } __packed;
 
 struct indirect_node {
index ebc5509..17ba4e4 100644 (file)
@@ -15,4 +15,9 @@
 
 #include <linux/firmware/imx/svc/misc.h>
 #include <linux/firmware/imx/svc/pm.h>
+
+int imx_scu_enable_general_irq_channel(struct device *dev);
+int imx_scu_irq_register_notifier(struct notifier_block *nb);
+int imx_scu_irq_unregister_notifier(struct notifier_block *nb);
+int imx_scu_irq_group_enable(u8 group, u32 mask, u8 enable);
 #endif /* _SC_SCI_H */
diff --git a/include/linux/firmware/trusted_foundations.h b/include/linux/firmware/trusted_foundations.h
new file mode 100644 (file)
index 0000000..4064e7c
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013, NVIDIA 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.
+ */
+
+/*
+ * Support for the Trusted Foundations secure monitor.
+ *
+ * Trusted Foundation comes active on some ARM consumer devices (most
+ * Tegra-based devices sold on the market are concerned). Such devices can only
+ * perform some basic operations, like setting the CPU reset vector, through
+ * SMC calls to the secure monitor. The calls are completely specific to
+ * Trusted Foundations, and do *not* follow the SMC calling convention or the
+ * PSCI standard.
+ */
+
+#ifndef __FIRMWARE_TRUSTED_FOUNDATIONS_H
+#define __FIRMWARE_TRUSTED_FOUNDATIONS_H
+
+#include <linux/printk.h>
+#include <linux/bug.h>
+#include <linux/of.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#include <linux/types.h>
+
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/outercache.h>
+
+#define TF_PM_MODE_LP0                 0
+#define TF_PM_MODE_LP1                 1
+#define TF_PM_MODE_LP1_NO_MC_CLK       2
+#define TF_PM_MODE_LP2                 3
+#define TF_PM_MODE_LP2_NOFLUSH_L2      4
+
+struct trusted_foundations_platform_data {
+       unsigned int version_major;
+       unsigned int version_minor;
+};
+
+#if IS_ENABLED(CONFIG_TRUSTED_FOUNDATIONS)
+
+void register_trusted_foundations(struct trusted_foundations_platform_data *pd);
+void of_register_trusted_foundations(void);
+bool trusted_foundations_registered(void);
+
+#else /* CONFIG_TRUSTED_FOUNDATIONS */
+static inline void tf_dummy_write_sec(unsigned long val, unsigned int reg)
+{
+}
+
+static inline void register_trusted_foundations(
+                                  struct trusted_foundations_platform_data *pd)
+{
+       /*
+        * If the system requires TF and we cannot provide it, continue booting
+        * but disable features that cannot be provided.
+        */
+       pr_err("No support for Trusted Foundations, continuing in degraded mode.\n");
+       pr_err("Secondary processors as well as CPU PM will be disabled.\n");
+#if IS_ENABLED(CONFIG_CACHE_L2X0)
+       pr_err("L2X0 cache will be kept disabled.\n");
+       outer_cache.write_sec = tf_dummy_write_sec;
+#endif
+#if IS_ENABLED(CONFIG_SMP)
+       setup_max_cpus = 0;
+#endif
+       cpu_idle_poll_ctrl(true);
+}
+
+static inline void of_register_trusted_foundations(void)
+{
+       /*
+        * If we find the target should enable TF but does not support it,
+        * fail as the system won't be able to do much anyway
+        */
+       if (of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations"))
+               register_trusted_foundations(NULL);
+}
+
+static inline bool trusted_foundations_registered(void)
+{
+       return false;
+}
+#endif /* CONFIG_TRUSTED_FOUNDATIONS */
+
+#endif
index 642dab1..1262ea6 100644 (file)
 #define        ZYNQMP_PM_CAPABILITY_WAKEUP     0x4U
 #define        ZYNQMP_PM_CAPABILITY_POWER      0x8U
 
+/*
+ * Firmware FPGA Manager flags
+ * XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration
+ * XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
+ */
+#define XILINX_ZYNQMP_PM_FPGA_FULL     0x0U
+#define XILINX_ZYNQMP_PM_FPGA_PARTIAL  BIT(0)
+
 enum pm_api_id {
        PM_GET_API_VERSION = 1,
        PM_REQUEST_NODE = 13,
@@ -56,6 +64,8 @@ enum pm_api_id {
        PM_RESET_ASSERT = 17,
        PM_RESET_GET_STATUS,
        PM_PM_INIT_FINALIZE = 21,
+       PM_FPGA_LOAD,
+       PM_FPGA_GET_STATUS,
        PM_GET_CHIPID = 24,
        PM_IOCTL = 34,
        PM_QUERY_DATA,
@@ -258,6 +268,8 @@ struct zynqmp_pm_query_data {
 struct zynqmp_eemi_ops {
        int (*get_api_version)(u32 *version);
        int (*get_chipid)(u32 *idcode, u32 *version);
+       int (*fpga_load)(const u64 address, const u32 size, const u32 flags);
+       int (*fpga_get_status)(u32 *value);
        int (*query_data)(struct zynqmp_pm_query_data qdata, u32 *out);
        int (*clock_enable)(u32 clock_id);
        int (*clock_disable)(u32 clock_id);
@@ -293,7 +305,7 @@ const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void);
 #else
 static inline struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void)
 {
-       return NULL;
+       return ERR_PTR(-ENODEV);
 }
 #endif
 
index 0c0ef30..94972e8 100644 (file)
@@ -151,39 +151,6 @@ static inline void fsnotify_vfsmount_delete(struct vfsmount *mnt)
        __fsnotify_vfsmount_delete(mnt);
 }
 
-/*
- * fsnotify_nameremove - a filename was removed from a directory
- *
- * This is mostly called under parent vfs inode lock so name and
- * dentry->d_parent should be stable. However there are some corner cases where
- * inode lock is not held. So to be on the safe side and be reselient to future
- * callers and out of tree users of d_delete(), we do not assume that d_parent
- * and d_name are stable and we use dget_parent() and
- * take_dentry_name_snapshot() to grab stable references.
- */
-static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
-{
-       struct dentry *parent;
-       struct name_snapshot name;
-       __u32 mask = FS_DELETE;
-
-       /* d_delete() of pseudo inode? (e.g. __ns_get_path() playing tricks) */
-       if (IS_ROOT(dentry))
-               return;
-
-       if (isdir)
-               mask |= FS_ISDIR;
-
-       parent = dget_parent(dentry);
-       take_dentry_name_snapshot(&name, dentry);
-
-       fsnotify(d_inode(parent), mask, d_inode(dentry), FSNOTIFY_EVENT_INODE,
-                &name.name, 0);
-
-       release_dentry_name_snapshot(&name);
-       dput(parent);
-}
-
 /*
  * fsnotify_inoderemove - an inode is going away
  */
index c28f6ed..a9f9dcc 100644 (file)
@@ -355,6 +355,7 @@ extern int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u
 extern void __fsnotify_inode_delete(struct inode *inode);
 extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
 extern void fsnotify_sb_delete(struct super_block *sb);
+extern void fsnotify_nameremove(struct dentry *dentry, int isdir);
 extern u32 fsnotify_get_cookie(void);
 
 static inline int fsnotify_inode_watches_children(struct inode *inode)
@@ -524,6 +525,9 @@ static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
 static inline void fsnotify_sb_delete(struct super_block *sb)
 {}
 
+static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
+{}
+
 static inline void fsnotify_update_flags(struct dentry *dentry)
 {}
 
index 2089991..25e2995 100644 (file)
@@ -741,6 +741,8 @@ struct ftrace_graph_ret {
 typedef void (*trace_func_graph_ret_t)(struct ftrace_graph_ret *); /* return */
 typedef int (*trace_func_graph_ent_t)(struct ftrace_graph_ent *); /* entry */
 
+extern int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace);
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 
 struct fgraph_ops {
index fdab7de..fb07b50 100644 (file)
@@ -585,12 +585,12 @@ static inline bool pm_suspended_storage(void)
 }
 #endif /* CONFIG_PM_SLEEP */
 
-#if (defined(CONFIG_MEMORY_ISOLATION) && defined(CONFIG_COMPACTION)) || defined(CONFIG_CMA)
+#ifdef CONFIG_CONTIG_ALLOC
 /* The below functions must be run on a range from a single zone. */
 extern int alloc_contig_range(unsigned long start, unsigned long end,
                              unsigned migratetype, gfp_t gfp_mask);
-extern void free_contig_range(unsigned long pfn, unsigned nr_pages);
 #endif
+void free_contig_range(unsigned long pfn, unsigned int nr_pages);
 
 #ifdef CONFIG_CMA
 /* CMA stuff */
index ad50b7b..51ec27a 100644 (file)
 #include <linux/migrate.h>
 #include <linux/memremap.h>
 #include <linux/completion.h>
+#include <linux/mmu_notifier.h>
 
-struct hmm;
+
+/*
+ * struct hmm - HMM per mm struct
+ *
+ * @mm: mm struct this HMM struct is bound to
+ * @lock: lock protecting ranges list
+ * @ranges: list of range being snapshotted
+ * @mirrors: list of mirrors for this mm
+ * @mmu_notifier: mmu notifier to track updates to CPU page table
+ * @mirrors_sem: read/write semaphore protecting the mirrors list
+ * @wq: wait queue for user waiting on a range invalidation
+ * @notifiers: count of active mmu notifiers
+ * @dead: is the mm dead ?
+ */
+struct hmm {
+       struct mm_struct        *mm;
+       struct kref             kref;
+       struct mutex            lock;
+       struct list_head        ranges;
+       struct list_head        mirrors;
+       struct mmu_notifier     mmu_notifier;
+       struct rw_semaphore     mirrors_sem;
+       wait_queue_head_t       wq;
+       long                    notifiers;
+       bool                    dead;
+};
 
 /*
  * hmm_pfn_flag_e - HMM flag enums
@@ -131,6 +157,7 @@ enum hmm_pfn_value_e {
 /*
  * struct hmm_range - track invalidation lock on virtual address range
  *
+ * @hmm: the core HMM structure this range is active against
  * @vma: the vm area struct for the range
  * @list: all range lock are on a list
  * @start: range virtual start address (inclusive)
@@ -138,10 +165,13 @@ enum hmm_pfn_value_e {
  * @pfns: array of pfns (big enough for the range)
  * @flags: pfn flags to match device driver page table
  * @values: pfn value for some special case (none, special, error, ...)
+ * @default_flags: default flags for the range (write, read, ... see hmm doc)
+ * @pfn_flags_mask: allows to mask pfn flags so that only default_flags matter
  * @pfn_shifts: pfn shift value (should be <= PAGE_SHIFT)
  * @valid: pfns array did not change since it has been fill by an HMM function
  */
 struct hmm_range {
+       struct hmm              *hmm;
        struct vm_area_struct   *vma;
        struct list_head        list;
        unsigned long           start;
@@ -149,41 +179,96 @@ struct hmm_range {
        uint64_t                *pfns;
        const uint64_t          *flags;
        const uint64_t          *values;
+       uint64_t                default_flags;
+       uint64_t                pfn_flags_mask;
+       uint8_t                 page_shift;
        uint8_t                 pfn_shift;
        bool                    valid;
 };
 
 /*
- * hmm_pfn_to_page() - return struct page pointed to by a valid HMM pfn
- * @range: range use to decode HMM pfn value
- * @pfn: HMM pfn value to get corresponding struct page from
- * Returns: struct page pointer if pfn is a valid HMM pfn, NULL otherwise
+ * hmm_range_page_shift() - return the page shift for the range
+ * @range: range being queried
+ * Returns: page shift (page size = 1 << page shift) for the range
+ */
+static inline unsigned hmm_range_page_shift(const struct hmm_range *range)
+{
+       return range->page_shift;
+}
+
+/*
+ * hmm_range_page_size() - return the page size for the range
+ * @range: range being queried
+ * Returns: page size for the range in bytes
+ */
+static inline unsigned long hmm_range_page_size(const struct hmm_range *range)
+{
+       return 1UL << hmm_range_page_shift(range);
+}
+
+/*
+ * hmm_range_wait_until_valid() - wait for range to be valid
+ * @range: range affected by invalidation to wait on
+ * @timeout: time out for wait in ms (ie abort wait after that period of time)
+ * Returns: true if the range is valid, false otherwise.
+ */
+static inline bool hmm_range_wait_until_valid(struct hmm_range *range,
+                                             unsigned long timeout)
+{
+       /* Check if mm is dead ? */
+       if (range->hmm == NULL || range->hmm->dead || range->hmm->mm == NULL) {
+               range->valid = false;
+               return false;
+       }
+       if (range->valid)
+               return true;
+       wait_event_timeout(range->hmm->wq, range->valid || range->hmm->dead,
+                          msecs_to_jiffies(timeout));
+       /* Return current valid status just in case we get lucky */
+       return range->valid;
+}
+
+/*
+ * hmm_range_valid() - test if a range is valid or not
+ * @range: range
+ * Returns: true if the range is valid, false otherwise.
+ */
+static inline bool hmm_range_valid(struct hmm_range *range)
+{
+       return range->valid;
+}
+
+/*
+ * hmm_device_entry_to_page() - return struct page pointed to by a device entry
+ * @range: range use to decode device entry value
+ * @entry: device entry value to get corresponding struct page from
+ * Returns: struct page pointer if entry is a valid, NULL otherwise
  *
- * If the HMM pfn is valid (ie valid flag set) then return the struct page
- * matching the pfn value stored in the HMM pfn. Otherwise return NULL.
+ * If the device entry is valid (ie valid flag set) then return the struct page
+ * matching the entry value. Otherwise return NULL.
  */
-static inline struct page *hmm_pfn_to_page(const struct hmm_range *range,
-                                          uint64_t pfn)
+static inline struct page *hmm_device_entry_to_page(const struct hmm_range *range,
+                                                   uint64_t entry)
 {
-       if (pfn == range->values[HMM_PFN_NONE])
+       if (entry == range->values[HMM_PFN_NONE])
                return NULL;
-       if (pfn == range->values[HMM_PFN_ERROR])
+       if (entry == range->values[HMM_PFN_ERROR])
                return NULL;
-       if (pfn == range->values[HMM_PFN_SPECIAL])
+       if (entry == range->values[HMM_PFN_SPECIAL])
                return NULL;
-       if (!(pfn & range->flags[HMM_PFN_VALID]))
+       if (!(entry & range->flags[HMM_PFN_VALID]))
                return NULL;
-       return pfn_to_page(pfn >> range->pfn_shift);
+       return pfn_to_page(entry >> range->pfn_shift);
 }
 
 /*
- * hmm_pfn_to_pfn() - return pfn value store in a HMM pfn
- * @range: range use to decode HMM pfn value
- * @pfn: HMM pfn value to extract pfn from
- * Returns: pfn value if HMM pfn is valid, -1UL otherwise
+ * hmm_device_entry_to_pfn() - return pfn value store in a device entry
+ * @range: range use to decode device entry value
+ * @entry: device entry to extract pfn from
+ * Returns: pfn value if device entry is valid, -1UL otherwise
  */
-static inline unsigned long hmm_pfn_to_pfn(const struct hmm_range *range,
-                                          uint64_t pfn)
+static inline unsigned long
+hmm_device_entry_to_pfn(const struct hmm_range *range, uint64_t pfn)
 {
        if (pfn == range->values[HMM_PFN_NONE])
                return -1UL;
@@ -197,31 +282,66 @@ static inline unsigned long hmm_pfn_to_pfn(const struct hmm_range *range,
 }
 
 /*
- * hmm_pfn_from_page() - create a valid HMM pfn value from struct page
+ * hmm_device_entry_from_page() - create a valid device entry for a page
  * @range: range use to encode HMM pfn value
- * @page: struct page pointer for which to create the HMM pfn
- * Returns: valid HMM pfn for the page
+ * @page: page for which to create the device entry
+ * Returns: valid device entry for the page
  */
-static inline uint64_t hmm_pfn_from_page(const struct hmm_range *range,
-                                        struct page *page)
+static inline uint64_t hmm_device_entry_from_page(const struct hmm_range *range,
+                                                 struct page *page)
 {
        return (page_to_pfn(page) << range->pfn_shift) |
                range->flags[HMM_PFN_VALID];
 }
 
 /*
- * hmm_pfn_from_pfn() - create a valid HMM pfn value from pfn
+ * hmm_device_entry_from_pfn() - create a valid device entry value from pfn
  * @range: range use to encode HMM pfn value
- * @pfn: pfn value for which to create the HMM pfn
- * Returns: valid HMM pfn for the pfn
+ * @pfn: pfn value for which to create the device entry
+ * Returns: valid device entry for the pfn
  */
-static inline uint64_t hmm_pfn_from_pfn(const struct hmm_range *range,
-                                       unsigned long pfn)
+static inline uint64_t hmm_device_entry_from_pfn(const struct hmm_range *range,
+                                                unsigned long pfn)
 {
        return (pfn << range->pfn_shift) |
                range->flags[HMM_PFN_VALID];
 }
 
+/*
+ * Old API:
+ * hmm_pfn_to_page()
+ * hmm_pfn_to_pfn()
+ * hmm_pfn_from_page()
+ * hmm_pfn_from_pfn()
+ *
+ * This are the OLD API please use new API, it is here to avoid cross-tree
+ * merge painfullness ie we convert things to new API in stages.
+ */
+static inline struct page *hmm_pfn_to_page(const struct hmm_range *range,
+                                          uint64_t pfn)
+{
+       return hmm_device_entry_to_page(range, pfn);
+}
+
+static inline unsigned long hmm_pfn_to_pfn(const struct hmm_range *range,
+                                          uint64_t pfn)
+{
+       return hmm_device_entry_to_pfn(range, pfn);
+}
+
+static inline uint64_t hmm_pfn_from_page(const struct hmm_range *range,
+                                        struct page *page)
+{
+       return hmm_device_entry_from_page(range, page);
+}
+
+static inline uint64_t hmm_pfn_from_pfn(const struct hmm_range *range,
+                                       unsigned long pfn)
+{
+       return hmm_device_entry_from_pfn(range, pfn);
+}
+
+
 
 #if IS_ENABLED(CONFIG_HMM_MIRROR)
 /*
@@ -353,43 +473,113 @@ struct hmm_mirror {
 int hmm_mirror_register(struct hmm_mirror *mirror, struct mm_struct *mm);
 void hmm_mirror_unregister(struct hmm_mirror *mirror);
 
-
 /*
- * To snapshot the CPU page table, call hmm_vma_get_pfns(), then take a device
- * driver lock that serializes device page table updates, then call
- * hmm_vma_range_done(), to check if the snapshot is still valid. The same
- * device driver page table update lock must also be used in the
- * hmm_mirror_ops.sync_cpu_device_pagetables() callback, so that CPU page
- * table invalidation serializes on it.
- *
- * YOU MUST CALL hmm_vma_range_done() ONCE AND ONLY ONCE EACH TIME YOU CALL
- * hmm_vma_get_pfns() WITHOUT ERROR !
- *
- * IF YOU DO NOT FOLLOW THE ABOVE RULE THE SNAPSHOT CONTENT MIGHT BE INVALID !
+ * hmm_mirror_mm_is_alive() - test if mm is still alive
+ * @mirror: the HMM mm mirror for which we want to lock the mmap_sem
+ * Returns: false if the mm is dead, true otherwise
+ *
+ * This is an optimization it will not accurately always return -EINVAL if the
+ * mm is dead ie there can be false negative (process is being kill but HMM is
+ * not yet inform of that). It is only intented to be use to optimize out case
+ * where driver is about to do something time consuming and it would be better
+ * to skip it if the mm is dead.
  */
-int hmm_vma_get_pfns(struct hmm_range *range);
-bool hmm_vma_range_done(struct hmm_range *range);
+static inline bool hmm_mirror_mm_is_alive(struct hmm_mirror *mirror)
+{
+       struct mm_struct *mm;
+
+       if (!mirror || !mirror->hmm)
+               return false;
+       mm = READ_ONCE(mirror->hmm->mm);
+       if (mirror->hmm->dead || !mm)
+               return false;
+
+       return true;
+}
 
 
 /*
- * Fault memory on behalf of device driver. Unlike handle_mm_fault(), this will
- * not migrate any device memory back to system memory. The HMM pfn array will
- * be updated with the fault result and current snapshot of the CPU page table
- * for the range.
- *
- * The mmap_sem must be taken in read mode before entering and it might be
- * dropped by the function if the block argument is false. In that case, the
- * function returns -EAGAIN.
- *
- * Return value does not reflect if the fault was successful for every single
- * address or not. Therefore, the caller must to inspect the HMM pfn array to
- * determine fault status for each address.
- *
- * Trying to fault inside an invalid vma will result in -EINVAL.
+ * Please see Documentation/vm/hmm.rst for how to use the range API.
+ */
+int hmm_range_register(struct hmm_range *range,
+                      struct mm_struct *mm,
+                      unsigned long start,
+                      unsigned long end,
+                      unsigned page_shift);
+void hmm_range_unregister(struct hmm_range *range);
+long hmm_range_snapshot(struct hmm_range *range);
+long hmm_range_fault(struct hmm_range *range, bool block);
+long hmm_range_dma_map(struct hmm_range *range,
+                      struct device *device,
+                      dma_addr_t *daddrs,
+                      bool block);
+long hmm_range_dma_unmap(struct hmm_range *range,
+                        struct vm_area_struct *vma,
+                        struct device *device,
+                        dma_addr_t *daddrs,
+                        bool dirty);
+
+/*
+ * HMM_RANGE_DEFAULT_TIMEOUT - default timeout (ms) when waiting for a range
  *
- * See the function description in mm/hmm.c for further documentation.
+ * When waiting for mmu notifiers we need some kind of time out otherwise we
+ * could potentialy wait for ever, 1000ms ie 1s sounds like a long time to
+ * wait already.
  */
-int hmm_vma_fault(struct hmm_range *range, bool block);
+#define HMM_RANGE_DEFAULT_TIMEOUT 1000
+
+/* This is a temporary helper to avoid merge conflict between trees. */
+static inline bool hmm_vma_range_done(struct hmm_range *range)
+{
+       bool ret = hmm_range_valid(range);
+
+       hmm_range_unregister(range);
+       return ret;
+}
+
+/* This is a temporary helper to avoid merge conflict between trees. */
+static inline int hmm_vma_fault(struct hmm_range *range, bool block)
+{
+       long ret;
+
+       /*
+        * With the old API the driver must set each individual entries with
+        * the requested flags (valid, write, ...). So here we set the mask to
+        * keep intact the entries provided by the driver and zero out the
+        * default_flags.
+        */
+       range->default_flags = 0;
+       range->pfn_flags_mask = -1UL;
+
+       ret = hmm_range_register(range, range->vma->vm_mm,
+                                range->start, range->end,
+                                PAGE_SHIFT);
+       if (ret)
+               return (int)ret;
+
+       if (!hmm_range_wait_until_valid(range, HMM_RANGE_DEFAULT_TIMEOUT)) {
+               /*
+                * The mmap_sem was taken by driver we release it here and
+                * returns -EAGAIN which correspond to mmap_sem have been
+                * drop in the old API.
+                */
+               up_read(&range->vma->vm_mm->mmap_sem);
+               return -EAGAIN;
+       }
+
+       ret = hmm_range_fault(range, block);
+       if (ret <= 0) {
+               if (ret == -EBUSY || !ret) {
+                       /* Same as above  drop mmap_sem to match old API. */
+                       up_read(&range->vma->vm_mm->mmap_sem);
+                       ret = -EBUSY;
+               } else if (ret == -EAGAIN)
+                       ret = -EBUSY;
+               hmm_range_unregister(range);
+               return ret;
+       }
+       return 0;
+}
 
 /* Below are for HMM internal use only! Not to be used by device driver! */
 void hmm_mm_destroy(struct mm_struct *mm);
index 381e872..7cd5c15 100644 (file)
@@ -47,10 +47,8 @@ extern bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,
 extern int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                        unsigned long addr, pgprot_t newprot,
                        int prot_numa);
-vm_fault_t vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
-                       pmd_t *pmd, pfn_t pfn, bool write);
-vm_fault_t vmf_insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,
-                       pud_t *pud, pfn_t pfn, bool write);
+vm_fault_t vmf_insert_pfn_pmd(struct vm_fault *vmf, pfn_t pfn, bool write);
+vm_fault_t vmf_insert_pfn_pud(struct vm_fault *vmf, pfn_t pfn, bool write);
 enum transparent_hugepage_flag {
        TRANSPARENT_HUGEPAGE_FLAG,
        TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG,
index 11943b6..edf476c 100644 (file)
@@ -123,9 +123,7 @@ void move_hugetlb_state(struct page *oldpage, struct page *newpage, int reason);
 void free_huge_page(struct page *page);
 void hugetlb_fix_reserve_counts(struct inode *inode);
 extern struct mutex *hugetlb_fault_mutex_table;
-u32 hugetlb_fault_mutex_hash(struct hstate *h, struct mm_struct *mm,
-                               struct vm_area_struct *vma,
-                               struct address_space *mapping,
+u32 hugetlb_fault_mutex_hash(struct hstate *h, struct address_space *mapping,
                                pgoff_t idx, unsigned long address);
 
 pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud);
index 9887f4f..b2d3483 100644 (file)
@@ -290,6 +290,20 @@ int iio_read_max_channel_raw(struct iio_channel *chan, int *val);
 int iio_read_avail_channel_raw(struct iio_channel *chan,
                               const int **vals, int *length);
 
+/**
+ * iio_read_avail_channel_attribute() - read available channel attribute values
+ * @chan:              The channel being queried.
+ * @vals:              Available values read back.
+ * @type:              Type of values read back.
+ * @length:            Number of entries in vals.
+ * @attribute:         info attribute to be read back.
+ *
+ * Returns an error code, IIO_AVAIL_RANGE or IIO_AVAIL_LIST.
+ */
+int iio_read_avail_channel_attribute(struct iio_channel *chan,
+                                    const int **vals, int *type, int *length,
+                                    enum iio_chan_info_enum attribute);
+
 /**
  * iio_get_channel_type() - get the type of a channel
  * @channel:           The channel being queried.
index 6ab8c1b..c309f43 100644 (file)
@@ -19,6 +19,7 @@ struct ipc_ids {
        struct rw_semaphore rwsem;
        struct idr ipcs_idr;
        int max_idx;
+       int last_idx;   /* For wrap around detection */
 #ifdef CONFIG_CHECKPOINT_RESTORE
        int next_id;
 #endif
diff --git a/include/linux/irqchip/irq-ixp4xx.h b/include/linux/irqchip/irq-ixp4xx.h
new file mode 100644 (file)
index 0000000..9395917
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __IRQ_IXP4XX_H
+#define __IRQ_IXP4XX_H
+
+#include <linux/ioport.h>
+struct irq_domain;
+
+void ixp4xx_irq_init(resource_size_t irqbase,
+                    bool is_356);
+struct irq_domain *ixp4xx_get_irq_domain(void);
+
+#endif /* __IRQ_IXP4XX_H */
index a3b59d1..74b1ee9 100644 (file)
@@ -484,6 +484,7 @@ extern int __kernel_text_address(unsigned long addr);
 extern int kernel_text_address(unsigned long addr);
 extern int func_ptr_is_kernel_text(void *ptr);
 
+u64 int_pow(u64 base, unsigned int exp);
 unsigned long int_sqrt(unsigned long);
 
 #if BITS_PER_LONG < 64
index 2c89e60..0f9da96 100644 (file)
@@ -4,7 +4,6 @@
 /* Simple interface for creating and stopping kernel threads without mess. */
 #include <linux/err.h>
 #include <linux/sched.h>
-#include <linux/cgroup.h>
 
 __printf(4, 5)
 struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
@@ -198,6 +197,8 @@ bool kthread_cancel_delayed_work_sync(struct kthread_delayed_work *work);
 
 void kthread_destroy_worker(struct kthread_worker *worker);
 
+struct cgroup_subsys_state;
+
 #ifdef CONFIG_BLK_CGROUP
 void kthread_associate_blkcg(struct cgroup_subsys_state *css);
 struct cgroup_subsys_state *kthread_blkcg(void);
index 7c560e0..9022f0c 100644 (file)
@@ -36,7 +36,7 @@ account_scheduler_latency(struct task_struct *task, int usecs, int inter)
                __account_scheduler_latency(task, usecs, inter);
 }
 
-void clear_all_latency_tracing(struct task_struct *p);
+void clear_tsk_latency_tracing(struct task_struct *p);
 
 extern int sysctl_latencytop(struct ctl_table *table, int write,
                        void __user *buffer, size_t *lenp, loff_t *ppos);
@@ -48,7 +48,7 @@ account_scheduler_latency(struct task_struct *task, int usecs, int inter)
 {
 }
 
-static inline void clear_all_latency_tracing(struct task_struct *p)
+static inline void clear_tsk_latency_tracing(struct task_struct *p)
 {
 }
 
index 5d865a5..4d0d565 100644 (file)
@@ -358,6 +358,7 @@ struct nvm_geo {
        u16     csecs;          /* sector size */
        u16     sos;            /* out-of-band area size */
        bool    ext;            /* metadata in extended data buffer */
+       u32     mdts;           /* Max data transfer size*/
 
        /* device write constrains */
        u32     ws_min;         /* minimum write size */
@@ -427,6 +428,7 @@ struct nvm_dev {
        char name[DISK_NAME_LEN];
        void *private_data;
 
+       struct kref ref;
        void *rmap;
 
        struct mutex mlock;
index 58aa3ad..e951228 100644 (file)
@@ -150,6 +150,23 @@ static inline void list_replace_init(struct list_head *old,
        INIT_LIST_HEAD(old);
 }
 
+/**
+ * list_swap - replace entry1 with entry2 and re-add entry1 at entry2's position
+ * @entry1: the location to place entry2
+ * @entry2: the location to place entry1
+ */
+static inline void list_swap(struct list_head *entry1,
+                            struct list_head *entry2)
+{
+       struct list_head *pos = entry2->prev;
+
+       list_del(entry2);
+       list_replace(entry1, entry2);
+       if (pos == entry1)
+               pos = entry2;
+       list_add(entry1, pos);
+}
+
 /**
  * list_del_init - deletes entry from list and reinitialize it.
  * @entry: the element to delete from the list.
@@ -270,6 +287,24 @@ static inline void list_rotate_left(struct list_head *head)
        }
 }
 
+/**
+ * list_rotate_to_front() - Rotate list to specific item.
+ * @list: The desired new front of the list.
+ * @head: The head of the list.
+ *
+ * Rotates list so that @list becomes the new front of the list.
+ */
+static inline void list_rotate_to_front(struct list_head *list,
+                                       struct list_head *head)
+{
+       /*
+        * Deletes the list head from the list denoted by @head and
+        * places it as the tail of @list, this effectively rotates the
+        * list so that @list is at the front.
+        */
+       list_move_tail(head, list);
+}
+
 /**
  * list_is_singular - tests whether a list has just one entry.
  * @head: the list to test.
@@ -754,7 +789,7 @@ static inline void hlist_add_behind(struct hlist_node *n,
                                    struct hlist_node *prev)
 {
        n->next = prev->next;
-       WRITE_ONCE(prev->next, n);
+       prev->next = n;
        n->pprev = &prev->next;
 
        if (n->next)
index 3fc2cc5..ae1b541 100644 (file)
@@ -86,6 +86,32 @@ static inline void hlist_bl_add_head(struct hlist_bl_node *n,
        hlist_bl_set_first(h, n);
 }
 
+static inline void hlist_bl_add_before(struct hlist_bl_node *n,
+                                      struct hlist_bl_node *next)
+{
+       struct hlist_bl_node **pprev = next->pprev;
+
+       n->pprev = pprev;
+       n->next = next;
+       next->pprev = &n->next;
+
+       /* pprev may be `first`, so be careful not to lose the lock bit */
+       WRITE_ONCE(*pprev,
+                  (struct hlist_bl_node *)
+                       ((uintptr_t)n | ((uintptr_t)*pprev & LIST_BL_LOCKMASK)));
+}
+
+static inline void hlist_bl_add_behind(struct hlist_bl_node *n,
+                                      struct hlist_bl_node *prev)
+{
+       n->next = prev->next;
+       n->pprev = &prev->next;
+       prev->next = n;
+
+       if (n->next)
+               n->next->pprev = &n->next;
+}
+
 static inline void __hlist_bl_del(struct hlist_bl_node *n)
 {
        struct hlist_bl_node *next = n->next;
index ba79956..20f178c 100644 (file)
@@ -6,6 +6,7 @@
 
 struct list_head;
 
+__attribute__((nonnull(2,3)))
 void list_sort(void *priv, struct list_head *head,
               int (*cmp)(void *priv, struct list_head *a,
                          struct list_head *b));
index 8c0cf10..0520c0c 100644 (file)
@@ -76,7 +76,7 @@ struct nlmclnt_operations {
 };
 
 extern int     nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl, void *data);
-extern int     lockd_up(struct net *net);
+extern int     lockd_up(struct net *net, const struct cred *cred);
 extern void    lockd_down(struct net *net);
 
 #endif /* LINUX_LOCKD_BIND_H */
index 294d5d8..676d390 100644 (file)
@@ -96,13 +96,14 @@ struct memblock {
 extern struct memblock memblock;
 extern int memblock_debug;
 
-#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
+#ifndef CONFIG_ARCH_KEEP_MEMBLOCK
 #define __init_memblock __meminit
 #define __initdata_memblock __meminitdata
 void memblock_discard(void);
 #else
 #define __init_memblock
 #define __initdata_memblock
+static inline void memblock_discard(void) {}
 #endif
 
 #define memblock_dbg(fmt, ...) \
@@ -240,6 +241,47 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
             i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid))
 #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
 
+#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
+void __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone,
+                                 unsigned long *out_spfn,
+                                 unsigned long *out_epfn);
+/**
+ * for_each_free_mem_range_in_zone - iterate through zone specific free
+ * memblock areas
+ * @i: u64 used as loop variable
+ * @zone: zone in which all of the memory blocks reside
+ * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
+ * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
+ *
+ * Walks over free (memory && !reserved) areas of memblock in a specific
+ * zone. Available once memblock and an empty zone is initialized. The main
+ * assumption is that the zone start, end, and pgdat have been associated.
+ * This way we can use the zone to determine NUMA node, and if a given part
+ * of the memblock is valid for the zone.
+ */
+#define for_each_free_mem_pfn_range_in_zone(i, zone, p_start, p_end)   \
+       for (i = 0,                                                     \
+            __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end);    \
+            i != U64_MAX;                                      \
+            __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end))
+
+/**
+ * for_each_free_mem_range_in_zone_from - iterate through zone specific
+ * free memblock areas from a given point
+ * @i: u64 used as loop variable
+ * @zone: zone in which all of the memory blocks reside
+ * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
+ * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
+ *
+ * Walks over free (memory && !reserved) areas of memblock in a specific
+ * zone, continuing from current position. Available as soon as memblock is
+ * initialized.
+ */
+#define for_each_free_mem_pfn_range_in_zone_from(i, zone, p_start, p_end) \
+       for (; i != U64_MAX;                                      \
+            __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end))
+#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
+
 /**
  * for_each_free_mem_range - iterate through free memblock areas
  * @i: u64 used as loop variable
index dbb6118..bc74d6a 100644 (file)
@@ -94,8 +94,8 @@ enum mem_cgroup_events_target {
        MEM_CGROUP_NTARGETS,
 };
 
-struct mem_cgroup_stat_cpu {
-       long count[MEMCG_NR_STAT];
+struct memcg_vmstats_percpu {
+       long stat[MEMCG_NR_STAT];
        unsigned long events[NR_VM_EVENT_ITEMS];
        unsigned long nr_page_events;
        unsigned long targets[MEM_CGROUP_NTARGETS];
@@ -128,6 +128,7 @@ struct mem_cgroup_per_node {
 
        struct lruvec_stat __percpu *lruvec_stat_cpu;
        atomic_long_t           lruvec_stat[NR_VM_NODE_STAT_ITEMS];
+       atomic_long_t           lruvec_stat_local[NR_VM_NODE_STAT_ITEMS];
 
        unsigned long           lru_zone_size[MAX_NR_ZONES][NR_LRU_LISTS];
 
@@ -274,13 +275,17 @@ struct mem_cgroup {
        struct task_struct      *move_lock_task;
 
        /* memory.stat */
-       struct mem_cgroup_stat_cpu __percpu *stat_cpu;
+       struct memcg_vmstats_percpu __percpu *vmstats_percpu;
 
        MEMCG_PADDING(_pad2_);
 
-       atomic_long_t           stat[MEMCG_NR_STAT];
-       atomic_long_t           events[NR_VM_EVENT_ITEMS];
-       atomic_long_t memory_events[MEMCG_NR_MEMORY_EVENTS];
+       atomic_long_t           vmstats[MEMCG_NR_STAT];
+       atomic_long_t           vmstats_local[MEMCG_NR_STAT];
+
+       atomic_long_t           vmevents[NR_VM_EVENT_ITEMS];
+       atomic_long_t           vmevents_local[NR_VM_EVENT_ITEMS];
+
+       atomic_long_t           memory_events[MEMCG_NR_MEMORY_EVENTS];
 
        unsigned long           socket_pressure;
 
@@ -501,22 +506,6 @@ int mem_cgroup_select_victim_node(struct mem_cgroup *memcg);
 void mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru,
                int zid, int nr_pages);
 
-unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
-                                          int nid, unsigned int lru_mask);
-
-static inline
-unsigned long mem_cgroup_get_lru_size(struct lruvec *lruvec, enum lru_list lru)
-{
-       struct mem_cgroup_per_node *mz;
-       unsigned long nr_pages = 0;
-       int zid;
-
-       mz = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
-       for (zid = 0; zid < MAX_NR_ZONES; zid++)
-               nr_pages += mz->lru_zone_size[zid][lru];
-       return nr_pages;
-}
-
 static inline
 unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec,
                enum lru_list lru, int zone_idx)
@@ -570,10 +559,9 @@ void unlock_page_memcg(struct page *page);
  * idx can be of type enum memcg_stat_item or node_stat_item.
  * Keep in sync with memcg_exact_page_state().
  */
-static inline unsigned long memcg_page_state(struct mem_cgroup *memcg,
-                                            int idx)
+static inline unsigned long memcg_page_state(struct mem_cgroup *memcg, int idx)
 {
-       long x = atomic_long_read(&memcg->stat[idx]);
+       long x = atomic_long_read(&memcg->vmstats[idx]);
 #ifdef CONFIG_SMP
        if (x < 0)
                x = 0;
@@ -581,23 +569,23 @@ static inline unsigned long memcg_page_state(struct mem_cgroup *memcg,
        return x;
 }
 
-/* idx can be of type enum memcg_stat_item or node_stat_item */
-static inline void __mod_memcg_state(struct mem_cgroup *memcg,
-                                    int idx, int val)
+/*
+ * idx can be of type enum memcg_stat_item or node_stat_item.
+ * Keep in sync with memcg_exact_page_state().
+ */
+static inline unsigned long memcg_page_state_local(struct mem_cgroup *memcg,
+                                                  int idx)
 {
-       long x;
-
-       if (mem_cgroup_disabled())
-               return;
-
-       x = val + __this_cpu_read(memcg->stat_cpu->count[idx]);
-       if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) {
-               atomic_long_add(x, &memcg->stat[idx]);
+       long x = atomic_long_read(&memcg->vmstats_local[idx]);
+#ifdef CONFIG_SMP
+       if (x < 0)
                x = 0;
-       }
-       __this_cpu_write(memcg->stat_cpu->count[idx], x);
+#endif
+       return x;
 }
 
+void __mod_memcg_state(struct mem_cgroup *memcg, int idx, int val);
+
 /* idx can be of type enum memcg_stat_item or node_stat_item */
 static inline void mod_memcg_state(struct mem_cgroup *memcg,
                                   int idx, int val)
@@ -658,32 +646,27 @@ static inline unsigned long lruvec_page_state(struct lruvec *lruvec,
        return x;
 }
 
-static inline void __mod_lruvec_state(struct lruvec *lruvec,
-                                     enum node_stat_item idx, int val)
+static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,
+                                                   enum node_stat_item idx)
 {
        struct mem_cgroup_per_node *pn;
        long x;
 
-       /* Update node */
-       __mod_node_page_state(lruvec_pgdat(lruvec), idx, val);
-
        if (mem_cgroup_disabled())
-               return;
+               return node_page_state(lruvec_pgdat(lruvec), idx);
 
        pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
-
-       /* Update memcg */
-       __mod_memcg_state(pn->memcg, idx, val);
-
-       /* Update lruvec */
-       x = val + __this_cpu_read(pn->lruvec_stat_cpu->count[idx]);
-       if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) {
-               atomic_long_add(x, &pn->lruvec_stat[idx]);
+       x = atomic_long_read(&pn->lruvec_stat_local[idx]);
+#ifdef CONFIG_SMP
+       if (x < 0)
                x = 0;
-       }
-       __this_cpu_write(pn->lruvec_stat_cpu->count[idx], x);
+#endif
+       return x;
 }
 
+void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
+                       int val);
+
 static inline void mod_lruvec_state(struct lruvec *lruvec,
                                    enum node_stat_item idx, int val)
 {
@@ -724,22 +707,8 @@ unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,
                                                gfp_t gfp_mask,
                                                unsigned long *total_scanned);
 
-static inline void __count_memcg_events(struct mem_cgroup *memcg,
-                                       enum vm_event_item idx,
-                                       unsigned long count)
-{
-       unsigned long x;
-
-       if (mem_cgroup_disabled())
-               return;
-
-       x = count + __this_cpu_read(memcg->stat_cpu->events[idx]);
-       if (unlikely(x > MEMCG_CHARGE_BATCH)) {
-               atomic_long_add(x, &memcg->events[idx]);
-               x = 0;
-       }
-       __this_cpu_write(memcg->stat_cpu->events[idx], x);
-}
+void __count_memcg_events(struct mem_cgroup *memcg, enum vm_event_item idx,
+                         unsigned long count);
 
 static inline void count_memcg_events(struct mem_cgroup *memcg,
                                      enum vm_event_item idx,
@@ -960,11 +929,6 @@ static inline bool mem_cgroup_online(struct mem_cgroup *memcg)
        return true;
 }
 
-static inline unsigned long
-mem_cgroup_get_lru_size(struct lruvec *lruvec, enum lru_list lru)
-{
-       return 0;
-}
 static inline
 unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec,
                enum lru_list lru, int zone_idx)
@@ -972,13 +936,6 @@ unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec,
        return 0;
 }
 
-static inline unsigned long
-mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
-                            int nid, unsigned int lru_mask)
-{
-       return 0;
-}
-
 static inline unsigned long mem_cgroup_get_max(struct mem_cgroup *memcg)
 {
        return 0;
@@ -1039,8 +996,13 @@ static inline void mem_cgroup_print_oom_group(struct mem_cgroup *memcg)
 {
 }
 
-static inline unsigned long memcg_page_state(struct mem_cgroup *memcg,
-                                            int idx)
+static inline unsigned long memcg_page_state(struct mem_cgroup *memcg, int idx)
+{
+       return 0;
+}
+
+static inline unsigned long memcg_page_state_local(struct mem_cgroup *memcg,
+                                                  int idx)
 {
        return 0;
 }
@@ -1075,6 +1037,12 @@ static inline unsigned long lruvec_page_state(struct lruvec *lruvec,
        return node_page_state(lruvec_pgdat(lruvec), idx);
 }
 
+static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,
+                                                   enum node_stat_item idx)
+{
+       return node_page_state(lruvec_pgdat(lruvec), idx);
+}
+
 static inline void __mod_lruvec_state(struct lruvec *lruvec,
                                      enum node_stat_item idx, int val)
 {
@@ -1117,6 +1085,12 @@ static inline void count_memcg_events(struct mem_cgroup *memcg,
 {
 }
 
+static inline void __count_memcg_events(struct mem_cgroup *memcg,
+                                       enum vm_event_item idx,
+                                       unsigned long count)
+{
+}
+
 static inline void count_memcg_page_event(struct page *page,
                                          int idx)
 {
index a6ddefc..e1dc1bb 100644 (file)
@@ -113,7 +113,7 @@ extern int register_memory_isolate_notifier(struct notifier_block *nb);
 extern void unregister_memory_isolate_notifier(struct notifier_block *nb);
 int hotplug_memory_register(int nid, struct mem_section *section);
 #ifdef CONFIG_MEMORY_HOTREMOVE
-extern int unregister_memory_section(struct mem_section *);
+extern void unregister_memory_section(struct mem_section *);
 #endif
 extern int memory_dev_init(void);
 extern int memory_notify(unsigned long val, void *v);
index 8ade08c..ae892ee 100644 (file)
@@ -53,6 +53,16 @@ enum {
        MMOP_ONLINE_MOVABLE,
 };
 
+/*
+ * Restrictions for the memory hotplug:
+ * flags:  MHP_ flags
+ * altmap: alternative allocator for memmap array
+ */
+struct mhp_restrictions {
+       unsigned long flags;
+       struct vmem_altmap *altmap;
+};
+
 /*
  * Zone resizing functions
  *
@@ -87,7 +97,8 @@ extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
 extern int online_pages(unsigned long, unsigned long, int);
 extern int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
        unsigned long *valid_start, unsigned long *valid_end);
-extern void __offline_isolated_pages(unsigned long, unsigned long);
+extern unsigned long __offline_isolated_pages(unsigned long start_pfn,
+                                               unsigned long end_pfn);
 
 typedef void (*online_page_callback_t)(struct page *page, unsigned int order);
 
@@ -100,6 +111,8 @@ extern void __online_page_free(struct page *page);
 
 extern int try_online_node(int nid);
 
+extern int arch_add_memory(int nid, u64 start, u64 size,
+                       struct mhp_restrictions *restrictions);
 extern u64 max_mem_size;
 
 extern bool memhp_auto_online;
@@ -111,26 +124,33 @@ static inline bool movable_node_is_enabled(void)
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
-extern int arch_remove_memory(int nid, u64 start, u64 size,
-                               struct vmem_altmap *altmap);
-extern int __remove_pages(struct zone *zone, unsigned long start_pfn,
-       unsigned long nr_pages, struct vmem_altmap *altmap);
+extern void arch_remove_memory(int nid, u64 start, u64 size,
+                              struct vmem_altmap *altmap);
+extern void __remove_pages(struct zone *zone, unsigned long start_pfn,
+                          unsigned long nr_pages, struct vmem_altmap *altmap);
 #endif /* CONFIG_MEMORY_HOTREMOVE */
 
+/*
+ * Do we want sysfs memblock files created. This will allow userspace to online
+ * and offline memory explicitly. Lack of this bit means that the caller has to
+ * call move_pfn_range_to_zone to finish the initialization.
+ */
+
+#define MHP_MEMBLOCK_API               (1<<0)
+
 /* reasonably generic interface to expand the physical pages */
 extern int __add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
-               struct vmem_altmap *altmap, bool want_memblock);
+                      struct mhp_restrictions *restrictions);
 
 #ifndef CONFIG_ARCH_HAS_ADD_PAGES
 static inline int add_pages(int nid, unsigned long start_pfn,
-               unsigned long nr_pages, struct vmem_altmap *altmap,
-               bool want_memblock)
+               unsigned long nr_pages, struct mhp_restrictions *restrictions)
 {
-       return __add_pages(nid, start_pfn, nr_pages, altmap, want_memblock);
+       return __add_pages(nid, start_pfn, nr_pages, restrictions);
 }
 #else /* ARCH_HAS_ADD_PAGES */
 int add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
-               struct vmem_altmap *altmap, bool want_memblock);
+             struct mhp_restrictions *restrictions);
 #endif /* ARCH_HAS_ADD_PAGES */
 
 #ifdef CONFIG_NUMA
@@ -331,8 +351,6 @@ extern int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn,
 extern int __add_memory(int nid, u64 start, u64 size);
 extern int add_memory(int nid, u64 start, u64 size);
 extern int add_memory_resource(int nid, struct resource *resource);
-extern int arch_add_memory(int nid, u64 start, u64 size,
-               struct vmem_altmap *altmap, bool want_memblock);
 extern void move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn,
                unsigned long nr_pages, struct vmem_altmap *altmap);
 extern bool is_memblock_offlined(struct memory_block *mem);
diff --git a/include/linux/mfd/altera-sysmgr.h b/include/linux/mfd/altera-sysmgr.h
new file mode 100644 (file)
index 0000000..b1ef11a
--- /dev/null
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018-2019 Intel Corporation
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro Ltd.
+ */
+
+#ifndef __LINUX_MFD_ALTERA_SYSMGR_H__
+#define __LINUX_MFD_ALTERA_SYSMGR_H__
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/firmware/intel/stratix10-smc.h>
+
+struct device_node;
+
+#ifdef CONFIG_MFD_ALTERA_SYSMGR
+struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np,
+                                                   const char *property);
+#else
+static inline struct regmap *
+altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np,
+                                    const char *property)
+{
+       return ERR_PTR(-ENOTSUPP);
+}
+#endif
+
+#endif /* __LINUX_MFD_ALTERA_SYSMGR_H__ */
index 8f2a891..cfa78bb 100644 (file)
 #include <linux/mutex.h>
 
 #define CROS_EC_DEV_NAME "cros_ec"
+#define CROS_EC_DEV_FP_NAME "cros_fp"
 #define CROS_EC_DEV_PD_NAME "cros_pd"
+#define CROS_EC_DEV_TP_NAME "cros_tp"
+#define CROS_EC_DEV_ISH_NAME "cros_ish"
 
 /*
  * The EC is unresponsive for a time after a reboot command.  Add a
@@ -120,6 +123,7 @@ struct cros_ec_command {
  * @pkt_xfer: Send packet to EC and get response.
  * @lock: One transaction at a time.
  * @mkbp_event_supported: True if this EC supports the MKBP event protocol.
+ * @host_sleep_v1: True if this EC supports the sleep v1 command.
  * @event_notifier: Interrupt event notifier for transport devices.
  * @event_data: Raw payload transferred with the MKBP event.
  * @event_size: Size in bytes of the event data.
@@ -153,6 +157,7 @@ struct cros_ec_device {
                        struct cros_ec_command *msg);
        struct mutex lock;
        bool mkbp_event_supported;
+       bool host_sleep_v1;
        struct blocking_notifier_head event_notifier;
 
        struct ec_response_get_next_event_v1 event_data;
index fc91082..dcec96f 100644 (file)
@@ -840,7 +840,7 @@ enum ec_feature_code {
         * (Common Smart Battery System Interface Specification)
         */
        EC_FEATURE_SMART_BATTERY = 18,
-       /* EC can dectect when the host hangs. */
+       /* EC can detect when the host hangs. */
        EC_FEATURE_HANG_DETECT = 19,
        /* Report power information, for pit only */
        EC_FEATURE_PMU = 20,
@@ -852,10 +852,42 @@ enum ec_feature_code {
        EC_FEATURE_USB_MUX = 23,
        /* Motion Sensor code has an internal software FIFO */
        EC_FEATURE_MOTION_SENSE_FIFO = 24,
+       /* Support temporary secure vstore */
+       EC_FEATURE_VSTORE = 25,
+       /* EC decides on USB-C SS mux state, muxes configured by host */
+       EC_FEATURE_USBC_SS_MUX_VIRTUAL = 26,
        /* EC has RTC feature that can be controlled by host commands */
        EC_FEATURE_RTC = 27,
+       /* The MCU exposes a Fingerprint sensor */
+       EC_FEATURE_FINGERPRINT = 28,
+       /* The MCU exposes a Touchpad */
+       EC_FEATURE_TOUCHPAD = 29,
+       /* The MCU has RWSIG task enabled */
+       EC_FEATURE_RWSIG = 30,
+       /* EC has device events support */
+       EC_FEATURE_DEVICE_EVENT = 31,
+       /* EC supports the unified wake masks for LPC/eSPI systems */
+       EC_FEATURE_UNIFIED_WAKE_MASKS = 32,
+       /* EC supports 64-bit host events */
+       EC_FEATURE_HOST_EVENT64 = 33,
+       /* EC runs code in RAM (not in place, a.k.a. XIP) */
+       EC_FEATURE_EXEC_IN_RAM = 34,
        /* EC supports CEC commands */
        EC_FEATURE_CEC = 35,
+       /* EC supports tight sensor timestamping. */
+       EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS = 36,
+       /*
+        * EC supports tablet mode detection aligned to Chrome and allows
+        * setting of threshold by host command using
+        * MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE.
+        */
+       EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS = 37,
+       /* EC supports audio codec. */
+       EC_FEATURE_AUDIO_CODEC = 38,
+       /* EC Supports SCP. */
+       EC_FEATURE_SCP = 39,
+       /* The MCU is an Integrated Sensor Hub */
+       EC_FEATURE_ISH = 40,
 };
 
 #define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
@@ -2729,6 +2761,63 @@ struct ec_params_host_sleep_event {
        uint8_t sleep_event;
 } __packed;
 
+/*
+ * Use a default timeout value (CONFIG_SLEEP_TIMEOUT_MS) for detecting sleep
+ * transition failures
+ */
+#define EC_HOST_SLEEP_TIMEOUT_DEFAULT 0
+
+/* Disable timeout detection for this sleep transition */
+#define EC_HOST_SLEEP_TIMEOUT_INFINITE 0xFFFF
+
+struct ec_params_host_sleep_event_v1 {
+       /* The type of sleep being entered or exited. */
+       uint8_t sleep_event;
+
+       /* Padding */
+       uint8_t reserved;
+       union {
+               /* Parameters that apply for suspend messages. */
+               struct {
+                       /*
+                        * The timeout in milliseconds between when this message
+                        * is received and when the EC will declare sleep
+                        * transition failure if the sleep signal is not
+                        * asserted.
+                        */
+                       uint16_t sleep_timeout_ms;
+               } suspend_params;
+
+               /* No parameters for non-suspend messages. */
+       };
+} __packed;
+
+/* A timeout occurred when this bit is set */
+#define EC_HOST_RESUME_SLEEP_TIMEOUT 0x80000000
+
+/*
+ * The mask defining which bits correspond to the number of sleep transitions,
+ * as well as the maximum number of suspend line transitions that will be
+ * reported back to the host.
+ */
+#define EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK 0x7FFFFFFF
+
+struct ec_response_host_sleep_event_v1 {
+       union {
+               /* Response fields that apply for resume messages. */
+               struct {
+                       /*
+                        * The number of sleep power signal transitions that
+                        * occurred since the suspend message. The high bit
+                        * indicates a timeout occurred.
+                        */
+                       uint32_t sleep_transitions;
+               } resume_response;
+
+               /* No response fields for non-resume messages. */
+       };
+} __packed;
+
 /*****************************************************************************/
 /* Smart battery pass-through */
 
index 71b0915..5cd06ab 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Definitions for DA9063 MFD driver
  *
@@ -5,12 +6,6 @@
  *
  * Author: Michal Hajduk, Dialog Semiconductor
  * Author: Krystian Garbaciak, Dialog 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.
- *
  */
 
 #ifndef __MFD_DA9063_CORE_H__
index 5d42859..ba706b0 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Registers definition for DA9063 modules
  *
@@ -5,12 +6,6 @@
  *
  * Author: Michal Hajduk, Dialog Semiconductor
  * Author: Krystian Garbaciak, Dialog 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.
- *
  */
 
 #ifndef _DA9063_REG_H
 
 /* DA9063 Configuration registers */
 /* OTP */
-#define        DA9063_REG_OPT_COUNT            0x101
-#define        DA9063_REG_OPT_ADDR             0x102
-#define        DA9063_REG_OPT_DATA             0x103
+#define        DA9063_REG_OTP_CONT             0x101
+#define        DA9063_REG_OTP_ADDR             0x102
+#define        DA9063_REG_OTP_DATA             0x103
 
 /* Customer Trim and Configuration */
 #define        DA9063_REG_T_OFFSET             0x104
index ad2a9a8..82407fe 100644 (file)
 #define MAX77620_FPS_PERIOD_MIN_US             40
 #define MAX20024_FPS_PERIOD_MIN_US             20
 
-#define MAX77620_FPS_PERIOD_MAX_US             2560
-#define MAX20024_FPS_PERIOD_MAX_US             5120
+#define MAX20024_FPS_PERIOD_MAX_US             2560
+#define MAX77620_FPS_PERIOD_MAX_US             5120
 
 #define MAX77620_REG_FPS_GPIO1                 0x54
 #define MAX77620_REG_FPS_GPIO2                 0x55
@@ -324,6 +324,7 @@ enum max77620_fps_src {
 enum max77620_chip_id {
        MAX77620,
        MAX20024,
+       MAX77663,
 };
 
 struct max77620_chip {
diff --git a/include/linux/mfd/max77650.h b/include/linux/mfd/max77650.h
new file mode 100644 (file)
index 0000000..c809e21
--- /dev/null
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 BayLibre SAS
+ * Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+ *
+ * Common definitions for MAXIM 77650/77651 charger/power-supply.
+ */
+
+#ifndef MAX77650_H
+#define MAX77650_H
+
+#include <linux/bits.h>
+
+#define MAX77650_REG_INT_GLBL          0x00
+#define MAX77650_REG_INT_CHG           0x01
+#define MAX77650_REG_STAT_CHG_A                0x02
+#define MAX77650_REG_STAT_CHG_B                0x03
+#define MAX77650_REG_ERCFLAG           0x04
+#define MAX77650_REG_STAT_GLBL         0x05
+#define MAX77650_REG_INTM_GLBL         0x06
+#define MAX77650_REG_INTM_CHG          0x07
+#define MAX77650_REG_CNFG_GLBL         0x10
+#define MAX77650_REG_CID               0x11
+#define MAX77650_REG_CNFG_GPIO         0x12
+#define MAX77650_REG_CNFG_CHG_A                0x18
+#define MAX77650_REG_CNFG_CHG_B                0x19
+#define MAX77650_REG_CNFG_CHG_C                0x1a
+#define MAX77650_REG_CNFG_CHG_D                0x1b
+#define MAX77650_REG_CNFG_CHG_E                0x1c
+#define MAX77650_REG_CNFG_CHG_F                0x1d
+#define MAX77650_REG_CNFG_CHG_G                0x1e
+#define MAX77650_REG_CNFG_CHG_H                0x1f
+#define MAX77650_REG_CNFG_CHG_I                0x20
+#define MAX77650_REG_CNFG_SBB_TOP      0x28
+#define MAX77650_REG_CNFG_SBB0_A       0x29
+#define MAX77650_REG_CNFG_SBB0_B       0x2a
+#define MAX77650_REG_CNFG_SBB1_A       0x2b
+#define MAX77650_REG_CNFG_SBB1_B       0x2c
+#define MAX77650_REG_CNFG_SBB2_A       0x2d
+#define MAX77650_REG_CNFG_SBB2_B       0x2e
+#define MAX77650_REG_CNFG_LDO_A                0x38
+#define MAX77650_REG_CNFG_LDO_B                0x39
+#define MAX77650_REG_CNFG_LED0_A       0x40
+#define MAX77650_REG_CNFG_LED1_A       0x41
+#define MAX77650_REG_CNFG_LED2_A       0x42
+#define MAX77650_REG_CNFG_LED0_B       0x43
+#define MAX77650_REG_CNFG_LED1_B       0x44
+#define MAX77650_REG_CNFG_LED2_B       0x45
+#define MAX77650_REG_CNFG_LED_TOP      0x46
+
+#define MAX77650_CID_MASK              GENMASK(3, 0)
+#define MAX77650_CID_BITS(_reg)                (_reg & MAX77650_CID_MASK)
+
+#define MAX77650_CID_77650A            0x03
+#define MAX77650_CID_77650C            0x0a
+#define MAX77650_CID_77651A            0x06
+#define MAX77650_CID_77651B            0x08
+
+#endif /* MAX77650_H */
diff --git a/include/linux/mfd/stmfx.h b/include/linux/mfd/stmfx.h
new file mode 100644 (file)
index 0000000..d890595
--- /dev/null
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 STMicroelectronics
+ * Author(s): Amelie Delaunay <amelie.delaunay@st.com>.
+ */
+
+#ifndef MFD_STMFX_H
+#define MFX_STMFX_H
+
+#include <linux/regmap.h>
+
+/* General */
+#define STMFX_REG_CHIP_ID              0x00 /* R */
+#define STMFX_REG_FW_VERSION_MSB       0x01 /* R */
+#define STMFX_REG_FW_VERSION_LSB       0x02 /* R */
+#define STMFX_REG_SYS_CTRL             0x40 /* RW */
+/* IRQ output management */
+#define STMFX_REG_IRQ_OUT_PIN          0x41 /* RW */
+#define STMFX_REG_IRQ_SRC_EN           0x42 /* RW */
+#define STMFX_REG_IRQ_PENDING          0x08 /* R */
+#define STMFX_REG_IRQ_ACK              0x44 /* RW */
+/* GPIO management */
+#define STMFX_REG_IRQ_GPI_PENDING1     0x0C /* R */
+#define STMFX_REG_IRQ_GPI_PENDING2     0x0D /* R */
+#define STMFX_REG_IRQ_GPI_PENDING3     0x0E /* R */
+#define STMFX_REG_GPIO_STATE1          0x10 /* R */
+#define STMFX_REG_GPIO_STATE2          0x11 /* R */
+#define STMFX_REG_GPIO_STATE3          0x12 /* R */
+#define STMFX_REG_IRQ_GPI_SRC1         0x48 /* RW */
+#define STMFX_REG_IRQ_GPI_SRC2         0x49 /* RW */
+#define STMFX_REG_IRQ_GPI_SRC3         0x4A /* RW */
+#define STMFX_REG_IRQ_GPI_EVT1         0x4C /* RW */
+#define STMFX_REG_IRQ_GPI_EVT2         0x4D /* RW */
+#define STMFX_REG_IRQ_GPI_EVT3         0x4E /* RW */
+#define STMFX_REG_IRQ_GPI_TYPE1                0x50 /* RW */
+#define STMFX_REG_IRQ_GPI_TYPE2                0x51 /* RW */
+#define STMFX_REG_IRQ_GPI_TYPE3                0x52 /* RW */
+#define STMFX_REG_IRQ_GPI_ACK1         0x54 /* RW */
+#define STMFX_REG_IRQ_GPI_ACK2         0x55 /* RW */
+#define STMFX_REG_IRQ_GPI_ACK3         0x56 /* RW */
+#define STMFX_REG_GPIO_DIR1            0x60 /* RW */
+#define STMFX_REG_GPIO_DIR2            0x61 /* RW */
+#define STMFX_REG_GPIO_DIR3            0x62 /* RW */
+#define STMFX_REG_GPIO_TYPE1           0x64 /* RW */
+#define STMFX_REG_GPIO_TYPE2           0x65 /* RW */
+#define STMFX_REG_GPIO_TYPE3           0x66 /* RW */
+#define STMFX_REG_GPIO_PUPD1           0x68 /* RW */
+#define STMFX_REG_GPIO_PUPD2           0x69 /* RW */
+#define STMFX_REG_GPIO_PUPD3           0x6A /* RW */
+#define STMFX_REG_GPO_SET1             0x6C /* RW */
+#define STMFX_REG_GPO_SET2             0x6D /* RW */
+#define STMFX_REG_GPO_SET3             0x6E /* RW */
+#define STMFX_REG_GPO_CLR1             0x70 /* RW */
+#define STMFX_REG_GPO_CLR2             0x71 /* RW */
+#define STMFX_REG_GPO_CLR3             0x72 /* RW */
+
+#define STMFX_REG_MAX                  0xB0
+
+/* MFX boot time is around 10ms, so after reset, we have to wait this delay */
+#define STMFX_BOOT_TIME_MS 10
+
+/* STMFX_REG_CHIP_ID bitfields */
+#define STMFX_REG_CHIP_ID_MASK         GENMASK(7, 0)
+
+/* STMFX_REG_SYS_CTRL bitfields */
+#define STMFX_REG_SYS_CTRL_GPIO_EN     BIT(0)
+#define STMFX_REG_SYS_CTRL_TS_EN       BIT(1)
+#define STMFX_REG_SYS_CTRL_IDD_EN      BIT(2)
+#define STMFX_REG_SYS_CTRL_ALTGPIO_EN  BIT(3)
+#define STMFX_REG_SYS_CTRL_SWRST       BIT(7)
+
+/* STMFX_REG_IRQ_OUT_PIN bitfields */
+#define STMFX_REG_IRQ_OUT_PIN_TYPE     BIT(0) /* 0-OD 1-PP */
+#define STMFX_REG_IRQ_OUT_PIN_POL      BIT(1) /* 0-active LOW 1-active HIGH */
+
+/* STMFX_REG_IRQ_(SRC_EN/PENDING/ACK) bit shift */
+enum stmfx_irqs {
+       STMFX_REG_IRQ_SRC_EN_GPIO = 0,
+       STMFX_REG_IRQ_SRC_EN_IDD,
+       STMFX_REG_IRQ_SRC_EN_ERROR,
+       STMFX_REG_IRQ_SRC_EN_TS_DET,
+       STMFX_REG_IRQ_SRC_EN_TS_NE,
+       STMFX_REG_IRQ_SRC_EN_TS_TH,
+       STMFX_REG_IRQ_SRC_EN_TS_FULL,
+       STMFX_REG_IRQ_SRC_EN_TS_OVF,
+       STMFX_REG_IRQ_SRC_MAX,
+};
+
+enum stmfx_functions {
+       STMFX_FUNC_GPIO         = BIT(0), /* GPIO[15:0] */
+       STMFX_FUNC_ALTGPIO_LOW  = BIT(1), /* aGPIO[3:0] */
+       STMFX_FUNC_ALTGPIO_HIGH = BIT(2), /* aGPIO[7:4] */
+       STMFX_FUNC_TS           = BIT(3),
+       STMFX_FUNC_IDD          = BIT(4),
+};
+
+/**
+ * struct stmfx_ddata - STMFX MFD structure
+ * @device:            device reference used for logs
+ * @map:               register map
+ * @vdd:               STMFX power supply
+ * @irq_domain:                IRQ domain
+ * @lock:              IRQ bus lock
+ * @irq_src:           cache of IRQ_SRC_EN register for bus_lock
+ * @bkp_sysctrl:       backup of SYS_CTRL register for suspend/resume
+ * @bkp_irqoutpin:     backup of IRQ_OUT_PIN register for suspend/resume
+ */
+struct stmfx {
+       struct device *dev;
+       struct regmap *map;
+       struct regulator *vdd;
+       struct irq_domain *irq_domain;
+       struct mutex lock; /* IRQ bus lock */
+       u8 irq_src;
+#ifdef CONFIG_PM
+       u8 bkp_sysctrl;
+       u8 bkp_irqoutpin;
+#endif
+};
+
+int stmfx_function_enable(struct stmfx *stmfx, u32 func);
+int stmfx_function_disable(struct stmfx *stmfx, u32 func);
+#endif
index 8293c3e..f61cd12 100644 (file)
@@ -1,12 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  *  Copyright (C) 2014 Atmel Corporation.
  *
  * Memory Controllers (MATRIX, EBI) - System peripherals registers.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
  */
 
 #ifndef _LINUX_MFD_SYSCON_ATMEL_MATRIX_H
index afd9b8f..99c5620 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
@@ -5,11 +6,6 @@
  * Memory Controllers (MC, EBI, SMC, SDRAMC, BFC) - System peripherals
  * registers.
  * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
  */
 
 #ifndef _LINUX_MFD_SYSCON_ATMEL_MC_H_
index 7a367f3..e9e24f4 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Atmel SMC (Static Memory Controller) register offsets and bit definitions.
  *
@@ -5,10 +6,6 @@
  * Copyright (C) 2014 Free Electrons
  *
  * Author: Boris Brezillon <boris.brezillon@free-electrons.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.
  */
 
 #ifndef _LINUX_MFD_SYSCON_ATMEL_SMC_H_
index 8acf1ec..5b6013d 100644 (file)
@@ -1,14 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
  *
  * System Timer (ST) - System peripherals registers.
  * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
  */
 
 #ifndef _LINUX_MFD_SYSCON_ATMEL_ST_H
index c1b25f5..f232c81 100644 (file)
 #define IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK             (0x3 << 17)
 #define IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_EXT              (0x3 << 13)
 
+#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_GPR4_FEC_ENET1_STOP_REQ                 (0x1 << 3)
 #define IMX6SX_GPR4_FEC_ENET2_STOP_REQ                 (0x1 << 4)
 
index 8261274..5e74305 100644 (file)
@@ -7344,7 +7344,7 @@ struct mlx5_ifc_create_eq_out_bits {
 
 struct mlx5_ifc_create_eq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_at_10[0x10];
+       u8         uid[0x10];
 
        u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
index 083d7b4..0e8834a 100644 (file)
@@ -124,10 +124,45 @@ extern int mmap_rnd_compat_bits __read_mostly;
 
 /*
  * On some architectures it is expensive to call memset() for small sizes.
- * Those architectures should provide their own implementation of "struct page"
- * zeroing by defining this macro in <asm/pgtable.h>.
+ * If an architecture decides to implement their own version of
+ * mm_zero_struct_page they should wrap the defines below in a #ifndef and
+ * define their own version of this macro in <asm/pgtable.h>
  */
-#ifndef mm_zero_struct_page
+#if BITS_PER_LONG == 64
+/* This function must be updated when the size of struct page grows above 80
+ * or reduces below 56. The idea that compiler optimizes out switch()
+ * statement, and only leaves move/store instructions. Also the compiler can
+ * combine write statments if they are both assignments and can be reordered,
+ * this can result in several of the writes here being dropped.
+ */
+#define        mm_zero_struct_page(pp) __mm_zero_struct_page(pp)
+static inline void __mm_zero_struct_page(struct page *page)
+{
+       unsigned long *_pp = (void *)page;
+
+        /* Check that struct page is either 56, 64, 72, or 80 bytes */
+       BUILD_BUG_ON(sizeof(struct page) & 7);
+       BUILD_BUG_ON(sizeof(struct page) < 56);
+       BUILD_BUG_ON(sizeof(struct page) > 80);
+
+       switch (sizeof(struct page)) {
+       case 80:
+               _pp[9] = 0;     /* fallthrough */
+       case 72:
+               _pp[8] = 0;     /* fallthrough */
+       case 64:
+               _pp[7] = 0;     /* fallthrough */
+       case 56:
+               _pp[6] = 0;
+               _pp[5] = 0;
+               _pp[4] = 0;
+               _pp[3] = 0;
+               _pp[2] = 0;
+               _pp[1] = 0;
+               _pp[0] = 0;
+       }
+}
+#else
 #define mm_zero_struct_page(pp)  ((void)memset((pp), 0, sizeof(struct page)))
 #endif
 
@@ -501,9 +536,6 @@ static inline void vma_set_anonymous(struct vm_area_struct *vma)
 struct mmu_gather;
 struct inode;
 
-#define page_private(page)             ((page)->private)
-#define set_page_private(page, v)      ((page)->private = (v))
-
 #if !defined(__HAVE_ARCH_PTE_DEVMAP) || !defined(CONFIG_TRANSPARENT_HUGEPAGE)
 static inline int pmd_devmap(pmd_t pmd)
 {
@@ -1007,6 +1039,30 @@ static inline void put_page(struct page *page)
                __put_page(page);
 }
 
+/**
+ * put_user_page() - release a gup-pinned page
+ * @page:            pointer to page to be released
+ *
+ * Pages that were pinned via get_user_pages*() must be released via
+ * either put_user_page(), or one of the put_user_pages*() routines
+ * below. This is so that eventually, pages that are pinned via
+ * get_user_pages*() can be separately tracked and uniquely handled. In
+ * particular, interactions with RDMA and filesystems need special
+ * handling.
+ *
+ * put_user_page() and put_page() are not interchangeable, despite this early
+ * implementation that makes them look the same. put_user_page() calls must
+ * be perfectly matched up with get_user_page() calls.
+ */
+static inline void put_user_page(struct page *page)
+{
+       put_page(page);
+}
+
+void put_user_pages_dirty(struct page **pages, unsigned long npages);
+void put_user_pages_dirty_lock(struct page **pages, unsigned long npages);
+void put_user_pages(struct page **pages, unsigned long npages);
+
 #if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
 #define SECTION_IN_PAGE_FLAGS
 #endif
@@ -1505,21 +1561,8 @@ long get_user_pages_locked(unsigned long start, unsigned long nr_pages,
 long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
                    struct page **pages, unsigned int gup_flags);
 
-#if defined(CONFIG_FS_DAX) || defined(CONFIG_CMA)
-long get_user_pages_longterm(unsigned long start, unsigned long nr_pages,
-                           unsigned int gup_flags, struct page **pages,
-                           struct vm_area_struct **vmas);
-#else
-static inline long get_user_pages_longterm(unsigned long start,
-               unsigned long nr_pages, unsigned int gup_flags,
-               struct page **pages, struct vm_area_struct **vmas)
-{
-       return get_user_pages(start, nr_pages, gup_flags, pages, vmas);
-}
-#endif /* CONFIG_FS_DAX */
-
-int get_user_pages_fast(unsigned long start, int nr_pages, int write,
-                       struct page **pages);
+int get_user_pages_fast(unsigned long start, int nr_pages,
+                       unsigned int gup_flags, struct page **pages);
 
 /* Container for pinned pfns / pages */
 struct frame_vector {
@@ -2533,6 +2576,10 @@ struct vm_area_struct *find_extend_vma(struct mm_struct *, unsigned long addr);
 int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
                        unsigned long pfn, unsigned long size, pgprot_t);
 int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *);
+int vm_map_pages(struct vm_area_struct *vma, struct page **pages,
+                               unsigned long num);
+int vm_map_pages_zero(struct vm_area_struct *vma, struct page **pages,
+                               unsigned long num);
 vm_fault_t vmf_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
                        unsigned long pfn);
 vm_fault_t vmf_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr,
@@ -2583,6 +2630,34 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
 #define FOLL_REMOTE    0x2000  /* we are working on non-current tsk/mm */
 #define FOLL_COW       0x4000  /* internal GUP flag */
 #define FOLL_ANON      0x8000  /* don't do file mappings */
+#define FOLL_LONGTERM  0x10000 /* mapping lifetime is indefinite: see below */
+
+/*
+ * NOTE on FOLL_LONGTERM:
+ *
+ * FOLL_LONGTERM indicates that the page will be held for an indefinite time
+ * period _often_ under userspace control.  This is contrasted with
+ * iov_iter_get_pages() where usages which are transient.
+ *
+ * FIXME: For pages which are part of a filesystem, mappings are subject to the
+ * lifetime enforced by the filesystem and we need guarantees that longterm
+ * users like RDMA and V4L2 only establish mappings which coordinate usage with
+ * the filesystem.  Ideas for this coordination include revoking the longterm
+ * pin, delaying writeback, bounce buffer page writeback, etc.  As FS DAX was
+ * added after the problem with filesystems was found FS DAX VMAs are
+ * specifically failed.  Filesystem pages are still subject to bugs and use of
+ * FOLL_LONGTERM should be avoided on those pages.
+ *
+ * FIXME: Also NOTE that FOLL_LONGTERM is not supported in every GUP call.
+ * Currently only get_user_pages() and get_user_pages_fast() support this flag
+ * and calls to get_user_pages_[un]locked are specifically not allowed.  This
+ * is due to an incompatibility with the FS DAX check and
+ * FAULT_FLAG_ALLOW_RETRY
+ *
+ * In the CMA case: longterm pins in a CMA region would unnecessarily fragment
+ * that region.  And so CMA attempts to migrate the page before pinning when
+ * FOLL_LONGTERM is specified.
+ */
 
 static inline int vm_fault_to_errno(vm_fault_t vm_fault, int foll_flags)
 {
index 04ec454..6f2fef7 100644 (file)
@@ -29,7 +29,7 @@ static __always_inline void __update_lru_size(struct lruvec *lruvec,
 {
        struct pglist_data *pgdat = lruvec_pgdat(lruvec);
 
-       __mod_node_page_state(pgdat, NR_LRU_BASE + lru, nr_pages);
+       __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
        __mod_zone_page_state(&pgdat->node_zones[zid],
                                NR_ZONE_LRU_BASE + lru, nr_pages);
 }
index 4ef4bbe..8ec38b1 100644 (file)
@@ -103,7 +103,7 @@ struct page {
                };
                struct {        /* slab, slob and slub */
                        union {
-                               struct list_head slab_list;     /* uses lru */
+                               struct list_head slab_list;
                                struct {        /* Partial pages */
                                        struct page *next;
 #ifdef CONFIG_64BIT
@@ -220,6 +220,9 @@ struct page {
 #define PAGE_FRAG_CACHE_MAX_SIZE       __ALIGN_MASK(32768, ~PAGE_MASK)
 #define PAGE_FRAG_CACHE_MAX_ORDER      get_order(PAGE_FRAG_CACHE_MAX_SIZE)
 
+#define page_private(page)             ((page)->private)
+#define set_page_private(page, v)      ((page)->private = (v))
+
 struct page_frag_cache {
        void * va;
 #if (PAGE_SIZE < PAGE_FRAG_CACHE_MAX_SIZE)
index 4050ec1..b6c004b 100644 (file)
 struct mmu_notifier;
 struct mmu_notifier_ops;
 
+/**
+ * enum mmu_notifier_event - reason for the mmu notifier callback
+ * @MMU_NOTIFY_UNMAP: either munmap() that unmap the range or a mremap() that
+ * move the range
+ *
+ * @MMU_NOTIFY_CLEAR: clear page table entry (many reasons for this like
+ * madvise() or replacing a page by another one, ...).
+ *
+ * @MMU_NOTIFY_PROTECTION_VMA: update is due to protection change for the range
+ * ie using the vma access permission (vm_page_prot) to update the whole range
+ * is enough no need to inspect changes to the CPU page table (mprotect()
+ * syscall)
+ *
+ * @MMU_NOTIFY_PROTECTION_PAGE: update is due to change in read/write flag for
+ * pages in the range so to mirror those changes the user must inspect the CPU
+ * page table (from the end callback).
+ *
+ * @MMU_NOTIFY_SOFT_DIRTY: soft dirty accounting (still same page and same
+ * access flags). User should soft dirty the page in the end callback to make
+ * sure that anyone relying on soft dirtyness catch pages that might be written
+ * through non CPU mappings.
+ */
+enum mmu_notifier_event {
+       MMU_NOTIFY_UNMAP = 0,
+       MMU_NOTIFY_CLEAR,
+       MMU_NOTIFY_PROTECTION_VMA,
+       MMU_NOTIFY_PROTECTION_PAGE,
+       MMU_NOTIFY_SOFT_DIRTY,
+};
+
 #ifdef CONFIG_MMU_NOTIFIER
 
 /*
@@ -25,11 +55,15 @@ struct mmu_notifier_mm {
        spinlock_t lock;
 };
 
+#define MMU_NOTIFIER_RANGE_BLOCKABLE (1 << 0)
+
 struct mmu_notifier_range {
+       struct vm_area_struct *vma;
        struct mm_struct *mm;
        unsigned long start;
        unsigned long end;
-       bool blockable;
+       unsigned flags;
+       enum mmu_notifier_event event;
 };
 
 struct mmu_notifier_ops {
@@ -225,6 +259,14 @@ extern void __mmu_notifier_invalidate_range_end(struct mmu_notifier_range *r,
                                  bool only_end);
 extern void __mmu_notifier_invalidate_range(struct mm_struct *mm,
                                  unsigned long start, unsigned long end);
+extern bool
+mmu_notifier_range_update_to_read_only(const struct mmu_notifier_range *range);
+
+static inline bool
+mmu_notifier_range_blockable(const struct mmu_notifier_range *range)
+{
+       return (range->flags & MMU_NOTIFIER_RANGE_BLOCKABLE);
+}
 
 static inline void mmu_notifier_release(struct mm_struct *mm)
 {
@@ -269,7 +311,7 @@ static inline void
 mmu_notifier_invalidate_range_start(struct mmu_notifier_range *range)
 {
        if (mm_has_notifiers(range->mm)) {
-               range->blockable = true;
+               range->flags |= MMU_NOTIFIER_RANGE_BLOCKABLE;
                __mmu_notifier_invalidate_range_start(range);
        }
 }
@@ -278,7 +320,7 @@ static inline int
 mmu_notifier_invalidate_range_start_nonblock(struct mmu_notifier_range *range)
 {
        if (mm_has_notifiers(range->mm)) {
-               range->blockable = false;
+               range->flags &= ~MMU_NOTIFIER_RANGE_BLOCKABLE;
                return __mmu_notifier_invalidate_range_start(range);
        }
        return 0;
@@ -318,13 +360,19 @@ static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
 
 
 static inline void mmu_notifier_range_init(struct mmu_notifier_range *range,
+                                          enum mmu_notifier_event event,
+                                          unsigned flags,
+                                          struct vm_area_struct *vma,
                                           struct mm_struct *mm,
                                           unsigned long start,
                                           unsigned long end)
 {
+       range->vma = vma;
+       range->event = event;
        range->mm = mm;
        range->start = start;
        range->end = end;
+       range->flags = flags;
 }
 
 #define ptep_clear_flush_young_notify(__vma, __address, __ptep)                \
@@ -452,9 +500,14 @@ static inline void _mmu_notifier_range_init(struct mmu_notifier_range *range,
        range->end = end;
 }
 
-#define mmu_notifier_range_init(range, mm, start, end) \
+#define mmu_notifier_range_init(range,event,flags,vma,mm,start,end)  \
        _mmu_notifier_range_init(range, start, end)
 
+static inline bool
+mmu_notifier_range_blockable(const struct mmu_notifier_range *range)
+{
+       return true;
+}
 
 static inline int mm_has_notifiers(struct mm_struct *mm)
 {
@@ -517,6 +570,8 @@ static inline void mmu_notifier_mm_destroy(struct mm_struct *mm)
 {
 }
 
+#define mmu_notifier_range_update_to_read_only(r) false
+
 #define ptep_clear_flush_young_notify ptep_clear_flush_young
 #define pmdp_clear_flush_young_notify pmdp_clear_flush_young
 #define ptep_clear_young_notify ptep_test_and_clear_young
index fba7741..70394ca 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/pageblock-flags.h>
 #include <linux/page-flags-layout.h>
 #include <linux/atomic.h>
+#include <linux/mm_types.h>
+#include <linux/page-flags.h>
 #include <asm/page.h>
 
 /* Free memory management - zoned buddy allocator.  */
@@ -98,6 +100,62 @@ struct free_area {
        unsigned long           nr_free;
 };
 
+/* Used for pages not on another list */
+static inline void add_to_free_area(struct page *page, struct free_area *area,
+                            int migratetype)
+{
+       list_add(&page->lru, &area->free_list[migratetype]);
+       area->nr_free++;
+}
+
+/* Used for pages not on another list */
+static inline void add_to_free_area_tail(struct page *page, struct free_area *area,
+                                 int migratetype)
+{
+       list_add_tail(&page->lru, &area->free_list[migratetype]);
+       area->nr_free++;
+}
+
+#ifdef CONFIG_SHUFFLE_PAGE_ALLOCATOR
+/* Used to preserve page allocation order entropy */
+void add_to_free_area_random(struct page *page, struct free_area *area,
+               int migratetype);
+#else
+static inline void add_to_free_area_random(struct page *page,
+               struct free_area *area, int migratetype)
+{
+       add_to_free_area(page, area, migratetype);
+}
+#endif
+
+/* Used for pages which are on another list */
+static inline void move_to_free_area(struct page *page, struct free_area *area,
+                            int migratetype)
+{
+       list_move(&page->lru, &area->free_list[migratetype]);
+}
+
+static inline struct page *get_page_from_free_area(struct free_area *area,
+                                           int migratetype)
+{
+       return list_first_entry_or_null(&area->free_list[migratetype],
+                                       struct page, lru);
+}
+
+static inline void del_page_from_free_area(struct page *page,
+               struct free_area *area)
+{
+       list_del(&page->lru);
+       __ClearPageBuddy(page);
+       set_page_private(page, 0);
+       area->nr_free--;
+}
+
+static inline bool free_area_empty(struct free_area *area, int migratetype)
+{
+       return list_empty(&area->free_list[migratetype]);
+}
+
 struct pglist_data;
 
 /*
@@ -247,11 +305,6 @@ struct lruvec {
 #endif
 };
 
-/* Mask used at gathering information at once (see memcontrol.c) */
-#define LRU_ALL_FILE (BIT(LRU_INACTIVE_FILE) | BIT(LRU_ACTIVE_FILE))
-#define LRU_ALL_ANON (BIT(LRU_INACTIVE_ANON) | BIT(LRU_ACTIVE_ANON))
-#define LRU_ALL             ((1 << NR_LRU_LISTS) - 1)
-
 /* Isolate unmapped file */
 #define ISOLATE_UNMAPPED       ((__force isolate_mode_t)0x2)
 /* Isolate for asynchronous migration */
@@ -1276,6 +1329,7 @@ void sparse_init(void);
 #else
 #define sparse_init()  do {} while (0)
 #define sparse_index_init(_sec, _nid)  do {} while (0)
+#define pfn_present pfn_valid
 #endif /* CONFIG_SPARSEMEM */
 
 /*
index 8f75277..188998d 100644 (file)
@@ -332,6 +332,7 @@ struct mod_kallsyms {
        Elf_Sym *symtab;
        unsigned int num_symtab;
        char *strtab;
+       char *typetab;
 };
 
 #ifdef CONFIG_LIVEPATCH
@@ -717,6 +718,17 @@ static inline bool within_module_core(unsigned long addr,
        return false;
 }
 
+static inline bool within_module_init(unsigned long addr,
+                                     const struct module *mod)
+{
+       return false;
+}
+
+static inline bool within_module(unsigned long addr, const struct module *mod)
+{
+       return false;
+}
+
 /* Get/put a kernel symbol (calls should be symmetric) */
 #define symbol_get(x) ({ extern typeof(x) x __attribute__((weak)); &(x); })
 #define symbol_put(x) do { } while (0)
index 7e9b81c..052f04f 100644 (file)
@@ -148,24 +148,6 @@ u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag);
 void pci_msi_mask_irq(struct irq_data *data);
 void pci_msi_unmask_irq(struct irq_data *data);
 
-/* Conversion helpers. Should be removed after merging */
-static inline void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
-{
-       __pci_write_msi_msg(entry, msg);
-}
-static inline void write_msi_msg(int irq, struct msi_msg *msg)
-{
-       pci_write_msi_msg(irq, msg);
-}
-static inline void mask_msi_irq(struct irq_data *data)
-{
-       pci_msi_mask_irq(data);
-}
-static inline void unmask_msi_irq(struct irq_data *data)
-{
-       pci_msi_unmask_irq(data);
-}
-
 /*
  * The arch hooks to setup up msi irqs. Those functions are
  * implemented as weak symbols so that they /can/ be overriden by
index c40720c..8028ada 100644 (file)
@@ -1246,9 +1246,9 @@ enum {
        NVME_SC_FW_NEEDS_SUBSYS_RESET   = 0x110,
        NVME_SC_FW_NEEDS_RESET          = 0x111,
        NVME_SC_FW_NEEDS_MAX_TIME       = 0x112,
-       NVME_SC_FW_ACIVATE_PROHIBITED   = 0x113,
+       NVME_SC_FW_ACTIVATE_PROHIBITED  = 0x113,
        NVME_SC_OVERLAPPING_RANGE       = 0x114,
-       NVME_SC_NS_INSUFFICENT_CAP      = 0x115,
+       NVME_SC_NS_INSUFFICIENT_CAP     = 0x115,
        NVME_SC_NS_ID_UNAVAILABLE       = 0x116,
        NVME_SC_NS_ALREADY_ATTACHED     = 0x118,
        NVME_SC_NS_IS_PRIVATE           = 0x119,
index 15eb85d..6590450 100644 (file)
@@ -284,11 +284,15 @@ static inline __must_check size_t array3_size(size_t a, size_t b, size_t c)
        return bytes;
 }
 
-static inline __must_check size_t __ab_c_size(size_t n, size_t size, size_t c)
+/*
+ * Compute a*b+c, returning SIZE_MAX on overflow. Internal helper for
+ * struct_size() below.
+ */
+static inline __must_check size_t __ab_c_size(size_t a, size_t b, size_t c)
 {
        size_t bytes;
 
-       if (check_mul_overflow(n, size, &bytes))
+       if (check_mul_overflow(a, b, &bytes))
                return SIZE_MAX;
        if (check_add_overflow(bytes, c, &bytes))
                return SIZE_MAX;
index bcf909d..9ec3544 100644 (file)
@@ -333,6 +333,19 @@ static inline struct page *grab_cache_page_nowait(struct address_space *mapping,
                        mapping_gfp_mask(mapping));
 }
 
+static inline struct page *find_subpage(struct page *page, pgoff_t offset)
+{
+       unsigned long mask;
+
+       if (PageHuge(page))
+               return page;
+
+       VM_BUG_ON_PAGE(PageTail(page), page);
+
+       mask = (1UL << compound_order(page)) - 1;
+       return page + (offset & mask);
+}
+
 struct page *find_get_entry(struct address_space *mapping, pgoff_t offset);
 struct page *find_lock_entry(struct address_space *mapping, pgoff_t offset);
 unsigned find_get_entries(struct address_space *mapping, pgoff_t start,
@@ -360,9 +373,6 @@ static inline unsigned find_get_pages_tag(struct address_space *mapping,
        return find_get_pages_range_tag(mapping, index, (pgoff_t)-1, tag,
                                        nr_pages, pages);
 }
-unsigned find_get_entries_tag(struct address_space *mapping, pgoff_t start,
-                       xa_mark_t tag, unsigned int nr_entries,
-                       struct page **entries, pgoff_t *indices);
 
 struct page *grab_cache_page_write_begin(struct address_space *mapping,
                        pgoff_t index, unsigned flags);
@@ -527,15 +537,7 @@ static inline int wait_on_page_locked_killable(struct page *page)
 
 extern void put_and_wait_on_page_locked(struct page *page);
 
-/* 
- * Wait for a page to complete writeback
- */
-static inline void wait_on_page_writeback(struct page *page)
-{
-       if (PageWriteback(page))
-               wait_on_page_bit(page, PG_writeback);
-}
-
+void wait_on_page_writeback(struct page *page);
 extern void end_page_writeback(struct page *page);
 void wait_for_stable_page(struct page *page);
 
index 29efa09..a73164c 100644 (file)
@@ -56,6 +56,7 @@ extern struct pci_ecam_ops thunder_pem_ecam_ops; /* Cavium ThunderX 1.x & 2.x */
 extern struct pci_ecam_ops pci_thunder_ecam_ops; /* Cavium ThunderX 1.x */
 extern struct pci_ecam_ops xgene_v1_pcie_ecam_ops; /* APM X-Gene PCIe v1 */
 extern struct pci_ecam_ops xgene_v2_pcie_ecam_ops; /* APM X-Gene PCIe v2.x */
+extern struct pci_ecam_ops al_pcie_ops; /* Amazon Annapurna Labs PCIe */
 #endif
 
 #ifdef CONFIG_PCI_HOST_COMMON
index c3ffa39..f641bad 100644 (file)
@@ -109,6 +109,7 @@ struct pci_epc {
  * @reserved_bar: bitmap to indicate reserved BAR unavailable to function driver
  * @bar_fixed_64bit: bitmap to indicate fixed 64bit BARs
  * @bar_fixed_size: Array specifying the size supported by each BAR
+ * @align: alignment size required for BAR buffer allocation
  */
 struct pci_epc_features {
        unsigned int    linkup_notifier : 1;
@@ -117,6 +118,7 @@ struct pci_epc_features {
        u8      reserved_bar;
        u8      bar_fixed_64bit;
        u64     bar_fixed_size[BAR_5 + 1];
+       size_t  align;
 };
 
 #define to_pci_epc(device) container_of((device), struct pci_epc, dev)
index ec02f58..2d6f075 100644 (file)
@@ -149,7 +149,8 @@ void pci_epf_destroy(struct pci_epf *epf);
 int __pci_epf_register_driver(struct pci_epf_driver *driver,
                              struct module *owner);
 void pci_epf_unregister_driver(struct pci_epf_driver *driver);
-void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar);
+void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
+                         size_t align);
 void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar);
 int pci_epf_bind(struct pci_epf *epf);
 void pci_epf_unbind(struct pci_epf *epf);
index 1250806..4a5a84d 100644 (file)
@@ -348,6 +348,8 @@ struct pci_dev {
        unsigned int    hotplug_user_indicators:1; /* SlotCtl indicators
                                                      controlled exclusively by
                                                      user sysfs */
+       unsigned int    clear_retrain_link:1;   /* Need to clear Retrain Link
+                                                  bit manually */
        unsigned int    d3_delay;       /* D3->D0 transition time in ms */
        unsigned int    d3cold_delay;   /* D3cold->D0 transition time in ms */
 
@@ -490,6 +492,7 @@ struct pci_host_bridge {
        void            *sysdata;
        int             busnr;
        struct list_head windows;       /* resource_entry */
+       struct list_head dma_ranges;    /* dma ranges resource list */
        u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* Platform IRQ swizzler */
        int (*map_irq)(const struct pci_dev *, u8, u8);
        void (*release_fn)(struct pci_host_bridge *);
@@ -596,6 +599,11 @@ struct pci_bus {
 
 #define to_pci_bus(n)  container_of(n, struct pci_bus, dev)
 
+static inline u16 pci_dev_id(struct pci_dev *dev)
+{
+       return PCI_DEVID(dev->bus->number, dev->devfn);
+}
+
 /*
  * Returns true if the PCI bus is root (behind host-PCI bridge),
  * false otherwise
@@ -1233,7 +1241,6 @@ int __must_check pci_request_regions(struct pci_dev *, const char *);
 int __must_check pci_request_regions_exclusive(struct pci_dev *, const char *);
 void pci_release_regions(struct pci_dev *);
 int __must_check pci_request_region(struct pci_dev *, int, const char *);
-int __must_check pci_request_region_exclusive(struct pci_dev *, int, const char *);
 void pci_release_region(struct pci_dev *, int);
 int pci_request_selected_regions(struct pci_dev *, int, const char *);
 int pci_request_selected_regions_exclusive(struct pci_dev *, int, const char *);
index 7acc9f9..f694eb2 100644 (file)
@@ -124,26 +124,72 @@ struct hpp_type2 {
        u32 sec_unc_err_mask_or;
 };
 
-struct hotplug_params {
-       struct hpp_type0 *t0;           /* Type0: NULL if not available */
-       struct hpp_type1 *t1;           /* Type1: NULL if not available */
-       struct hpp_type2 *t2;           /* Type2: NULL if not available */
-       struct hpp_type0 type0_data;
-       struct hpp_type1 type1_data;
-       struct hpp_type2 type2_data;
+/*
+ * _HPX PCI Express Setting Record (Type 3)
+ */
+struct hpx_type3 {
+       u16 device_type;
+       u16 function_type;
+       u16 config_space_location;
+       u16 pci_exp_cap_id;
+       u16 pci_exp_cap_ver;
+       u16 pci_exp_vendor_id;
+       u16 dvsec_id;
+       u16 dvsec_rev;
+       u16 match_offset;
+       u32 match_mask_and;
+       u32 match_value;
+       u16 reg_offset;
+       u32 reg_mask_and;
+       u32 reg_mask_or;
+};
+
+struct hotplug_program_ops {
+       void (*program_type0)(struct pci_dev *dev, struct hpp_type0 *hpp);
+       void (*program_type1)(struct pci_dev *dev, struct hpp_type1 *hpp);
+       void (*program_type2)(struct pci_dev *dev, struct hpp_type2 *hpp);
+       void (*program_type3)(struct pci_dev *dev, struct hpx_type3 *hpp);
+};
+
+enum hpx_type3_dev_type {
+       HPX_TYPE_ENDPOINT       = BIT(0),
+       HPX_TYPE_LEG_END        = BIT(1),
+       HPX_TYPE_RC_END         = BIT(2),
+       HPX_TYPE_RC_EC          = BIT(3),
+       HPX_TYPE_ROOT_PORT      = BIT(4),
+       HPX_TYPE_UPSTREAM       = BIT(5),
+       HPX_TYPE_DOWNSTREAM     = BIT(6),
+       HPX_TYPE_PCI_BRIDGE     = BIT(7),
+       HPX_TYPE_PCIE_BRIDGE    = BIT(8),
+};
+
+enum hpx_type3_fn_type {
+       HPX_FN_NORMAL           = BIT(0),
+       HPX_FN_SRIOV_PHYS       = BIT(1),
+       HPX_FN_SRIOV_VIRT       = BIT(2),
+};
+
+enum hpx_type3_cfg_loc {
+       HPX_CFG_PCICFG          = 0,
+       HPX_CFG_PCIE_CAP        = 1,
+       HPX_CFG_PCIE_CAP_EXT    = 2,
+       HPX_CFG_VEND_CAP        = 3,
+       HPX_CFG_DVSEC           = 4,
+       HPX_CFG_MAX,
 };
 
 #ifdef CONFIG_ACPI
 #include <linux/acpi.h>
-int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp);
+int pci_acpi_program_hp_params(struct pci_dev *dev,
+                              const struct hotplug_program_ops *hp_ops);
 bool pciehp_is_native(struct pci_dev *bridge);
 int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge);
 bool shpchp_is_native(struct pci_dev *bridge);
 int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle);
 int acpi_pci_detect_ejectable(acpi_handle handle);
 #else
-static inline int pci_get_hp_params(struct pci_dev *dev,
-                                   struct hotplug_params *hpp)
+static inline int pci_acpi_program_hp_params(struct pci_dev *dev,
+                                   const struct hotplug_program_ops *hp_ops)
 {
        return -ENODEV;
 }
index 70b7123..9909dc0 100644 (file)
 #define PCPU_MIN_ALLOC_SHIFT           2
 #define PCPU_MIN_ALLOC_SIZE            (1 << PCPU_MIN_ALLOC_SHIFT)
 
-/* number of bits per page, used to trigger a scan if blocks are > PAGE_SIZE */
-#define PCPU_BITS_PER_PAGE             (PAGE_SIZE >> PCPU_MIN_ALLOC_SHIFT)
-
 /*
- * This determines the size of each metadata block.  There are several subtle
- * constraints around this constant.  The reserved region must be a multiple of
- * PCPU_BITMAP_BLOCK_SIZE.  Additionally, PCPU_BITMAP_BLOCK_SIZE must be a
- * multiple of PAGE_SIZE or PAGE_SIZE must be a multiple of
- * PCPU_BITMAP_BLOCK_SIZE to align with the populated page map. The unit_size
- * also has to be a multiple of PCPU_BITMAP_BLOCK_SIZE to ensure full blocks.
+ * The PCPU_BITMAP_BLOCK_SIZE must be the same size as PAGE_SIZE as the
+ * updating of hints is used to manage the nr_empty_pop_pages in both
+ * the chunk and globally.
  */
 #define PCPU_BITMAP_BLOCK_SIZE         PAGE_SIZE
 #define PCPU_BITMAP_BLOCK_BITS         (PCPU_BITMAP_BLOCK_SIZE >>      \
diff --git a/include/linux/platform_data/eth-ep93xx.h b/include/linux/platform_data/eth-ep93xx.h
new file mode 100644 (file)
index 0000000..8eef637
--- /dev/null
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_PLATFORM_DATA_ETH_EP93XX
+#define _LINUX_PLATFORM_DATA_ETH_EP93XX
+
+struct ep93xx_eth_data {
+       unsigned char   dev_addr[6];
+       unsigned char   phy_id;
+};
+
+#endif
index 0e36818..3054fce 100644 (file)
@@ -9,8 +9,7 @@ struct matrix_keymap_data;
 #define EP93XX_KEYPAD_DIAG_MODE                (1<<1)  /* diagnostic mode */
 #define EP93XX_KEYPAD_BACK_DRIVE       (1<<2)  /* back driving mode */
 #define EP93XX_KEYPAD_TEST_MODE                (1<<3)  /* scan only column 0 */
-#define EP93XX_KEYPAD_KDIV             (1<<4)  /* 1/4 clock or 1/16 clock */
-#define EP93XX_KEYPAD_AUTOREPEAT       (1<<5)  /* enable key autorepeat */
+#define EP93XX_KEYPAD_AUTOREPEAT       (1<<4)  /* enable key autorepeat */
 
 /**
  * struct ep93xx_keypad_platform_data - platform specific device structure
@@ -24,6 +23,7 @@ struct ep93xx_keypad_platform_data {
        unsigned int    debounce;
        unsigned int    prescale;
        unsigned int    flags;
+       unsigned int    clk_rate;
 };
 
 #define EP93XX_MATRIX_ROWS             (8)
index 7538e38..762e689 100644 (file)
@@ -38,9 +38,11 @@ enum lm3630a_ledb_ctrl {
 
 #define LM3630A_MAX_BRIGHTNESS 255
 /*
+ *@leda_label    : optional led a label.
  *@leda_init_brt : led a init brightness. 4~255
  *@leda_max_brt  : led a max brightness.  4~255
  *@leda_ctrl     : led a disable, enable linear, enable exponential
+ *@ledb_label    : optional led b label.
  *@ledb_init_brt : led b init brightness. 4~255
  *@ledb_max_brt  : led b max brightness.  4~255
  *@ledb_ctrl     : led b disable, enable linear, enable exponential
@@ -50,10 +52,12 @@ enum lm3630a_ledb_ctrl {
 struct lm3630a_platform_data {
 
        /* led a config.  */
+       const char *leda_label;
        int leda_init_brt;
        int leda_max_brt;
        enum lm3630a_leda_ctrl leda_ctrl;
        /* led b config. */
+       const char *ledb_label;
        int ledb_init_brt;
        int ledb_max_brt;
        enum lm3630a_ledb_ctrl ledb_ctrl;
index fbf5ed7..dd59719 100644 (file)
@@ -51,6 +51,11 @@ struct am33xx_pm_platform_data {
                               unsigned long args);
        struct  am33xx_pm_sram_addr *(*get_sram_addrs)(void);
        void __iomem *(*get_rtc_base_addr)(void);
+       void (*save_context)(void);
+       void (*restore_context)(void);
+       void (*prepare_rtc_suspend)(void);
+       void (*prepare_rtc_resume)(void);
+       int (*check_off_mode_enable)(void);
 };
 
 struct am33xx_pm_sram_data {
index 1ea3aab..9256c03 100644 (file)
@@ -46,8 +46,13 @@ struct sysc_regbits {
        s8 emufree_shift;
 };
 
-#define SYSC_QUIRK_LEGACY_IDLE         BIT(8)
-#define SYSC_QUIRK_RESET_STATUS                BIT(7)
+#define SYSC_QUIRK_SWSUP_MSTANDBY      BIT(13)
+#define SYSC_QUIRK_SWSUP_SIDLE_ACT     BIT(12)
+#define SYSC_QUIRK_SWSUP_SIDLE         BIT(11)
+#define SYSC_QUIRK_EXT_OPT_CLOCK       BIT(10)
+#define SYSC_QUIRK_LEGACY_IDLE         BIT(9)
+#define SYSC_QUIRK_RESET_STATUS                BIT(8)
+#define SYSC_QUIRK_NO_IDLE             BIT(7)
 #define SYSC_QUIRK_NO_IDLE_ON_INIT     BIT(6)
 #define SYSC_QUIRK_NO_RESET_ON_INIT    BIT(5)
 #define SYSC_QUIRK_OPT_CLKS_NEEDED     BIT(4)
diff --git a/include/linux/platform_data/timer-ixp4xx.h b/include/linux/platform_data/timer-ixp4xx.h
new file mode 100644 (file)
index 0000000..ee92ae7
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __TIMER_IXP4XX_H
+#define __TIMER_IXP4XX_H
+
+#include <linux/ioport.h>
+
+void __init ixp4xx_timer_setup(resource_size_t timerbase,
+                              int timer_irq,
+                              unsigned int timer_freq);
+
+#endif
index 9788360..9365df5 100644 (file)
@@ -231,7 +231,7 @@ static inline int plist_node_empty(const struct plist_node *node)
  * @type:      the type of the struct this is embedded in
  * @member:    the name of the list_head within the struct
  */
-#ifdef CONFIG_DEBUG_PI_LIST
+#ifdef CONFIG_DEBUG_PLIST
 # define plist_first_entry(head, type, member) \
 ({ \
        WARN_ON(plist_head_empty(head)); \
@@ -248,7 +248,7 @@ static inline int plist_node_empty(const struct plist_node *node)
  * @type:      the type of the struct this is embedded in
  * @member:    the name of the list_head within the struct
  */
-#ifdef CONFIG_DEBUG_PI_LIST
+#ifdef CONFIG_DEBUG_PLIST
 # define plist_last_entry(head, type, member)  \
 ({ \
        WARN_ON(plist_head_empty(head)); \
index 0e8e356..b21f35f 100644 (file)
  *                             driver must then comply with the so called,
  *                             last-man-standing algorithm, for the CPUs in the
  *                             PM domain.
+ *
+ * GENPD_FLAG_RPM_ALWAYS_ON:   Instructs genpd to always keep the PM domain
+ *                             powered on except for system suspend.
  */
 #define GENPD_FLAG_PM_CLK       (1U << 0)
 #define GENPD_FLAG_IRQ_SAFE     (1U << 1)
 #define GENPD_FLAG_ALWAYS_ON    (1U << 2)
 #define GENPD_FLAG_ACTIVE_WAKEUP (1U << 3)
 #define GENPD_FLAG_CPU_DOMAIN   (1U << 4)
+#define GENPD_FLAG_RPM_ALWAYS_ON (1U << 5)
 
 enum gpd_status {
        GPD_STATE_ACTIVE = 0,   /* PM domain is active */
index 7e0fdcf..1cdc32b 100644 (file)
 extern struct ctl_table epoll_table[]; /* for sysctl */
 /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating
    additional memory. */
+#ifdef __clang__
+#define MAX_STACK_ALLOC 768
+#else
 #define MAX_STACK_ALLOC 832
+#endif
 #define FRONTEND_STACK_ALLOC   256
 #define SELECT_STACK_ALLOC     FRONTEND_STACK_ALLOC
 #define POLL_STACK_ALLOC       FRONTEND_STACK_ALLOC
index 2f9c201..d9c0c09 100644 (file)
@@ -40,11 +40,15 @@ enum {
        POWER_SUPPLY_STATUS_FULL,
 };
 
+/* What algorithm is the charger using? */
 enum {
        POWER_SUPPLY_CHARGE_TYPE_UNKNOWN = 0,
        POWER_SUPPLY_CHARGE_TYPE_NONE,
-       POWER_SUPPLY_CHARGE_TYPE_TRICKLE,
-       POWER_SUPPLY_CHARGE_TYPE_FAST,
+       POWER_SUPPLY_CHARGE_TYPE_TRICKLE,       /* slow speed */
+       POWER_SUPPLY_CHARGE_TYPE_FAST,          /* fast speed */
+       POWER_SUPPLY_CHARGE_TYPE_STANDARD,      /* normal speed */
+       POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE,      /* dynamically adjusted speed */
+       POWER_SUPPLY_CHARGE_TYPE_CUSTOM,        /* use CHARGE_CONTROL_* props */
 };
 
 enum {
@@ -57,6 +61,7 @@ enum {
        POWER_SUPPLY_HEALTH_COLD,
        POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE,
        POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE,
+       POWER_SUPPLY_HEALTH_OVERCURRENT,
 };
 
 enum {
@@ -121,6 +126,8 @@ enum power_supply_property {
        POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
        POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
        POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
+       POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD, /* in percents! */
+       POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD, /* in percents! */
        POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
        POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
        POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
index 56f35dd..44171e6 100644 (file)
 #define _PPS_GPIO_H
 
 struct pps_gpio_platform_data {
+       struct gpio_desc *gpio_pin;
+       struct gpio_desc *echo_pin;
        bool assert_falling_edge;
        bool capture_clear;
-       unsigned int gpio_pin;
-       const char *gpio_label;
+       unsigned int echo_active_ms;
 };
 
 #endif /* _PPS_GPIO_H */
index 84ea4d0..cefd374 100644 (file)
@@ -82,6 +82,8 @@ static inline void console_verbose(void)
 extern char devkmsg_log_str[];
 struct ctl_table;
 
+extern int suppress_printk;
+
 struct va_format {
        const char *fmt;
        va_list *va;
index 7006008..7b3de73 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/jump_label.h>
 #include <linux/psi_types.h>
 #include <linux/sched.h>
+#include <linux/poll.h>
 
 struct seq_file;
 struct css_set;
@@ -11,6 +12,7 @@ struct css_set;
 #ifdef CONFIG_PSI
 
 extern struct static_key_false psi_disabled;
+extern struct psi_group psi_system;
 
 void psi_init(void);
 
@@ -26,6 +28,13 @@ int psi_show(struct seq_file *s, struct psi_group *group, enum psi_res res);
 int psi_cgroup_alloc(struct cgroup *cgrp);
 void psi_cgroup_free(struct cgroup *cgrp);
 void cgroup_move_task(struct task_struct *p, struct css_set *to);
+
+struct psi_trigger *psi_trigger_create(struct psi_group *group,
+                       char *buf, size_t nbytes, enum psi_res res);
+void psi_trigger_replace(void **trigger_ptr, struct psi_trigger *t);
+
+__poll_t psi_trigger_poll(void **trigger_ptr, struct file *file,
+                       poll_table *wait);
 #endif
 
 #else /* CONFIG_PSI */
index 2cf422d..07aaf9b 100644 (file)
@@ -1,8 +1,11 @@
 #ifndef _LINUX_PSI_TYPES_H
 #define _LINUX_PSI_TYPES_H
 
+#include <linux/kthread.h>
 #include <linux/seqlock.h>
 #include <linux/types.h>
+#include <linux/kref.h>
+#include <linux/wait.h>
 
 #ifdef CONFIG_PSI
 
@@ -11,7 +14,7 @@ enum psi_task_count {
        NR_IOWAIT,
        NR_MEMSTALL,
        NR_RUNNING,
-       NR_PSI_TASK_COUNTS,
+       NR_PSI_TASK_COUNTS = 3,
 };
 
 /* Task state bitmasks */
@@ -24,7 +27,7 @@ enum psi_res {
        PSI_IO,
        PSI_MEM,
        PSI_CPU,
-       NR_PSI_RESOURCES,
+       NR_PSI_RESOURCES = 3,
 };
 
 /*
@@ -41,7 +44,13 @@ enum psi_states {
        PSI_CPU_SOME,
        /* Only per-CPU, to weigh the CPU in the global average: */
        PSI_NONIDLE,
-       NR_PSI_STATES,
+       NR_PSI_STATES = 6,
+};
+
+enum psi_aggregators {
+       PSI_AVGS = 0,
+       PSI_POLL,
+       NR_PSI_AGGREGATORS,
 };
 
 struct psi_group_cpu {
@@ -53,6 +62,9 @@ struct psi_group_cpu {
        /* States of the tasks belonging to this group */
        unsigned int tasks[NR_PSI_TASK_COUNTS];
 
+       /* Aggregate pressure state derived from the tasks */
+       u32 state_mask;
+
        /* Period time sampling buckets for each state of interest (ns) */
        u32 times[NR_PSI_STATES];
 
@@ -62,25 +74,94 @@ struct psi_group_cpu {
        /* 2nd cacheline updated by the aggregator */
 
        /* Delta detection against the sampling buckets */
-       u32 times_prev[NR_PSI_STATES] ____cacheline_aligned_in_smp;
+       u32 times_prev[NR_PSI_AGGREGATORS][NR_PSI_STATES]
+                       ____cacheline_aligned_in_smp;
+};
+
+/* PSI growth tracking window */
+struct psi_window {
+       /* Window size in ns */
+       u64 size;
+
+       /* Start time of the current window in ns */
+       u64 start_time;
+
+       /* Value at the start of the window */
+       u64 start_value;
+
+       /* Value growth in the previous window */
+       u64 prev_growth;
+};
+
+struct psi_trigger {
+       /* PSI state being monitored by the trigger */
+       enum psi_states state;
+
+       /* User-spacified threshold in ns */
+       u64 threshold;
+
+       /* List node inside triggers list */
+       struct list_head node;
+
+       /* Backpointer needed during trigger destruction */
+       struct psi_group *group;
+
+       /* Wait queue for polling */
+       wait_queue_head_t event_wait;
+
+       /* Pending event flag */
+       int event;
+
+       /* Tracking window */
+       struct psi_window win;
+
+       /*
+        * Time last event was generated. Used for rate-limiting
+        * events to one per window
+        */
+       u64 last_event_time;
+
+       /* Refcounting to prevent premature destruction */
+       struct kref refcount;
 };
 
 struct psi_group {
-       /* Protects data updated during an aggregation */
-       struct mutex stat_lock;
+       /* Protects data used by the aggregator */
+       struct mutex avgs_lock;
 
        /* Per-cpu task state & time tracking */
        struct psi_group_cpu __percpu *pcpu;
 
-       /* Periodic aggregation state */
-       u64 total_prev[NR_PSI_STATES - 1];
-       u64 last_update;
-       u64 next_update;
-       struct delayed_work clock_work;
+       /* Running pressure averages */
+       u64 avg_total[NR_PSI_STATES - 1];
+       u64 avg_last_update;
+       u64 avg_next_update;
+
+       /* Aggregator work control */
+       struct delayed_work avgs_work;
 
        /* Total stall times and sampled pressure averages */
-       u64 total[NR_PSI_STATES - 1];
+       u64 total[NR_PSI_AGGREGATORS][NR_PSI_STATES - 1];
        unsigned long avg[NR_PSI_STATES - 1][3];
+
+       /* Monitor work control */
+       atomic_t poll_scheduled;
+       struct kthread_worker __rcu *poll_kworker;
+       struct kthread_delayed_work poll_work;
+
+       /* Protects data used by the monitor */
+       struct mutex trigger_lock;
+
+       /* Configured polling triggers */
+       struct list_head triggers;
+       u32 nr_triggers[NR_PSI_STATES - 1];
+       u32 poll_states;
+       u64 poll_min_period;
+
+       /* Total stall times at the start of monitor activation */
+       u64 polling_total[NR_PSI_STATES - 1];
+       u64 polling_next_update;
+       u64 polling_until;
 };
 
 #else /* CONFIG_PSI */
index 3bcd67f..dd46494 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  */
index e63799a..3734cd8 100644 (file)
@@ -14,6 +14,7 @@ struct device;
 #define SYS_POWER_OFF  0x0003  /* Notify of system power off */
 
 enum reboot_mode {
+       REBOOT_UNDEFINED = -1,
        REBOOT_COLD = 0,
        REBOOT_WARM,
        REBOOT_HARD,
@@ -21,6 +22,7 @@ enum reboot_mode {
        REBOOT_GPIO,
 };
 extern enum reboot_mode reboot_mode;
+extern enum reboot_mode panic_reboot_mode;
 
 enum reboot_type {
        BOOT_TRIPLE     = 't',
index 95d555c..e7793fc 100644 (file)
@@ -2,6 +2,8 @@
 #ifndef _LINUX_RESET_H_
 #define _LINUX_RESET_H_
 
+#include <linux/err.h>
+#include <linux/errno.h>
 #include <linux/types.h>
 
 struct device;
diff --git a/include/linux/rtc/rtc-omap.h b/include/linux/rtc/rtc-omap.h
new file mode 100644 (file)
index 0000000..9f03a32
--- /dev/null
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _LINUX_RTCOMAP_H_
+#define _LINUX_RTCOMAP_H_
+
+int omap_rtc_power_off_program(struct device *dev);
+#endif /* _LINUX_RTCOMAP_H_ */
index a2cd158..1183741 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/latencytop.h>
 #include <linux/sched/prio.h>
 #include <linux/signal_types.h>
-#include <linux/psi_types.h>
 #include <linux/mm_types_task.h>
 #include <linux/task_io_accounting.h>
 #include <linux/rseq.h>
index e412c09..38a0f07 100644 (file)
@@ -271,17 +271,18 @@ static inline int signal_group_exit(const struct signal_struct *sig)
 extern void flush_signals(struct task_struct *);
 extern void ignore_signals(struct task_struct *);
 extern void flush_signal_handlers(struct task_struct *, int force_default);
-extern int dequeue_signal(struct task_struct *tsk, sigset_t *mask, kernel_siginfo_t *info);
+extern int dequeue_signal(struct task_struct *task,
+                         sigset_t *mask, kernel_siginfo_t *info);
 
 static inline int kernel_dequeue_signal(void)
 {
-       struct task_struct *tsk = current;
+       struct task_struct *task = current;
        kernel_siginfo_t __info;
        int ret;
 
-       spin_lock_irq(&tsk->sighand->siglock);
-       ret = dequeue_signal(tsk, &tsk->blocked, &__info);
-       spin_unlock_irq(&tsk->sighand->siglock);
+       spin_lock_irq(&task->sighand->siglock);
+       ret = dequeue_signal(task, &task->blocked, &__info);
+       spin_unlock_irq(&task->sighand->siglock);
 
        return ret;
 }
@@ -419,18 +420,18 @@ static inline void set_restore_sigmask(void)
        WARN_ON(!test_thread_flag(TIF_SIGPENDING));
 }
 
-static inline void clear_tsk_restore_sigmask(struct task_struct *tsk)
+static inline void clear_tsk_restore_sigmask(struct task_struct *task)
 {
-       clear_tsk_thread_flag(tsk, TIF_RESTORE_SIGMASK);
+       clear_tsk_thread_flag(task, TIF_RESTORE_SIGMASK);
 }
 
 static inline void clear_restore_sigmask(void)
 {
        clear_thread_flag(TIF_RESTORE_SIGMASK);
 }
-static inline bool test_tsk_restore_sigmask(struct task_struct *tsk)
+static inline bool test_tsk_restore_sigmask(struct task_struct *task)
 {
-       return test_tsk_thread_flag(tsk, TIF_RESTORE_SIGMASK);
+       return test_tsk_thread_flag(task, TIF_RESTORE_SIGMASK);
 }
 static inline bool test_restore_sigmask(void)
 {
@@ -449,9 +450,9 @@ static inline void set_restore_sigmask(void)
        current->restore_sigmask = true;
        WARN_ON(!test_thread_flag(TIF_SIGPENDING));
 }
-static inline void clear_tsk_restore_sigmask(struct task_struct *tsk)
+static inline void clear_tsk_restore_sigmask(struct task_struct *task)
 {
-       tsk->restore_sigmask = false;
+       task->restore_sigmask = false;
 }
 static inline void clear_restore_sigmask(void)
 {
@@ -461,9 +462,9 @@ static inline bool test_restore_sigmask(void)
 {
        return current->restore_sigmask;
 }
-static inline bool test_tsk_restore_sigmask(struct task_struct *tsk)
+static inline bool test_tsk_restore_sigmask(struct task_struct *task)
 {
-       return tsk->restore_sigmask;
+       return task->restore_sigmask;
 }
 static inline bool test_and_clear_restore_sigmask(void)
 {
@@ -617,9 +618,9 @@ static inline struct pid *task_session(struct task_struct *task)
        return task->signal->pids[PIDTYPE_SID];
 }
 
-static inline int get_nr_threads(struct task_struct *tsk)
+static inline int get_nr_threads(struct task_struct *task)
 {
-       return tsk->signal->nr_threads;
+       return task->signal->nr_threads;
 }
 
 static inline bool thread_group_leader(struct task_struct *p)
@@ -658,35 +659,35 @@ static inline int thread_group_empty(struct task_struct *p)
 #define delay_group_leader(p) \
                (thread_group_leader(p) && !thread_group_empty(p))
 
-extern struct sighand_struct *__lock_task_sighand(struct task_struct *tsk,
+extern struct sighand_struct *__lock_task_sighand(struct task_struct *task,
                                                        unsigned long *flags);
 
-static inline struct sighand_struct *lock_task_sighand(struct task_struct *tsk,
+static inline struct sighand_struct *lock_task_sighand(struct task_struct *task,
                                                       unsigned long *flags)
 {
        struct sighand_struct *ret;
 
-       ret = __lock_task_sighand(tsk, flags);
-       (void)__cond_lock(&tsk->sighand->siglock, ret);
+       ret = __lock_task_sighand(task, flags);
+       (void)__cond_lock(&task->sighand->siglock, ret);
        return ret;
 }
 
-static inline void unlock_task_sighand(struct task_struct *tsk,
+static inline void unlock_task_sighand(struct task_struct *task,
                                                unsigned long *flags)
 {
-       spin_unlock_irqrestore(&tsk->sighand->siglock, *flags);
+       spin_unlock_irqrestore(&task->sighand->siglock, *flags);
 }
 
-static inline unsigned long task_rlimit(const struct task_struct *tsk,
+static inline unsigned long task_rlimit(const struct task_struct *task,
                unsigned int limit)
 {
-       return READ_ONCE(tsk->signal->rlim[limit].rlim_cur);
+       return READ_ONCE(task->signal->rlim[limit].rlim_cur);
 }
 
-static inline unsigned long task_rlimit_max(const struct task_struct *tsk,
+static inline unsigned long task_rlimit_max(const struct task_struct *task,
                unsigned int limit)
 {
-       return READ_ONCE(tsk->signal->rlim[limit].rlim_max);
+       return READ_ONCE(task->signal->rlim[limit].rlim_max);
 }
 
 static inline unsigned long rlimit(unsigned int limit)
index 9a5eafb..abc7de7 100644 (file)
@@ -61,9 +61,6 @@ struct kmem_cache {
        atomic_t allocmiss;
        atomic_t freehit;
        atomic_t freemiss;
-#ifdef CONFIG_DEBUG_SLAB_LEAK
-       atomic_t store_user_clean;
-#endif
 
        /*
         * If debugging is enabled, then the allocator can add additional
diff --git a/include/linux/soc/cirrus/ep93xx.h b/include/linux/soc/cirrus/ep93xx.h
new file mode 100644 (file)
index 0000000..56fbe2d
--- /dev/null
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SOC_EP93XX_H
+#define _SOC_EP93XX_H
+
+struct platform_device;
+
+#define EP93XX_CHIP_REV_D0     3
+#define EP93XX_CHIP_REV_D1     4
+#define EP93XX_CHIP_REV_E0     5
+#define EP93XX_CHIP_REV_E1     6
+#define EP93XX_CHIP_REV_E2     7
+
+#ifdef CONFIG_ARCH_EP93XX
+int ep93xx_pwm_acquire_gpio(struct platform_device *pdev);
+void ep93xx_pwm_release_gpio(struct platform_device *pdev);
+int ep93xx_ide_acquire_gpio(struct platform_device *pdev);
+void ep93xx_ide_release_gpio(struct platform_device *pdev);
+int ep93xx_keypad_acquire_gpio(struct platform_device *pdev);
+void ep93xx_keypad_release_gpio(struct platform_device *pdev);
+int ep93xx_i2s_acquire(void);
+void ep93xx_i2s_release(void);
+unsigned int ep93xx_chip_revision(void);
+
+#else
+static inline int ep93xx_pwm_acquire_gpio(struct platform_device *pdev) { return 0; }
+static inline void ep93xx_pwm_release_gpio(struct platform_device *pdev) {}
+static inline int ep93xx_ide_acquire_gpio(struct platform_device *pdev) { return 0; }
+static inline void ep93xx_ide_release_gpio(struct platform_device *pdev) {}
+static inline int ep93xx_keypad_acquire_gpio(struct platform_device *pdev) { return 0; }
+static inline void ep93xx_keypad_release_gpio(struct platform_device *pdev) {}
+static inline int ep93xx_i2s_acquire(void) { return 0; }
+static inline void ep93xx_i2s_release(void) {}
+static inline unsigned int ep93xx_chip_revision(void) { return 0; }
+
+#endif
+
+#endif
diff --git a/include/linux/soc/ixp4xx/npe.h b/include/linux/soc/ixp4xx/npe.h
new file mode 100644 (file)
index 0000000..2a91f46
--- /dev/null
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __IXP4XX_NPE_H
+#define __IXP4XX_NPE_H
+
+#include <linux/kernel.h>
+
+extern const char *npe_names[];
+
+struct npe_regs {
+       u32 exec_addr, exec_data, exec_status_cmd, exec_count;
+       u32 action_points[4];
+       u32 watchpoint_fifo, watch_count;
+       u32 profile_count;
+       u32 messaging_status, messaging_control;
+       u32 mailbox_status, /*messaging_*/ in_out_fifo;
+};
+
+struct npe {
+       struct npe_regs __iomem *regs;
+       int id;
+       int valid;
+};
+
+
+static inline const char *npe_name(struct npe *npe)
+{
+       return npe_names[npe->id];
+}
+
+int npe_running(struct npe *npe);
+int npe_send_message(struct npe *npe, const void *msg, const char *what);
+int npe_recv_message(struct npe *npe, void *msg, const char *what);
+int npe_send_recv_message(struct npe *npe, void *msg, const char *what);
+int npe_load_firmware(struct npe *npe, const char *name, struct device *dev);
+struct npe *npe_request(unsigned id);
+void npe_release(struct npe *npe);
+
+#endif /* __IXP4XX_NPE_H */
diff --git a/include/linux/soc/ixp4xx/qmgr.h b/include/linux/soc/ixp4xx/qmgr.h
new file mode 100644 (file)
index 0000000..bed8ee9
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+#ifndef IXP4XX_QMGR_H
+#define IXP4XX_QMGR_H
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+
+#define DEBUG_QMGR     0
+
+#define HALF_QUEUES    32
+#define QUEUES         64
+#define MAX_QUEUE_LENGTH 4     /* in dwords */
+
+#define QUEUE_STAT1_EMPTY              1 /* queue status bits */
+#define QUEUE_STAT1_NEARLY_EMPTY       2
+#define QUEUE_STAT1_NEARLY_FULL                4
+#define QUEUE_STAT1_FULL               8
+#define QUEUE_STAT2_UNDERFLOW          1
+#define QUEUE_STAT2_OVERFLOW           2
+
+#define QUEUE_WATERMARK_0_ENTRIES      0
+#define QUEUE_WATERMARK_1_ENTRY                1
+#define QUEUE_WATERMARK_2_ENTRIES      2
+#define QUEUE_WATERMARK_4_ENTRIES      3
+#define QUEUE_WATERMARK_8_ENTRIES      4
+#define QUEUE_WATERMARK_16_ENTRIES     5
+#define QUEUE_WATERMARK_32_ENTRIES     6
+#define QUEUE_WATERMARK_64_ENTRIES     7
+
+/* queue interrupt request conditions */
+#define QUEUE_IRQ_SRC_EMPTY            0
+#define QUEUE_IRQ_SRC_NEARLY_EMPTY     1
+#define QUEUE_IRQ_SRC_NEARLY_FULL      2
+#define QUEUE_IRQ_SRC_FULL             3
+#define QUEUE_IRQ_SRC_NOT_EMPTY                4
+#define QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY 5
+#define QUEUE_IRQ_SRC_NOT_NEARLY_FULL  6
+#define QUEUE_IRQ_SRC_NOT_FULL         7
+
+struct qmgr_regs {
+       u32 acc[QUEUES][MAX_QUEUE_LENGTH]; /* 0x000 - 0x3FF */
+       u32 stat1[4];           /* 0x400 - 0x40F */
+       u32 stat2[2];           /* 0x410 - 0x417 */
+       u32 statne_h;           /* 0x418 - queue nearly empty */
+       u32 statf_h;            /* 0x41C - queue full */
+       u32 irqsrc[4];          /* 0x420 - 0x42F IRC source */
+       u32 irqen[2];           /* 0x430 - 0x437 IRQ enabled */
+       u32 irqstat[2];         /* 0x438 - 0x43F - IRQ access only */
+       u32 reserved[1776];
+       u32 sram[2048];         /* 0x2000 - 0x3FFF - config and buffer */
+};
+
+void qmgr_put_entry(unsigned int queue, u32 val);
+u32 qmgr_get_entry(unsigned int queue);
+int qmgr_stat_empty(unsigned int queue);
+int qmgr_stat_below_low_watermark(unsigned int queue);
+int qmgr_stat_full(unsigned int queue);
+int qmgr_stat_overflow(unsigned int queue);
+void qmgr_release_queue(unsigned int queue);
+void qmgr_set_irq(unsigned int queue, int src,
+                 void (*handler)(void *pdev), void *pdev);
+void qmgr_enable_irq(unsigned int queue);
+void qmgr_disable_irq(unsigned int queue);
+
+/* request_ and release_queue() must be called from non-IRQ context */
+
+#if DEBUG_QMGR
+extern char qmgr_queue_descs[QUEUES][32];
+
+int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
+                      unsigned int nearly_empty_watermark,
+                      unsigned int nearly_full_watermark,
+                      const char *desc_format, const char* name);
+#else
+int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
+                        unsigned int nearly_empty_watermark,
+                        unsigned int nearly_full_watermark);
+#define qmgr_request_queue(queue, len, nearly_empty_watermark,         \
+                          nearly_full_watermark, desc_format, name)    \
+       __qmgr_request_queue(queue, len, nearly_empty_watermark,        \
+                            nearly_full_watermark)
+#endif
+
+#endif
index e523853..1afe38e 100644 (file)
@@ -271,6 +271,7 @@ struct svc_rqst {
 #define        RQ_VICTIM       (5)                     /* about to be shut down */
 #define        RQ_BUSY         (6)                     /* request is busy */
 #define        RQ_DATA         (7)                     /* request has data */
+#define RQ_AUTHERR     (8)                     /* Request status is auth error */
        unsigned long           rq_flags;       /* flags field */
        ktime_t                 rq_qtime;       /* enqueue time */
 
@@ -382,6 +383,16 @@ struct svc_deferred_req {
        __be32                  args[0];
 };
 
+struct svc_process_info {
+       union {
+               int  (*dispatch)(struct svc_rqst *, __be32 *);
+               struct {
+                       unsigned int lovers;
+                       unsigned int hivers;
+               } mismatch;
+       };
+};
+
 /*
  * List of RPC programs on the same transport endpoint
  */
@@ -396,6 +407,14 @@ struct svc_program {
        char *                  pg_class;       /* class name: services sharing authentication */
        struct svc_stat *       pg_stats;       /* rpc statistics */
        int                     (*pg_authenticate)(struct svc_rqst *);
+       __be32                  (*pg_init_request)(struct svc_rqst *,
+                                                  const struct svc_program *,
+                                                  struct svc_process_info *);
+       int                     (*pg_rpcbind_set)(struct net *net,
+                                                 const struct svc_program *,
+                                                 u32 version, int family,
+                                                 unsigned short proto,
+                                                 unsigned short port);
 };
 
 /*
@@ -504,6 +523,20 @@ unsigned int          svc_fill_write_vector(struct svc_rqst *rqstp,
 char             *svc_fill_symlink_pathname(struct svc_rqst *rqstp,
                                             struct kvec *first, void *p,
                                             size_t total);
+__be32            svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err);
+__be32            svc_generic_init_request(struct svc_rqst *rqstp,
+                                           const struct svc_program *progp,
+                                           struct svc_process_info *procinfo);
+int               svc_generic_rpcbind_set(struct net *net,
+                                          const struct svc_program *progp,
+                                          u32 version, int family,
+                                          unsigned short proto,
+                                          unsigned short port);
+int               svc_rpcbind_set_version(struct net *net,
+                                          const struct svc_program *progp,
+                                          u32 version, int family,
+                                          unsigned short proto,
+                                          unsigned short port);
 
 #define        RPC_MAX_ADDRBUFLEN      (63U)
 
index b3f9577..ea6f46b 100644 (file)
@@ -86,6 +86,7 @@ struct svc_xprt {
        struct list_head        xpt_users;      /* callbacks on free */
 
        struct net              *xpt_net;
+       const struct cred       *xpt_cred;
        struct rpc_xprt         *xpt_bc_xprt;   /* NFSv4.1 backchannel */
        struct rpc_xprt_switch  *xpt_bc_xps;    /* NFSv4.1 backchannel */
 };
@@ -119,7 +120,8 @@ void        svc_unreg_xprt_class(struct svc_xprt_class *);
 void   svc_xprt_init(struct net *, struct svc_xprt_class *, struct svc_xprt *,
                      struct svc_serv *);
 int    svc_create_xprt(struct svc_serv *, const char *, struct net *,
-                       const int, const unsigned short, int);
+                       const int, const unsigned short, int,
+                       const struct cred *);
 void   svc_xprt_do_enqueue(struct svc_xprt *xprt);
 void   svc_xprt_enqueue(struct svc_xprt *xprt);
 void   svc_xprt_put(struct svc_xprt *xprt);
index 119718a..771baad 100644 (file)
@@ -59,7 +59,8 @@ void          svc_drop(struct svc_rqst *);
 void           svc_sock_update_bufs(struct svc_serv *serv);
 bool           svc_alien_sock(struct net *net, int fd);
 int            svc_addsock(struct svc_serv *serv, const int fd,
-                                       char *name_return, const size_t len);
+                                       char *name_return, const size_t len,
+                                       const struct cred *cred);
 void           svc_init_xprt_sock(void);
 void           svc_cleanup_xprt_sock(void);
 struct svc_xprt *svc_sock_create(struct svc_serv *serv, int prot);
index 52a079b..0cfc34a 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/cdev.h>
 
 #define SWITCHTEC_MRPC_PAYLOAD_SIZE 1024
-#define SWITCHTEC_MAX_PFF_CSR 48
+#define SWITCHTEC_MAX_PFF_CSR 255
 
 #define SWITCHTEC_EVENT_OCCURRED BIT(0)
 #define SWITCHTEC_EVENT_CLEAR    BIT(0)
index 5f4705f..15a4ca5 100644 (file)
@@ -442,11 +442,16 @@ void thermal_zone_device_update(struct thermal_zone_device *,
                                enum thermal_notify_event);
 void thermal_zone_set_trips(struct thermal_zone_device *);
 
-struct thermal_cooling_device *thermal_cooling_device_register(char *, void *,
-               const struct thermal_cooling_device_ops *);
+struct thermal_cooling_device *thermal_cooling_device_register(const char *,
+               void *, const struct thermal_cooling_device_ops *);
 struct thermal_cooling_device *
-thermal_of_cooling_device_register(struct device_node *np, char *, void *,
+thermal_of_cooling_device_register(struct device_node *np, const char *, void *,
                                   const struct thermal_cooling_device_ops *);
+struct thermal_cooling_device *
+devm_thermal_of_cooling_device_register(struct device *dev,
+                               struct device_node *np,
+                               char *type, void *devdata,
+                               const struct thermal_cooling_device_ops *ops);
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
 struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
 int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
@@ -503,6 +508,14 @@ static inline struct thermal_cooling_device *
 thermal_of_cooling_device_register(struct device_node *np,
        char *type, void *devdata, const struct thermal_cooling_device_ops *ops)
 { return ERR_PTR(-ENODEV); }
+static inline struct thermal_cooling_device *
+devm_thermal_of_cooling_device_register(struct device *dev,
+                               struct device_node *np,
+                               char *type, void *devdata,
+                               const struct thermal_cooling_device_ops *ops)
+{
+       return ERR_PTR(-ENODEV);
+}
 static inline void thermal_cooling_device_unregister(
        struct thermal_cooling_device *cdev)
 { }
index 53604b0..2fc8541 100644 (file)
@@ -55,6 +55,7 @@ struct ti_emif_pm_data {
 struct ti_emif_pm_functions {
        u32 save_context;
        u32 restore_context;
+       u32 run_hw_leveling;
        u32 enter_sr;
        u32 exit_sr;
        u32 abort_sr;
@@ -126,6 +127,8 @@ static inline void ti_emif_asm_offsets(void)
               offsetof(struct ti_emif_pm_functions, save_context));
        DEFINE(EMIF_PM_RESTORE_CONTEXT_OFFSET,
               offsetof(struct ti_emif_pm_functions, restore_context));
+       DEFINE(EMIF_PM_RUN_HW_LEVELING,
+              offsetof(struct ti_emif_pm_functions, run_hw_leveling));
        DEFINE(EMIF_PM_ENTER_SR_OFFSET,
               offsetof(struct ti_emif_pm_functions, enter_sr));
        DEFINE(EMIF_PM_EXIT_SR_OFFSET,
index 9c31865..86b019a 100644 (file)
@@ -548,4 +548,19 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
 
 #define TRACE_EVENT_PERF_PERM(event, expr...)
 
+#define DECLARE_EVENT_NOP(name, proto, args)                           \
+       static inline void trace_##name(proto)                          \
+       { }                                                             \
+       static inline bool trace_##name##_enabled(void)                 \
+       {                                                               \
+               return false;                                           \
+       }
+
+#define TRACE_EVENT_NOP(name, proto, args, struct, assign, print)      \
+       DECLARE_EVENT_NOP(name, PARAMS(proto), PARAMS(args))
+
+#define DECLARE_EVENT_CLASS_NOP(name, proto, args, tstruct, assign, print)
+#define DEFINE_EVENT_NOP(template, name, proto, args)                  \
+       DECLARE_EVENT_NOP(name, PARAMS(proto), PARAMS(args))
+
 #endif /* ifdef TRACE_EVENT (see note above) */
index 37c9eba..ac9d71e 100644 (file)
@@ -28,6 +28,8 @@
 #define UFFD_SHARED_FCNTL_FLAGS (O_CLOEXEC | O_NONBLOCK)
 #define UFFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS)
 
+extern int sysctl_unprivileged_userfaultfd;
+
 extern vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason);
 
 extern ssize_t mcopy_atomic(struct mm_struct *dst_mm, unsigned long dst_start,
index 673fe3e..15f906e 100644 (file)
@@ -90,23 +90,6 @@ dma_addr_t virtqueue_get_desc_addr(struct virtqueue *vq);
 dma_addr_t virtqueue_get_avail_addr(struct virtqueue *vq);
 dma_addr_t virtqueue_get_used_addr(struct virtqueue *vq);
 
-/*
- * Legacy accessors -- in almost all cases, these are the wrong functions
- * to use.
- */
-static inline void *virtqueue_get_desc(struct virtqueue *vq)
-{
-       return virtqueue_get_vring(vq)->desc;
-}
-static inline void *virtqueue_get_avail(struct virtqueue *vq)
-{
-       return virtqueue_get_vring(vq)->avail;
-}
-static inline void *virtqueue_get_used(struct virtqueue *vq)
-{
-       return virtqueue_get_vring(vq)->used;
-}
-
 /**
  * virtio_device - representation of a device using virtio
  * @index: unique position on the virtio bus
index 2db8d60..bdeda4b 100644 (file)
@@ -26,7 +26,7 @@ struct reclaim_stat {
        unsigned nr_congested;
        unsigned nr_writeback;
        unsigned nr_immediate;
-       unsigned nr_activate;
+       unsigned nr_activate[2];
        unsigned nr_ref_keep;
        unsigned nr_unmap_fail;
 };
index 2b0072f..7dec36a 100644 (file)
@@ -305,6 +305,19 @@ do {                                                                       \
        __ret;                                                          \
 })
 
+#define __wait_var_event_interruptible(var, condition)                 \
+       ___wait_var_event(var, condition, TASK_INTERRUPTIBLE, 0, 0,     \
+                         schedule())
+
+#define wait_var_event_interruptible(var, condition)                   \
+({                                                                     \
+       int __ret = 0;                                                  \
+       might_sleep();                                                  \
+       if (!(condition))                                               \
+               __ret = __wait_var_event_interruptible(var, condition); \
+       __ret;                                                          \
+})
+
 /**
  * clear_and_wake_up_bit - clear a bit and wake up anyone waiting on that bit
  *
index 5c31a76..f76d2f2 100644 (file)
@@ -92,7 +92,7 @@ struct vpbe_config {
        struct encoder_config_info *ext_encoders;
        /* amplifier information goes here */
        struct amp_config_info *amp;
-       int num_outputs;
+       unsigned int num_outputs;
        /* Order is venc outputs followed by LCD and then external encoders */
        struct vpbe_output *outputs;
 };
index 78c856c..93358bf 100644 (file)
@@ -45,6 +45,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *,
                                           gfp_t,
                                           rxrpc_notify_rx_t,
                                           bool,
+                                          bool,
                                           unsigned int);
 int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *,
                           struct msghdr *, size_t,
@@ -68,5 +69,7 @@ u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *);
 bool rxrpc_kernel_get_reply_time(struct socket *, struct rxrpc_call *,
                                 ktime_t *);
 bool rxrpc_kernel_call_is_complete(struct rxrpc_call *);
+void rxrpc_kernel_set_max_life(struct socket *, struct rxrpc_call *,
+                              unsigned long);
 
 #endif /* _NET_RXRPC_H */
index 6aaaadd..6852948 100644 (file)
@@ -99,24 +99,9 @@ struct __dsa_skb_cb {
 
 #define DSA_SKB_CB(skb) ((struct dsa_skb_cb *)((skb)->cb))
 
-#define DSA_SKB_CB_COPY(nskb, skb)             \
-       { *__DSA_SKB_CB(nskb) = *__DSA_SKB_CB(skb); }
-
-#define DSA_SKB_CB_ZERO(skb)                   \
-       { *__DSA_SKB_CB(skb) = (struct __dsa_skb_cb) {0}; }
-
 #define DSA_SKB_CB_PRIV(skb)                   \
        ((void *)(skb)->cb + offsetof(struct __dsa_skb_cb, priv))
 
-#define DSA_SKB_CB_CLONE(_clone, _skb)         \
-       {                                       \
-               struct sk_buff *clone = _clone; \
-               struct sk_buff *skb = _skb;     \
-                                               \
-               DSA_SKB_CB_COPY(clone, skb);    \
-               DSA_SKB_CB(skb)->clone = clone; \
-       }
-
 struct dsa_switch_tree {
        struct list_head        list;
 
index cb30c55..bd75f97 100644 (file)
                assign, print, reg, unreg)                      \
        DEFINE_TRACE_FN(name, reg, unreg)
 
+#undef TRACE_EVENT_NOP
+#define TRACE_EVENT_NOP(name, proto, args, struct, assign, print)
+
+#undef DEFINE_EVENT_NOP
+#define DEFINE_EVENT_NOP(template, name, proto, args)
+
 #undef DEFINE_EVENT
 #define DEFINE_EVENT(template, name, proto, args) \
        DEFINE_TRACE(name)
 #undef TRACE_EVENT_FN
 #undef TRACE_EVENT_FN_COND
 #undef TRACE_EVENT_CONDITION
+#undef TRACE_EVENT_NOP
+#undef DEFINE_EVENT_NOP
 #undef DECLARE_EVENT_CLASS
 #undef DEFINE_EVENT
 #undef DEFINE_EVENT_FN
index 6074eff..e5bf6ee 100644 (file)
@@ -64,6 +64,7 @@ DEFINE_EVENT(mm_compaction_isolate_template, mm_compaction_isolate_freepages,
        TP_ARGS(start_pfn, end_pfn, nr_scanned, nr_taken)
 );
 
+#ifdef CONFIG_COMPACTION
 TRACE_EVENT(mm_compaction_migratepages,
 
        TP_PROTO(unsigned long nr_all,
@@ -132,7 +133,6 @@ TRACE_EVENT(mm_compaction_begin,
                __entry->sync ? "sync" : "async")
 );
 
-#ifdef CONFIG_COMPACTION
 TRACE_EVENT(mm_compaction_end,
        TP_PROTO(unsigned long zone_start, unsigned long migrate_pfn,
                unsigned long free_pfn, unsigned long zone_end, bool sync,
@@ -166,7 +166,6 @@ TRACE_EVENT(mm_compaction_end,
                __entry->sync ? "sync" : "async",
                __print_symbolic(__entry->status, COMPACTION_STATUS))
 );
-#endif
 
 TRACE_EVENT(mm_compaction_try_to_compact_pages,
 
@@ -189,13 +188,12 @@ TRACE_EVENT(mm_compaction_try_to_compact_pages,
                __entry->prio = prio;
        ),
 
-       TP_printk("order=%d gfp_mask=0x%x priority=%d",
+       TP_printk("order=%d gfp_mask=%s priority=%d",
                __entry->order,
-               __entry->gfp_mask,
+               show_gfp_flags(__entry->gfp_mask),
                __entry->prio)
 );
 
-#ifdef CONFIG_COMPACTION
 DECLARE_EVENT_CLASS(mm_compaction_suitable_template,
 
        TP_PROTO(struct zone *zone,
@@ -296,7 +294,6 @@ DEFINE_EVENT(mm_compaction_defer_template, mm_compaction_defer_reset,
 
        TP_ARGS(zone, order)
 );
-#endif
 
 TRACE_EVENT(mm_compaction_kcompactd_sleep,
 
@@ -352,6 +349,7 @@ DEFINE_EVENT(kcompactd_wake_template, mm_compaction_kcompactd_wake,
 
        TP_ARGS(nid, order, classzone_idx)
 );
+#endif
 
 #endif /* _TRACE_COMPACTION_H */
 
index a3916b4..53b96f1 100644 (file)
@@ -533,6 +533,37 @@ TRACE_EVENT(f2fs_truncate_partial_nodes,
                __entry->err)
 );
 
+TRACE_EVENT(f2fs_file_write_iter,
+
+       TP_PROTO(struct inode *inode, unsigned long offset,
+               unsigned long length, int ret),
+
+       TP_ARGS(inode, offset, length, ret),
+
+       TP_STRUCT__entry(
+               __field(dev_t,  dev)
+               __field(ino_t,  ino)
+               __field(unsigned long, offset)
+               __field(unsigned long, length)
+               __field(int,    ret)
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->ino    = inode->i_ino;
+               __entry->offset = offset;
+               __entry->length = length;
+               __entry->ret    = ret;
+       ),
+
+       TP_printk("dev = (%d,%d), ino = %lu, "
+               "offset = %lu, length = %lu, written(err) = %d",
+               show_dev_ino(__entry),
+               __entry->offset,
+               __entry->length,
+               __entry->ret)
+);
+
 TRACE_EVENT(f2fs_map_blocks,
        TP_PROTO(struct inode *inode, struct f2fs_map_blocks *map, int ret),
 
@@ -1253,6 +1284,32 @@ DEFINE_EVENT(f2fs__page, f2fs_commit_inmem_page,
        TP_ARGS(page, type)
 );
 
+TRACE_EVENT(f2fs_filemap_fault,
+
+       TP_PROTO(struct inode *inode, pgoff_t index, unsigned long ret),
+
+       TP_ARGS(inode, index, ret),
+
+       TP_STRUCT__entry(
+               __field(dev_t,  dev)
+               __field(ino_t,  ino)
+               __field(pgoff_t, index)
+               __field(unsigned long, ret)
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = inode->i_sb->s_dev;
+               __entry->ino    = inode->i_ino;
+               __entry->index  = index;
+               __entry->ret    = ret;
+       ),
+
+       TP_printk("dev = (%d,%d), ino = %lu, index = %lu, ret = %lx",
+               show_dev_ino(__entry),
+               (unsigned long)__entry->index,
+               __entry->ret)
+);
+
 TRACE_EVENT(f2fs_writepages,
 
        TP_PROTO(struct inode *inode, struct writeback_control *wbc, int type),
index 80339fd..02a3f78 100644 (file)
@@ -7,6 +7,12 @@
 
 #include <linux/tracepoint.h>
 
+#ifdef CONFIG_RCU_TRACE
+#define TRACE_EVENT_RCU TRACE_EVENT
+#else
+#define TRACE_EVENT_RCU TRACE_EVENT_NOP
+#endif
+
 /*
  * Tracepoint for start/end markers used for utilization calculations.
  * By convention, the string is of the following forms:
@@ -35,8 +41,6 @@ TRACE_EVENT(rcu_utilization,
        TP_printk("%s", __entry->s)
 );
 
-#ifdef CONFIG_RCU_TRACE
-
 #if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU)
 
 /*
@@ -62,7 +66,7 @@ TRACE_EVENT(rcu_utilization,
  *     "end": End a grace period.
  *     "cpuend": CPU first notices a grace-period end.
  */
-TRACE_EVENT(rcu_grace_period,
+TRACE_EVENT_RCU(rcu_grace_period,
 
        TP_PROTO(const char *rcuname, unsigned long gp_seq, const char *gpevent),
 
@@ -101,7 +105,7 @@ TRACE_EVENT(rcu_grace_period,
  * "Cleanup": Clean up rcu_node structure after previous GP.
  * "CleanupMore": Clean up, and another GP is needed.
  */
-TRACE_EVENT(rcu_future_grace_period,
+TRACE_EVENT_RCU(rcu_future_grace_period,
 
        TP_PROTO(const char *rcuname, unsigned long gp_seq,
                 unsigned long gp_seq_req, u8 level, int grplo, int grphi,
@@ -141,7 +145,7 @@ TRACE_EVENT(rcu_future_grace_period,
  * rcu_node structure, and the mask of CPUs that will be waited for.
  * All but the type of RCU are extracted from the rcu_node structure.
  */
-TRACE_EVENT(rcu_grace_period_init,
+TRACE_EVENT_RCU(rcu_grace_period_init,
 
        TP_PROTO(const char *rcuname, unsigned long gp_seq, u8 level,
                 int grplo, int grphi, unsigned long qsmask),
@@ -186,7 +190,7 @@ TRACE_EVENT(rcu_grace_period_init,
  *     "endwake": Woke piggybackers up.
  *     "done": Someone else did the expedited grace period for us.
  */
-TRACE_EVENT(rcu_exp_grace_period,
+TRACE_EVENT_RCU(rcu_exp_grace_period,
 
        TP_PROTO(const char *rcuname, unsigned long gpseq, const char *gpevent),
 
@@ -218,7 +222,7 @@ TRACE_EVENT(rcu_exp_grace_period,
  *     "nxtlvl": Advance to next level of rcu_node funnel
  *     "wait": Wait for someone else to do expedited GP
  */
-TRACE_EVENT(rcu_exp_funnel_lock,
+TRACE_EVENT_RCU(rcu_exp_funnel_lock,
 
        TP_PROTO(const char *rcuname, u8 level, int grplo, int grphi,
                 const char *gpevent),
@@ -269,7 +273,7 @@ TRACE_EVENT(rcu_exp_funnel_lock,
  *     "WaitQueue": Enqueue partially done, timed wait for it to complete.
  *     "WokeQueue": Partial enqueue now complete.
  */
-TRACE_EVENT(rcu_nocb_wake,
+TRACE_EVENT_RCU(rcu_nocb_wake,
 
        TP_PROTO(const char *rcuname, int cpu, const char *reason),
 
@@ -297,7 +301,7 @@ TRACE_EVENT(rcu_nocb_wake,
  * include SRCU), the grace-period number that the task is blocking
  * (the current or the next), and the task's PID.
  */
-TRACE_EVENT(rcu_preempt_task,
+TRACE_EVENT_RCU(rcu_preempt_task,
 
        TP_PROTO(const char *rcuname, int pid, unsigned long gp_seq),
 
@@ -324,7 +328,7 @@ TRACE_EVENT(rcu_preempt_task,
  * read-side critical section exiting that critical section.  Track the
  * type of RCU (which one day might include SRCU) and the task's PID.
  */
-TRACE_EVENT(rcu_unlock_preempted_task,
+TRACE_EVENT_RCU(rcu_unlock_preempted_task,
 
        TP_PROTO(const char *rcuname, unsigned long gp_seq, int pid),
 
@@ -353,7 +357,7 @@ TRACE_EVENT(rcu_unlock_preempted_task,
  * whether there are any blocked tasks blocking the current grace period.
  * All but the type of RCU are extracted from the rcu_node structure.
  */
-TRACE_EVENT(rcu_quiescent_state_report,
+TRACE_EVENT_RCU(rcu_quiescent_state_report,
 
        TP_PROTO(const char *rcuname, unsigned long gp_seq,
                 unsigned long mask, unsigned long qsmask,
@@ -396,7 +400,7 @@ TRACE_EVENT(rcu_quiescent_state_report,
  * state, which can be "dti" for dyntick-idle mode or "kick" when kicking
  * a CPU that has been in dyntick-idle mode for too long.
  */
-TRACE_EVENT(rcu_fqs,
+TRACE_EVENT_RCU(rcu_fqs,
 
        TP_PROTO(const char *rcuname, unsigned long gp_seq, int cpu, const char *qsevent),
 
@@ -436,7 +440,7 @@ TRACE_EVENT(rcu_fqs,
  * events use two separate counters, and that the "++=" and "--=" events
  * for irq/NMI will change the counter by two, otherwise by one.
  */
-TRACE_EVENT(rcu_dyntick,
+TRACE_EVENT_RCU(rcu_dyntick,
 
        TP_PROTO(const char *polarity, long oldnesting, long newnesting, atomic_t dynticks),
 
@@ -468,7 +472,7 @@ TRACE_EVENT(rcu_dyntick,
  * number of lazy callbacks queued, and the fourth element is the
  * total number of callbacks queued.
  */
-TRACE_EVENT(rcu_callback,
+TRACE_EVENT_RCU(rcu_callback,
 
        TP_PROTO(const char *rcuname, struct rcu_head *rhp, long qlen_lazy,
                 long qlen),
@@ -504,7 +508,7 @@ TRACE_EVENT(rcu_callback,
  * the fourth argument is the number of lazy callbacks queued, and the
  * fifth argument is the total number of callbacks queued.
  */
-TRACE_EVENT(rcu_kfree_callback,
+TRACE_EVENT_RCU(rcu_kfree_callback,
 
        TP_PROTO(const char *rcuname, struct rcu_head *rhp, unsigned long offset,
                 long qlen_lazy, long qlen),
@@ -539,7 +543,7 @@ TRACE_EVENT(rcu_kfree_callback,
  * the total number of callbacks queued, and the fourth argument is
  * the current RCU-callback batch limit.
  */
-TRACE_EVENT(rcu_batch_start,
+TRACE_EVENT_RCU(rcu_batch_start,
 
        TP_PROTO(const char *rcuname, long qlen_lazy, long qlen, long blimit),
 
@@ -569,7 +573,7 @@ TRACE_EVENT(rcu_batch_start,
  * The first argument is the type of RCU, and the second argument is
  * a pointer to the RCU callback itself.
  */
-TRACE_EVENT(rcu_invoke_callback,
+TRACE_EVENT_RCU(rcu_invoke_callback,
 
        TP_PROTO(const char *rcuname, struct rcu_head *rhp),
 
@@ -598,7 +602,7 @@ TRACE_EVENT(rcu_invoke_callback,
  * is the offset of the callback within the enclosing RCU-protected
  * data structure.
  */
-TRACE_EVENT(rcu_invoke_kfree_callback,
+TRACE_EVENT_RCU(rcu_invoke_kfree_callback,
 
        TP_PROTO(const char *rcuname, struct rcu_head *rhp, unsigned long offset),
 
@@ -631,7 +635,7 @@ TRACE_EVENT(rcu_invoke_kfree_callback,
  * and the sixth argument (risk) is the return value from
  * rcu_is_callbacks_kthread().
  */
-TRACE_EVENT(rcu_batch_end,
+TRACE_EVENT_RCU(rcu_batch_end,
 
        TP_PROTO(const char *rcuname, int callbacks_invoked,
                 char cb, char nr, char iit, char risk),
@@ -673,7 +677,7 @@ TRACE_EVENT(rcu_batch_end,
  * callback address can be NULL.
  */
 #define RCUTORTURENAME_LEN 8
-TRACE_EVENT(rcu_torture_read,
+TRACE_EVENT_RCU(rcu_torture_read,
 
        TP_PROTO(const char *rcutorturename, struct rcu_head *rhp,
                 unsigned long secs, unsigned long c_old, unsigned long c),
@@ -721,7 +725,7 @@ TRACE_EVENT(rcu_torture_read,
  * The "cpu" argument is the CPU or -1 if meaningless, the "cnt" argument
  * is the count of remaining callbacks, and "done" is the piggybacking count.
  */
-TRACE_EVENT(rcu_barrier,
+TRACE_EVENT_RCU(rcu_barrier,
 
        TP_PROTO(const char *rcuname, const char *s, int cpu, int cnt, unsigned long done),
 
@@ -748,41 +752,6 @@ TRACE_EVENT(rcu_barrier,
                  __entry->done)
 );
 
-#else /* #ifdef CONFIG_RCU_TRACE */
-
-#define trace_rcu_grace_period(rcuname, gp_seq, gpevent) do { } while (0)
-#define trace_rcu_future_grace_period(rcuname, gp_seq, gp_seq_req, \
-                                     level, grplo, grphi, event) \
-                                     do { } while (0)
-#define trace_rcu_grace_period_init(rcuname, gp_seq, level, grplo, grphi, \
-                                   qsmask) do { } while (0)
-#define trace_rcu_exp_grace_period(rcuname, gqseq, gpevent) \
-       do { } while (0)
-#define trace_rcu_exp_funnel_lock(rcuname, level, grplo, grphi, gpevent) \
-       do { } while (0)
-#define trace_rcu_nocb_wake(rcuname, cpu, reason) do { } while (0)
-#define trace_rcu_preempt_task(rcuname, pid, gp_seq) do { } while (0)
-#define trace_rcu_unlock_preempted_task(rcuname, gp_seq, pid) do { } while (0)
-#define trace_rcu_quiescent_state_report(rcuname, gp_seq, mask, qsmask, level, \
-                                        grplo, grphi, gp_tasks) do { } \
-       while (0)
-#define trace_rcu_fqs(rcuname, gp_seq, cpu, qsevent) do { } while (0)
-#define trace_rcu_dyntick(polarity, oldnesting, newnesting, dyntick) do { } while (0)
-#define trace_rcu_callback(rcuname, rhp, qlen_lazy, qlen) do { } while (0)
-#define trace_rcu_kfree_callback(rcuname, rhp, offset, qlen_lazy, qlen) \
-       do { } while (0)
-#define trace_rcu_batch_start(rcuname, qlen_lazy, qlen, blimit) \
-       do { } while (0)
-#define trace_rcu_invoke_callback(rcuname, rhp) do { } while (0)
-#define trace_rcu_invoke_kfree_callback(rcuname, rhp, offset) do { } while (0)
-#define trace_rcu_batch_end(rcuname, callbacks_invoked, cb, nr, iit, risk) \
-       do { } while (0)
-#define trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c) \
-       do { } while (0)
-#define trace_rcu_barrier(name, s, cpu, cnt, done) do { } while (0)
-
-#endif /* #else #ifdef CONFIG_RCU_TRACE */
-
 #endif /* _TRACE_RCU_H */
 
 /* This part must be outside protection */
index 9a4bdfa..c8c7c7e 100644 (file)
@@ -241,7 +241,6 @@ DECLARE_EVENT_CLASS(sched_process_template,
 DEFINE_EVENT(sched_process_template, sched_process_free,
             TP_PROTO(struct task_struct *p),
             TP_ARGS(p));
-            
 
 /*
  * Tracepoint for a task exiting:
@@ -336,11 +335,20 @@ TRACE_EVENT(sched_process_exec,
                  __entry->pid, __entry->old_pid)
 );
 
+
+#ifdef CONFIG_SCHEDSTATS
+#define DEFINE_EVENT_SCHEDSTAT DEFINE_EVENT
+#define DECLARE_EVENT_CLASS_SCHEDSTAT DECLARE_EVENT_CLASS
+#else
+#define DEFINE_EVENT_SCHEDSTAT DEFINE_EVENT_NOP
+#define DECLARE_EVENT_CLASS_SCHEDSTAT DECLARE_EVENT_CLASS_NOP
+#endif
+
 /*
  * XXX the below sched_stat tracepoints only apply to SCHED_OTHER/BATCH/IDLE
  *     adding sched_stat support to SCHED_FIFO/RR would be welcome.
  */
-DECLARE_EVENT_CLASS(sched_stat_template,
+DECLARE_EVENT_CLASS_SCHEDSTAT(sched_stat_template,
 
        TP_PROTO(struct task_struct *tsk, u64 delay),
 
@@ -363,12 +371,11 @@ DECLARE_EVENT_CLASS(sched_stat_template,
                        (unsigned long long)__entry->delay)
 );
 
-
 /*
  * Tracepoint for accounting wait time (time the task is runnable
  * but not actually running due to scheduler contention).
  */
-DEFINE_EVENT(sched_stat_template, sched_stat_wait,
+DEFINE_EVENT_SCHEDSTAT(sched_stat_template, sched_stat_wait,
             TP_PROTO(struct task_struct *tsk, u64 delay),
             TP_ARGS(tsk, delay));
 
@@ -376,7 +383,7 @@ DEFINE_EVENT(sched_stat_template, sched_stat_wait,
  * Tracepoint for accounting sleep time (time the task is not runnable,
  * including iowait, see below).
  */
-DEFINE_EVENT(sched_stat_template, sched_stat_sleep,
+DEFINE_EVENT_SCHEDSTAT(sched_stat_template, sched_stat_sleep,
             TP_PROTO(struct task_struct *tsk, u64 delay),
             TP_ARGS(tsk, delay));
 
@@ -384,14 +391,14 @@ DEFINE_EVENT(sched_stat_template, sched_stat_sleep,
  * Tracepoint for accounting iowait time (time the task is not runnable
  * due to waiting on IO to complete).
  */
-DEFINE_EVENT(sched_stat_template, sched_stat_iowait,
+DEFINE_EVENT_SCHEDSTAT(sched_stat_template, sched_stat_iowait,
             TP_PROTO(struct task_struct *tsk, u64 delay),
             TP_ARGS(tsk, delay));
 
 /*
  * Tracepoint for accounting blocked time (time the task is in uninterruptible).
  */
-DEFINE_EVENT(sched_stat_template, sched_stat_blocked,
+DEFINE_EVENT_SCHEDSTAT(sched_stat_template, sched_stat_blocked,
             TP_PROTO(struct task_struct *tsk, u64 delay),
             TP_ARGS(tsk, delay));
 
index 252327d..a5ab297 100644 (file)
                {RECLAIM_WB_ASYNC,      "RECLAIM_WB_ASYNC"}     \
                ) : "RECLAIM_WB_NONE"
 
-#define trace_reclaim_flags(page) ( \
-       (page_is_file_cache(page) ? RECLAIM_WB_FILE : RECLAIM_WB_ANON) | \
+#define trace_reclaim_flags(file) ( \
+       (file ? RECLAIM_WB_FILE : RECLAIM_WB_ANON) | \
        (RECLAIM_WB_ASYNC) \
        )
 
-#define trace_shrink_flags(file) \
-       ( \
-               (file ? RECLAIM_WB_FILE : RECLAIM_WB_ANON) | \
-               (RECLAIM_WB_ASYNC) \
-       )
-
 TRACE_EVENT(mm_vmscan_kswapd_sleep,
 
        TP_PROTO(int nid),
@@ -73,7 +67,9 @@ TRACE_EVENT(mm_vmscan_kswapd_wake,
                __entry->order  = order;
        ),
 
-       TP_printk("nid=%d zid=%d order=%d", __entry->nid, __entry->zid, __entry->order)
+       TP_printk("nid=%d order=%d",
+               __entry->nid,
+               __entry->order)
 );
 
 TRACE_EVENT(mm_vmscan_wakeup_kswapd,
@@ -96,60 +92,53 @@ TRACE_EVENT(mm_vmscan_wakeup_kswapd,
                __entry->gfp_flags      = gfp_flags;
        ),
 
-       TP_printk("nid=%d zid=%d order=%d gfp_flags=%s",
+       TP_printk("nid=%d order=%d gfp_flags=%s",
                __entry->nid,
-               __entry->zid,
                __entry->order,
                show_gfp_flags(__entry->gfp_flags))
 );
 
 DECLARE_EVENT_CLASS(mm_vmscan_direct_reclaim_begin_template,
 
-       TP_PROTO(int order, int may_writepage, gfp_t gfp_flags, int classzone_idx),
+       TP_PROTO(int order, gfp_t gfp_flags),
 
-       TP_ARGS(order, may_writepage, gfp_flags, classzone_idx),
+       TP_ARGS(order, gfp_flags),
 
        TP_STRUCT__entry(
                __field(        int,    order           )
-               __field(        int,    may_writepage   )
                __field(        gfp_t,  gfp_flags       )
-               __field(        int,    classzone_idx   )
        ),
 
        TP_fast_assign(
                __entry->order          = order;
-               __entry->may_writepage  = may_writepage;
                __entry->gfp_flags      = gfp_flags;
-               __entry->classzone_idx  = classzone_idx;
        ),
 
-       TP_printk("order=%d may_writepage=%d gfp_flags=%s classzone_idx=%d",
+       TP_printk("order=%d gfp_flags=%s",
                __entry->order,
-               __entry->may_writepage,
-               show_gfp_flags(__entry->gfp_flags),
-               __entry->classzone_idx)
+               show_gfp_flags(__entry->gfp_flags))
 );
 
 DEFINE_EVENT(mm_vmscan_direct_reclaim_begin_template, mm_vmscan_direct_reclaim_begin,
 
-       TP_PROTO(int order, int may_writepage, gfp_t gfp_flags, int classzone_idx),
+       TP_PROTO(int order, gfp_t gfp_flags),
 
-       TP_ARGS(order, may_writepage, gfp_flags, classzone_idx)
+       TP_ARGS(order, gfp_flags)
 );
 
 #ifdef CONFIG_MEMCG
 DEFINE_EVENT(mm_vmscan_direct_reclaim_begin_template, mm_vmscan_memcg_reclaim_begin,
 
-       TP_PROTO(int order, int may_writepage, gfp_t gfp_flags, int classzone_idx),
+       TP_PROTO(int order, gfp_t gfp_flags),
 
-       TP_ARGS(order, may_writepage, gfp_flags, classzone_idx)
+       TP_ARGS(order, gfp_flags)
 );
 
 DEFINE_EVENT(mm_vmscan_direct_reclaim_begin_template, mm_vmscan_memcg_softlimit_reclaim_begin,
 
-       TP_PROTO(int order, int may_writepage, gfp_t gfp_flags, int classzone_idx),
+       TP_PROTO(int order, gfp_t gfp_flags),
 
-       TP_ARGS(order, may_writepage, gfp_flags, classzone_idx)
+       TP_ARGS(order, gfp_flags)
 );
 #endif /* CONFIG_MEMCG */
 
@@ -333,7 +322,8 @@ TRACE_EVENT(mm_vmscan_writepage,
 
        TP_fast_assign(
                __entry->pfn = page_to_pfn(page);
-               __entry->reclaim_flags = trace_reclaim_flags(page);
+               __entry->reclaim_flags = trace_reclaim_flags(
+                                               page_is_file_cache(page));
        ),
 
        TP_printk("page=%p pfn=%lu flags=%s",
@@ -358,7 +348,8 @@ TRACE_EVENT(mm_vmscan_lru_shrink_inactive,
                __field(unsigned long, nr_writeback)
                __field(unsigned long, nr_congested)
                __field(unsigned long, nr_immediate)
-               __field(unsigned long, nr_activate)
+               __field(unsigned int, nr_activate0)
+               __field(unsigned int, nr_activate1)
                __field(unsigned long, nr_ref_keep)
                __field(unsigned long, nr_unmap_fail)
                __field(int, priority)
@@ -373,20 +364,22 @@ TRACE_EVENT(mm_vmscan_lru_shrink_inactive,
                __entry->nr_writeback = stat->nr_writeback;
                __entry->nr_congested = stat->nr_congested;
                __entry->nr_immediate = stat->nr_immediate;
-               __entry->nr_activate = stat->nr_activate;
+               __entry->nr_activate0 = stat->nr_activate[0];
+               __entry->nr_activate1 = stat->nr_activate[1];
                __entry->nr_ref_keep = stat->nr_ref_keep;
                __entry->nr_unmap_fail = stat->nr_unmap_fail;
                __entry->priority = priority;
-               __entry->reclaim_flags = trace_shrink_flags(file);
+               __entry->reclaim_flags = trace_reclaim_flags(file);
        ),
 
-       TP_printk("nid=%d nr_scanned=%ld nr_reclaimed=%ld nr_dirty=%ld nr_writeback=%ld nr_congested=%ld nr_immediate=%ld nr_activate=%ld nr_ref_keep=%ld nr_unmap_fail=%ld priority=%d flags=%s",
+       TP_printk("nid=%d nr_scanned=%ld nr_reclaimed=%ld nr_dirty=%ld nr_writeback=%ld nr_congested=%ld nr_immediate=%ld nr_activate_anon=%d nr_activate_file=%d nr_ref_keep=%ld nr_unmap_fail=%ld priority=%d flags=%s",
                __entry->nid,
                __entry->nr_scanned, __entry->nr_reclaimed,
                __entry->nr_dirty, __entry->nr_writeback,
                __entry->nr_congested, __entry->nr_immediate,
-               __entry->nr_activate, __entry->nr_ref_keep,
-               __entry->nr_unmap_fail, __entry->priority,
+               __entry->nr_activate0, __entry->nr_activate1,
+               __entry->nr_ref_keep, __entry->nr_unmap_fail,
+               __entry->priority,
                show_reclaim_flags(__entry->reclaim_flags))
 );
 
@@ -415,7 +408,7 @@ TRACE_EVENT(mm_vmscan_lru_shrink_active,
                __entry->nr_deactivated = nr_deactivated;
                __entry->nr_referenced = nr_referenced;
                __entry->priority = priority;
-               __entry->reclaim_flags = trace_shrink_flags(file);
+               __entry->reclaim_flags = trace_reclaim_flags(file);
        ),
 
        TP_printk("nid=%d nr_taken=%ld nr_active=%ld nr_deactivated=%ld nr_referenced=%ld priority=%d flags=%s",
@@ -454,7 +447,8 @@ TRACE_EVENT(mm_vmscan_inactive_list_is_low,
                __entry->total_active = total_active;
                __entry->active = active;
                __entry->ratio = ratio;
-               __entry->reclaim_flags = trace_shrink_flags(file) & RECLAIM_WB_LRU;
+               __entry->reclaim_flags = trace_reclaim_flags(file) &
+                                        RECLAIM_WB_LRU;
        ),
 
        TP_printk("nid=%d reclaim_idx=%d total_inactive=%ld inactive=%ld total_active=%ld active=%ld ratio=%ld flags=%s",
@@ -465,6 +459,38 @@ TRACE_EVENT(mm_vmscan_inactive_list_is_low,
                __entry->ratio,
                show_reclaim_flags(__entry->reclaim_flags))
 );
+
+TRACE_EVENT(mm_vmscan_node_reclaim_begin,
+
+       TP_PROTO(int nid, int order, gfp_t gfp_flags),
+
+       TP_ARGS(nid, order, gfp_flags),
+
+       TP_STRUCT__entry(
+               __field(int, nid)
+               __field(int, order)
+               __field(gfp_t, gfp_flags)
+       ),
+
+       TP_fast_assign(
+               __entry->nid = nid;
+               __entry->order = order;
+               __entry->gfp_flags = gfp_flags;
+       ),
+
+       TP_printk("nid=%d order=%d gfp_flags=%s",
+               __entry->nid,
+               __entry->order,
+               show_gfp_flags(__entry->gfp_flags))
+);
+
+DEFINE_EVENT(mm_vmscan_direct_reclaim_end_template, mm_vmscan_node_reclaim_end,
+
+       TP_PROTO(unsigned long nr_reclaimed),
+
+       TP_ARGS(nr_reclaimed)
+);
+
 #endif /* _TRACE_VMSCAN_H */
 
 /* This part must be outside protection */
index 32db72c..aa7f3ae 100644 (file)
@@ -53,7 +53,7 @@ WB_WORK_REASON
 
 struct wb_writeback_work;
 
-TRACE_EVENT(writeback_dirty_page,
+DECLARE_EVENT_CLASS(writeback_page_template,
 
        TP_PROTO(struct page *page, struct address_space *mapping),
 
@@ -79,6 +79,20 @@ TRACE_EVENT(writeback_dirty_page,
        )
 );
 
+DEFINE_EVENT(writeback_page_template, writeback_dirty_page,
+
+       TP_PROTO(struct page *page, struct address_space *mapping),
+
+       TP_ARGS(page, mapping)
+);
+
+DEFINE_EVENT(writeback_page_template, wait_on_page_writeback,
+
+       TP_PROTO(struct page *page, struct address_space *mapping),
+
+       TP_ARGS(page, mapping)
+);
+
 DECLARE_EVENT_CLASS(writeback_dirty_inode_template,
 
        TP_PROTO(struct inode *inode, int flags),
index 72336ba..63e0cf6 100644 (file)
@@ -629,7 +629,7 @@ union bpf_attr {
  *             **BPF_F_INVALIDATE_HASH** (set *skb*\ **->hash**, *skb*\
  *             **->swhash** and *skb*\ **->l4hash** to 0).
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -654,7 +654,7 @@ union bpf_attr {
  *             flexibility and can handle sizes larger than 2 or 4 for the
  *             checksum to update.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -686,7 +686,7 @@ union bpf_attr {
  *             flexibility and can handle sizes larger than 2 or 4 for the
  *             checksum to update.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -741,7 +741,7 @@ union bpf_attr {
  *             efficient, but it is handled through an action code where the
  *             redirection happens only after the eBPF program has returned.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -806,7 +806,7 @@ union bpf_attr {
  *             **ETH_P_8021Q** and **ETH_P_8021AD**, it is considered to
  *             be **ETH_P_8021Q**.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -818,7 +818,7 @@ union bpf_attr {
  *     Description
  *             Pop a VLAN header from the packet associated to *skb*.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1168,7 +1168,7 @@ union bpf_attr {
  *             All values for *flags* are reserved for future usage, and must
  *             be left at zero.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1281,7 +1281,7 @@ union bpf_attr {
  *             implicitly linearizes, unclones and drops offloads from the
  *             *skb*.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1317,7 +1317,7 @@ union bpf_attr {
  *             **bpf_skb_pull_data()** to effectively unclone the *skb* from
  *             the very beginning in case it is indeed cloned.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1369,7 +1369,7 @@ union bpf_attr {
  *             All values for *flags* are reserved for future usage, and must
  *             be left at zero.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1384,7 +1384,7 @@ union bpf_attr {
  *             can be used to prepare the packet for pushing or popping
  *             headers.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1518,20 +1518,20 @@ union bpf_attr {
  *             * **BPF_F_ADJ_ROOM_FIXED_GSO**: Do not adjust gso_size.
  *               Adjusting mss in this way is not allowed for datagrams.
  *
- *             * **BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 **:
- *             * **BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 **:
+ *             * **BPF_F_ADJ_ROOM_ENCAP_L3_IPV4**,
+ *               **BPF_F_ADJ_ROOM_ENCAP_L3_IPV6**:
  *               Any new space is reserved to hold a tunnel header.
  *               Configure skb offsets and other fields accordingly.
  *
- *             * **BPF_F_ADJ_ROOM_ENCAP_L4_GRE **:
- *             * **BPF_F_ADJ_ROOM_ENCAP_L4_UDP **:
+ *             * **BPF_F_ADJ_ROOM_ENCAP_L4_GRE**,
+ *               **BPF_F_ADJ_ROOM_ENCAP_L4_UDP**:
  *               Use with ENCAP_L3 flags to further specify the tunnel type.
  *
- *             * **BPF_F_ADJ_ROOM_ENCAP_L2(len) **:
+ *             * **BPF_F_ADJ_ROOM_ENCAP_L2**\ (*len*):
  *               Use with ENCAP_L3/L4 flags to further specify the tunnel
- *               type; **len** is the length of the inner MAC header.
+ *               type; *len* is the length of the inner MAC header.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1610,7 +1610,7 @@ union bpf_attr {
  *             more flexibility as the user is free to store whatever meta
  *             data they need.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1852,7 +1852,7 @@ union bpf_attr {
  *             copied if necessary (i.e. if data was not linear and if start
  *             and end pointers do not point to the same chunk).
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1886,7 +1886,7 @@ union bpf_attr {
  *             only possible to shrink the packet as of this writing,
  *             therefore *delta* must be a negative integer.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -2061,18 +2061,18 @@ union bpf_attr {
  *             **BPF_LWT_ENCAP_IP**
  *                     IP encapsulation (GRE/GUE/IPIP/etc). The outer header
  *                     must be IPv4 or IPv6, followed by zero or more
- *                     additional headers, up to LWT_BPF_MAX_HEADROOM total
- *                     bytes in all prepended headers. Please note that
- *                     if skb_is_gso(skb) is true, no more than two headers
- *                     can be prepended, and the inner header, if present,
- *                     should be either GRE or UDP/GUE.
- *
- *             BPF_LWT_ENCAP_SEG6*** types can be called by bpf programs of
- *             type BPF_PROG_TYPE_LWT_IN; BPF_LWT_ENCAP_IP type can be called
- *             by bpf programs of types BPF_PROG_TYPE_LWT_IN and
- *             BPF_PROG_TYPE_LWT_XMIT.
- *
- *             A call to this helper is susceptible to change the underlaying
+ *                     additional headers, up to **LWT_BPF_MAX_HEADROOM**
+ *                     total bytes in all prepended headers. Please note that
+ *                     if **skb_is_gso**\ (*skb*) is true, no more than two
+ *                     headers can be prepended, and the inner header, if
+ *                     present, should be either GRE or UDP/GUE.
+ *
+ *             **BPF_LWT_ENCAP_SEG6**\ \* types can be called by BPF programs
+ *             of type **BPF_PROG_TYPE_LWT_IN**; **BPF_LWT_ENCAP_IP** type can
+ *             be called by bpf programs of types **BPF_PROG_TYPE_LWT_IN** and
+ *             **BPF_PROG_TYPE_LWT_XMIT**.
+ *
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -2087,7 +2087,7 @@ union bpf_attr {
  *             inside the outermost IPv6 Segment Routing Header can be
  *             modified through this helper.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -2103,7 +2103,7 @@ union bpf_attr {
  *             after the segments are accepted. *delta* can be as well
  *             positive (growing) as negative (shrinking).
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -2126,13 +2126,13 @@ union bpf_attr {
  *                     Type of *param*: **int**.
  *             **SEG6_LOCAL_ACTION_END_B6**
  *                     End.B6 action: Endpoint bound to an SRv6 policy.
- *                     Type of param: **struct ipv6_sr_hdr**.
+ *                     Type of *param*: **struct ipv6_sr_hdr**.
  *             **SEG6_LOCAL_ACTION_END_B6_ENCAP**
  *                     End.B6.Encap action: Endpoint bound to an SRv6
  *                     encapsulation policy.
- *                     Type of param: **struct ipv6_sr_hdr**.
+ *                     Type of *param*: **struct ipv6_sr_hdr**.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -2285,7 +2285,8 @@ union bpf_attr {
  *     Return
  *             Pointer to **struct bpf_sock**, or **NULL** in case of failure.
  *             For sockets with reuseport option, the **struct bpf_sock**
- *             result is from **reuse->socks**\ [] using the hash of the tuple.
+ *             result is from *reuse*\ **->socks**\ [] using the hash of the
+ *             tuple.
  *
  * struct bpf_sock *bpf_sk_lookup_udp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags)
  *     Description
@@ -2321,7 +2322,8 @@ union bpf_attr {
  *     Return
  *             Pointer to **struct bpf_sock**, or **NULL** in case of failure.
  *             For sockets with reuseport option, the **struct bpf_sock**
- *             result is from **reuse->socks**\ [] using the hash of the tuple.
+ *             result is from *reuse*\ **->socks**\ [] using the hash of the
+ *             tuple.
  *
  * int bpf_sk_release(struct bpf_sock *sock)
  *     Description
@@ -2490,31 +2492,34 @@ union bpf_attr {
  *             network namespace *netns*. The return value must be checked,
  *             and if non-**NULL**, released via **bpf_sk_release**\ ().
  *
- *             This function is identical to bpf_sk_lookup_tcp, except that it
- *             also returns timewait or request sockets. Use bpf_sk_fullsock
- *             or bpf_tcp_socket to access the full structure.
+ *             This function is identical to **bpf_sk_lookup_tcp**\ (), except
+ *             that it also returns timewait or request sockets. Use
+ *             **bpf_sk_fullsock**\ () or **bpf_tcp_sock**\ () to access the
+ *             full structure.
  *
  *             This helper is available only if the kernel was compiled with
  *             **CONFIG_NET** configuration option.
  *     Return
  *             Pointer to **struct bpf_sock**, or **NULL** in case of failure.
  *             For sockets with reuseport option, the **struct bpf_sock**
- *             result is from **reuse->socks**\ [] using the hash of the tuple.
+ *             result is from *reuse*\ **->socks**\ [] using the hash of the
+ *             tuple.
  *
  * int bpf_tcp_check_syncookie(struct bpf_sock *sk, void *iph, u32 iph_len, struct tcphdr *th, u32 th_len)
  *     Description
- *             Check whether iph and th contain a valid SYN cookie ACK for
- *             the listening socket in sk.
+ *             Check whether *iph* and *th* contain a valid SYN cookie ACK for
+ *             the listening socket in *sk*.
  *
- *             iph points to the start of the IPv4 or IPv6 header, while
- *             iph_len contains sizeof(struct iphdr) or sizeof(struct ip6hdr).
+ *             *iph* points to the start of the IPv4 or IPv6 header, while
+ *             *iph_len* contains **sizeof**\ (**struct iphdr**) or
+ *             **sizeof**\ (**struct ip6hdr**).
  *
- *             th points to the start of the TCP header, while th_len contains
- *             sizeof(struct tcphdr).
+ *             *th* points to the start of the TCP header, while *th_len*
+ *             contains **sizeof**\ (**struct tcphdr**).
  *
  *     Return
- *             0 if iph and th are a valid SYN cookie ACK, or a negative error
- *             otherwise.
+ *             0 if *iph* and *th* are a valid SYN cookie ACK, or a negative
+ *             error otherwise.
  *
  * int bpf_sysctl_get_name(struct bpf_sysctl *ctx, char *buf, size_t buf_len, u64 flags)
  *     Description
@@ -2592,17 +2597,17 @@ union bpf_attr {
  *             and save the result in *res*.
  *
  *             The string may begin with an arbitrary amount of white space
- *             (as determined by isspace(3)) followed by a single optional '-'
- *             sign.
+ *             (as determined by **isspace**\ (3)) followed by a single
+ *             optional '**-**' sign.
  *
  *             Five least significant bits of *flags* encode base, other bits
  *             are currently unused.
  *
  *             Base must be either 8, 10, 16 or 0 to detect it automatically
- *             similar to user space strtol(3).
+ *             similar to user space **strtol**\ (3).
  *     Return
  *             Number of characters consumed on success. Must be positive but
- *             no more than buf_len.
+ *             no more than *buf_len*.
  *
  *             **-EINVAL** if no valid digits were found or unsupported base
  *             was provided.
@@ -2616,16 +2621,16 @@ union bpf_attr {
  *             given base and save the result in *res*.
  *
  *             The string may begin with an arbitrary amount of white space
- *             (as determined by isspace(3)).
+ *             (as determined by **isspace**\ (3)).
  *
  *             Five least significant bits of *flags* encode base, other bits
  *             are currently unused.
  *
  *             Base must be either 8, 10, 16 or 0 to detect it automatically
- *             similar to user space strtoul(3).
+ *             similar to user space **strtoul**\ (3).
  *     Return
  *             Number of characters consumed on success. Must be positive but
- *             no more than buf_len.
+ *             no more than *buf_len*.
  *
  *             **-EINVAL** if no valid digits were found or unsupported base
  *             was provided.
@@ -2634,26 +2639,26 @@ union bpf_attr {
  *
  * void *bpf_sk_storage_get(struct bpf_map *map, struct bpf_sock *sk, void *value, u64 flags)
  *     Description
- *             Get a bpf-local-storage from a sk.
+ *             Get a bpf-local-storage from a *sk*.
  *
  *             Logically, it could be thought of getting the value from
  *             a *map* with *sk* as the **key**.  From this
  *             perspective,  the usage is not much different from
- *             **bpf_map_lookup_elem(map, &sk)** except this
- *             helper enforces the key must be a **bpf_fullsock()**
- *             and the map must be a BPF_MAP_TYPE_SK_STORAGE also.
+ *             **bpf_map_lookup_elem**\ (*map*, **&**\ *sk*) except this
+ *             helper enforces the key must be a full socket and the map must
+ *             be a **BPF_MAP_TYPE_SK_STORAGE** also.
  *
  *             Underneath, the value is stored locally at *sk* instead of
- *             the map.  The *map* is used as the bpf-local-storage **type**.
- *             The bpf-local-storage **type** (i.e. the *map*) is searched
- *             against all bpf-local-storages residing at sk.
+ *             the *map*.  The *map* is used as the bpf-local-storage
+ *             "type". The bpf-local-storage "type" (i.e. the *map*) is
+ *             searched against all bpf-local-storages residing at *sk*.
  *
- *             An optional *flags* (BPF_SK_STORAGE_GET_F_CREATE) can be
+ *             An optional *flags* (**BPF_SK_STORAGE_GET_F_CREATE**) can be
  *             used such that a new bpf-local-storage will be
  *             created if one does not exist.  *value* can be used
- *             together with BPF_SK_STORAGE_GET_F_CREATE to specify
+ *             together with **BPF_SK_STORAGE_GET_F_CREATE** to specify
  *             the initial value of a bpf-local-storage.  If *value* is
- *             NULL, the new bpf-local-storage will be zero initialized.
+ *             **NULL**, the new bpf-local-storage will be zero initialized.
  *     Return
  *             A bpf-local-storage pointer is returned on success.
  *
@@ -2662,7 +2667,7 @@ union bpf_attr {
  *
  * int bpf_sk_storage_delete(struct bpf_map *map, struct bpf_sock *sk)
  *     Description
- *             Delete a bpf-local-storage from a sk.
+ *             Delete a bpf-local-storage from a *sk*.
  *     Return
  *             0 on success.
  *
index 121e82c..59c71fa 100644 (file)
@@ -320,6 +320,9 @@ struct fscrypt_key {
 #define SYNC_FILE_RANGE_WAIT_BEFORE    1
 #define SYNC_FILE_RANGE_WRITE          2
 #define SYNC_FILE_RANGE_WAIT_AFTER     4
+#define SYNC_FILE_RANGE_WRITE_AND_WAIT (SYNC_FILE_RANGE_WRITE | \
+                                        SYNC_FILE_RANGE_WAIT_BEFORE | \
+                                        SYNC_FILE_RANGE_WAIT_AFTER)
 
 /*
  * Flags for preadv2/pwritev2:
index 2ac5986..19fb55e 100644 (file)
@@ -44,6 +44,7 @@
  *  - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in
  *  - add blksize field to fuse_attr
  *  - add file flags field to fuse_read_in and fuse_write_in
+ *  - Add ATIME_NOW and MTIME_NOW flags to fuse_setattr_in
  *
  * 7.10
  *  - add nonseekable open flag
@@ -54,7 +55,7 @@
  *  - add POLL message and NOTIFY_POLL notification
  *
  * 7.12
- *  - add umask flag to input argument of open, mknod and mkdir
+ *  - add umask flag to input argument of create, mknod and mkdir
  *  - add notification messages for invalidation of inodes and
  *    directory entries
  *
  *
  *  7.29
  *  - add FUSE_NO_OPENDIR_SUPPORT flag
+ *
+ *  7.30
+ *  - add FUSE_EXPLICIT_INVAL_DATA
+ *  - add FUSE_IOCTL_COMPAT_X32
  */
 
 #ifndef _LINUX_FUSE_H
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 29
+#define FUSE_KERNEL_MINOR_VERSION 30
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -229,11 +234,13 @@ struct fuse_file_lock {
  * FOPEN_KEEP_CACHE: don't invalidate the data cache on open
  * FOPEN_NONSEEKABLE: the file is not seekable
  * FOPEN_CACHE_DIR: allow caching this directory
+ * FOPEN_STREAM: the file is stream-like (no file position at all)
  */
 #define FOPEN_DIRECT_IO                (1 << 0)
 #define FOPEN_KEEP_CACHE       (1 << 1)
 #define FOPEN_NONSEEKABLE      (1 << 2)
 #define FOPEN_CACHE_DIR                (1 << 3)
+#define FOPEN_STREAM           (1 << 4)
 
 /**
  * INIT request/reply flags
@@ -263,6 +270,7 @@ struct fuse_file_lock {
  * FUSE_MAX_PAGES: init_out.max_pages contains the max number of req pages
  * FUSE_CACHE_SYMLINKS: cache READLINK responses
  * FUSE_NO_OPENDIR_SUPPORT: kernel supports zero-message opendir
+ * FUSE_EXPLICIT_INVAL_DATA: only invalidate cached pages on explicit request
  */
 #define FUSE_ASYNC_READ                (1 << 0)
 #define FUSE_POSIX_LOCKS       (1 << 1)
@@ -289,6 +297,7 @@ struct fuse_file_lock {
 #define FUSE_MAX_PAGES         (1 << 22)
 #define FUSE_CACHE_SYMLINKS    (1 << 23)
 #define FUSE_NO_OPENDIR_SUPPORT (1 << 24)
+#define FUSE_EXPLICIT_INVAL_DATA (1 << 25)
 
 /**
  * CUSE INIT request/reply flags
@@ -335,6 +344,7 @@ struct fuse_file_lock {
  * FUSE_IOCTL_RETRY: retry with new iovecs
  * FUSE_IOCTL_32BIT: 32bit ioctl
  * FUSE_IOCTL_DIR: is a directory
+ * FUSE_IOCTL_COMPAT_X32: x32 compat ioctl on 64bit machine (64bit time_t)
  *
  * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs
  */
@@ -343,6 +353,7 @@ struct fuse_file_lock {
 #define FUSE_IOCTL_RETRY       (1 << 2)
 #define FUSE_IOCTL_32BIT       (1 << 3)
 #define FUSE_IOCTL_DIR         (1 << 4)
+#define FUSE_IOCTL_COMPAT_X32  (1 << 5)
 
 #define FUSE_IOCTL_MAX_IOV     256
 
@@ -353,6 +364,13 @@ struct fuse_file_lock {
  */
 #define FUSE_POLL_SCHEDULE_NOTIFY (1 << 0)
 
+/**
+ * Fsync flags
+ *
+ * FUSE_FSYNC_FDATASYNC: Sync data only, not metadata
+ */
+#define FUSE_FSYNC_FDATASYNC   (1 << 0)
+
 enum fuse_opcode {
        FUSE_LOOKUP             = 1,
        FUSE_FORGET             = 2,  /* no reply */
index 64cee11..85387c7 100644 (file)
 #define KEY_SCREENSAVER                0x245   /* AL Screen Saver */
 #define KEY_VOICECOMMAND               0x246   /* Listening Voice Command */
 #define KEY_ASSISTANT          0x247   /* AL Context-aware desktop assistant */
+#define KEY_KBD_LAYOUT_NEXT    0x248   /* AC Next Keyboard Layout Select */
 
 #define KEY_BRIGHTNESS_MIN             0x250   /* Set Brightness to Minimum */
 #define KEY_BRIGHTNESS_MAX             0x251   /* Set Brightness to Maximum */
index f0cf7b0..505393c 100644 (file)
@@ -966,7 +966,6 @@ enum nft_socket_keys {
  * @NFT_CT_DST_IP: conntrack layer 3 protocol destination (IPv4 address)
  * @NFT_CT_SRC_IP6: conntrack layer 3 protocol source (IPv6 address)
  * @NFT_CT_DST_IP6: conntrack layer 3 protocol destination (IPv6 address)
- * @NFT_CT_TIMEOUT: connection tracking timeout policy assigned to conntrack
  * @NFT_CT_ID: conntrack id
  */
 enum nft_ct_keys {
@@ -993,7 +992,6 @@ enum nft_ct_keys {
        NFT_CT_DST_IP,
        NFT_CT_SRC_IP6,
        NFT_CT_DST_IP6,
-       NFT_CT_TIMEOUT,
        NFT_CT_ID,
        __NFT_CT_MAX
 };
@@ -1138,7 +1136,7 @@ enum nft_log_level {
        NFT_LOGLEVEL_AUDIT,
        __NFT_LOGLEVEL_MAX
 };
-#define NFT_LOGLEVEL_MAX       (__NFT_LOGLEVEL_MAX + 1)
+#define NFT_LOGLEVEL_MAX       (__NFT_LOGLEVEL_MAX - 1)
 
 /**
  * enum nft_queue_attributes - nf_tables queue expression netlink attributes
index f8f5ccc..b1e9de4 100644 (file)
@@ -36,6 +36,7 @@ enum cld_command {
        Cld_Remove,             /* remove record of this cm_id */
        Cld_Check,              /* is this cm_id allowed? */
        Cld_GraceDone,          /* grace period is complete */
+       Cld_GraceStart,
 };
 
 /* representation of long-form NFSv4 client ID */
index 5c98133..2716476 100644 (file)
@@ -1,7 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 /*
- *     pci_regs.h
- *
  *     PCI standard defines
  *     Copyright 1994, Drew Eckhardt
  *     Copyright 1997--1999 Martin Mares <mj@ucw.cz>
@@ -15,7 +13,7 @@
  *     PCI System Design Guide
  *
  *     For HyperTransport information, please consult the following manuals
- *     from http://www.hypertransport.org
+ *     from http://www.hypertransport.org :
  *
  *     The HyperTransport I/O Link Specification
  */
 #define  PCI_SID_ESR_FIC       0x20    /* First In Chassis Flag */
 #define PCI_SID_CHASSIS_NR     3       /* Chassis Number */
 
-/* Message Signalled Interrupts registers */
+/* Message Signalled Interrupt registers */
 
 #define PCI_MSI_FLAGS          2       /* Message Control */
 #define  PCI_MSI_FLAGS_ENABLE  0x0001  /* MSI feature enabled */
 #define PCI_MSI_MASK_64                16      /* Mask bits register for 64-bit devices */
 #define PCI_MSI_PENDING_64     20      /* Pending intrs for 64-bit devices */
 
-/* MSI-X registers */
+/* MSI-X registers (in MSI-X capability) */
 #define PCI_MSIX_FLAGS         2       /* Message Control */
 #define  PCI_MSIX_FLAGS_QSIZE  0x07FF  /* Table size */
 #define  PCI_MSIX_FLAGS_MASKALL        0x4000  /* Mask all vectors for this function */
 #define PCI_MSIX_FLAGS_BIRMASK PCI_MSIX_PBA_BIR /* deprecated */
 #define PCI_CAP_MSIX_SIZEOF    12      /* size of MSIX registers */
 
-/* MSI-X Table entry format */
+/* MSI-X Table entry format (in memory mapped by a BAR) */
 #define PCI_MSIX_ENTRY_SIZE            16
-#define  PCI_MSIX_ENTRY_LOWER_ADDR     0
-#define  PCI_MSIX_ENTRY_UPPER_ADDR     4
-#define  PCI_MSIX_ENTRY_DATA           8
-#define  PCI_MSIX_ENTRY_VECTOR_CTRL    12
-#define   PCI_MSIX_ENTRY_CTRL_MASKBIT  1
+#define PCI_MSIX_ENTRY_LOWER_ADDR      0  /* Message Address */
+#define PCI_MSIX_ENTRY_UPPER_ADDR      4  /* Message Upper Address */
+#define PCI_MSIX_ENTRY_DATA            8  /* Message Data */
+#define PCI_MSIX_ENTRY_VECTOR_CTRL     12 /* Vector Control */
+#define  PCI_MSIX_ENTRY_CTRL_MASKBIT   0x00000001
 
 /* CompactPCI Hotswap Register */
 
 #define PCI_EA_FIRST_ENT_BRIDGE        8       /* First EA Entry for Bridges */
 #define  PCI_EA_ES             0x00000007 /* Entry Size */
 #define  PCI_EA_BEI            0x000000f0 /* BAR Equivalent Indicator */
+
+/* EA fixed Secondary and Subordinate bus numbers for Bridge */
+#define PCI_EA_SEC_BUS_MASK    0xff
+#define PCI_EA_SUB_BUS_MASK    0xff00
+#define PCI_EA_SUB_BUS_SHIFT   8
+
 /* 0-5 map to BARs 0-5 respectively */
 #define   PCI_EA_BEI_BAR0              0
 #define   PCI_EA_BEI_BAR5              5
 /* PCI Express capability registers */
 
 #define PCI_EXP_FLAGS          2       /* Capabilities register */
-#define PCI_EXP_FLAGS_VERS     0x000f  /* Capability version */
-#define PCI_EXP_FLAGS_TYPE     0x00f0  /* Device/Port type */
-#define  PCI_EXP_TYPE_ENDPOINT 0x0     /* Express Endpoint */
-#define  PCI_EXP_TYPE_LEG_END  0x1     /* Legacy Endpoint */
-#define  PCI_EXP_TYPE_ROOT_PORT 0x4    /* Root Port */
-#define  PCI_EXP_TYPE_UPSTREAM 0x5     /* Upstream Port */
-#define  PCI_EXP_TYPE_DOWNSTREAM 0x6   /* Downstream Port */
-#define  PCI_EXP_TYPE_PCI_BRIDGE 0x7   /* PCIe to PCI/PCI-X Bridge */
-#define  PCI_EXP_TYPE_PCIE_BRIDGE 0x8  /* PCI/PCI-X to PCIe Bridge */
-#define  PCI_EXP_TYPE_RC_END   0x9     /* Root Complex Integrated Endpoint */
-#define  PCI_EXP_TYPE_RC_EC    0xa     /* Root Complex Event Collector */
-#define PCI_EXP_FLAGS_SLOT     0x0100  /* Slot implemented */
-#define PCI_EXP_FLAGS_IRQ      0x3e00  /* Interrupt message number */
+#define  PCI_EXP_FLAGS_VERS    0x000f  /* Capability version */
+#define  PCI_EXP_FLAGS_TYPE    0x00f0  /* Device/Port type */
+#define   PCI_EXP_TYPE_ENDPOINT           0x0  /* Express Endpoint */
+#define   PCI_EXP_TYPE_LEG_END    0x1  /* Legacy Endpoint */
+#define   PCI_EXP_TYPE_ROOT_PORT   0x4 /* Root Port */
+#define   PCI_EXP_TYPE_UPSTREAM           0x5  /* Upstream Port */
+#define   PCI_EXP_TYPE_DOWNSTREAM  0x6 /* Downstream Port */
+#define   PCI_EXP_TYPE_PCI_BRIDGE  0x7 /* PCIe to PCI/PCI-X Bridge */
+#define   PCI_EXP_TYPE_PCIE_BRIDGE 0x8 /* PCI/PCI-X to PCIe Bridge */
+#define   PCI_EXP_TYPE_RC_END     0x9  /* Root Complex Integrated Endpoint */
+#define   PCI_EXP_TYPE_RC_EC      0xa  /* Root Complex Event Collector */
+#define  PCI_EXP_FLAGS_SLOT    0x0100  /* Slot implemented */
+#define  PCI_EXP_FLAGS_IRQ     0x3e00  /* Interrupt message number */
 #define PCI_EXP_DEVCAP         4       /* Device capabilities */
 #define  PCI_EXP_DEVCAP_PAYLOAD        0x00000007 /* Max_Payload_Size */
 #define  PCI_EXP_DEVCAP_PHANTOM        0x00000018 /* Phantom functions */
 #define PCI_EXP_RTCAP          30      /* Root Capabilities */
 #define  PCI_EXP_RTCAP_CRSVIS  0x0001  /* CRS Software Visibility capability */
 #define PCI_EXP_RTSTA          32      /* Root Status */
-#define PCI_EXP_RTSTA_PME      0x00010000 /* PME status */
-#define PCI_EXP_RTSTA_PENDING  0x00020000 /* PME pending */
+#define  PCI_EXP_RTSTA_PME     0x00010000 /* PME status */
+#define  PCI_EXP_RTSTA_PENDING 0x00020000 /* PME pending */
 /*
  * The Device Capabilities 2, Device Status 2, Device Control 2,
  * Link Capabilities 2, Link Status 2, Link Control 2,
 #define  PCI_EXP_DEVCAP2_OBFF_MASK     0x000c0000 /* OBFF support mechanism */
 #define  PCI_EXP_DEVCAP2_OBFF_MSG      0x00040000 /* New message signaling */
 #define  PCI_EXP_DEVCAP2_OBFF_WAKE     0x00080000 /* Re-use WAKE# for OBFF */
-#define PCI_EXP_DEVCAP2_EE_PREFIX      0x00200000 /* End-End TLP Prefix */
+#define  PCI_EXP_DEVCAP2_EE_PREFIX     0x00200000 /* End-End TLP Prefix */
 #define PCI_EXP_DEVCTL2                40      /* Device Control 2 */
 #define  PCI_EXP_DEVCTL2_COMP_TIMEOUT  0x000f  /* Completion Timeout Value */
 #define  PCI_EXP_DEVCTL2_COMP_TMOUT_DIS        0x0010  /* Completion Timeout Disable */
 #define  PCI_EXP_DEVCTL2_ARI           0x0020  /* Alternative Routing-ID */
-#define PCI_EXP_DEVCTL2_ATOMIC_REQ     0x0040  /* Set Atomic requests */
-#define PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK 0x0080 /* Block atomic egress */
+#define  PCI_EXP_DEVCTL2_ATOMIC_REQ    0x0040  /* Set Atomic requests */
+#define  PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK 0x0080 /* Block atomic egress */
 #define  PCI_EXP_DEVCTL2_IDO_REQ_EN    0x0100  /* Allow IDO for requests */
 #define  PCI_EXP_DEVCTL2_IDO_CMP_EN    0x0200  /* Allow IDO for completions */
 #define  PCI_EXP_DEVCTL2_LTR_EN                0x0400  /* Enable LTR mechanism */
 #define  PCI_EXP_LNKCAP2_SLS_16_0GB    0x00000010 /* Supported Speed 16GT/s */
 #define  PCI_EXP_LNKCAP2_CROSSLINK     0x00000100 /* Crosslink supported */
 #define PCI_EXP_LNKCTL2                48      /* Link Control 2 */
-#define PCI_EXP_LNKCTL2_TLS            0x000f
-#define PCI_EXP_LNKCTL2_TLS_2_5GT      0x0001 /* Supported Speed 2.5GT/s */
-#define PCI_EXP_LNKCTL2_TLS_5_0GT      0x0002 /* Supported Speed 5GT/s */
-#define PCI_EXP_LNKCTL2_TLS_8_0GT      0x0003 /* Supported Speed 8GT/s */
-#define PCI_EXP_LNKCTL2_TLS_16_0GT     0x0004 /* Supported Speed 16GT/s */
+#define  PCI_EXP_LNKCTL2_TLS           0x000f
+#define  PCI_EXP_LNKCTL2_TLS_2_5GT     0x0001 /* Supported Speed 2.5GT/s */
+#define  PCI_EXP_LNKCTL2_TLS_5_0GT     0x0002 /* Supported Speed 5GT/s */
+#define  PCI_EXP_LNKCTL2_TLS_8_0GT     0x0003 /* Supported Speed 8GT/s */
+#define  PCI_EXP_LNKCTL2_TLS_16_0GT    0x0004 /* Supported Speed 16GT/s */
 #define PCI_EXP_LNKSTA2                50      /* Link Status 2 */
 #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 52      /* v2 endpoints with link end here */
 #define PCI_EXP_SLTCAP2                52      /* Slot Capabilities 2 */
 #define  PCI_ERR_CAP_ECRC_CHKE 0x00000100      /* ECRC Check Enable */
 #define PCI_ERR_HEADER_LOG     28      /* Header Log Register (16 bytes) */
 #define PCI_ERR_ROOT_COMMAND   44      /* Root Error Command */
-#define PCI_ERR_ROOT_CMD_COR_EN                0x00000001 /* Correctable Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_NONFATAL_EN   0x00000002 /* Non-Fatal Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_FATAL_EN      0x00000004 /* Fatal Err Reporting Enable */
+#define  PCI_ERR_ROOT_CMD_COR_EN       0x00000001 /* Correctable Err Reporting Enable */
+#define  PCI_ERR_ROOT_CMD_NONFATAL_EN  0x00000002 /* Non-Fatal Err Reporting Enable */
+#define  PCI_ERR_ROOT_CMD_FATAL_EN     0x00000004 /* Fatal Err Reporting Enable */
 #define PCI_ERR_ROOT_STATUS    48
-#define PCI_ERR_ROOT_COR_RCV           0x00000001 /* ERR_COR Received */
-#define PCI_ERR_ROOT_MULTI_COR_RCV     0x00000002 /* Multiple ERR_COR */
-#define PCI_ERR_ROOT_UNCOR_RCV         0x00000004 /* ERR_FATAL/NONFATAL */
-#define PCI_ERR_ROOT_MULTI_UNCOR_RCV   0x00000008 /* Multiple FATAL/NONFATAL */
-#define PCI_ERR_ROOT_FIRST_FATAL       0x00000010 /* First UNC is Fatal */
-#define PCI_ERR_ROOT_NONFATAL_RCV      0x00000020 /* Non-Fatal Received */
-#define PCI_ERR_ROOT_FATAL_RCV         0x00000040 /* Fatal Received */
-#define PCI_ERR_ROOT_AER_IRQ           0xf8000000 /* Advanced Error Interrupt Message Number */
+#define  PCI_ERR_ROOT_COR_RCV          0x00000001 /* ERR_COR Received */
+#define  PCI_ERR_ROOT_MULTI_COR_RCV    0x00000002 /* Multiple ERR_COR */
+#define  PCI_ERR_ROOT_UNCOR_RCV                0x00000004 /* ERR_FATAL/NONFATAL */
+#define  PCI_ERR_ROOT_MULTI_UNCOR_RCV  0x00000008 /* Multiple FATAL/NONFATAL */
+#define  PCI_ERR_ROOT_FIRST_FATAL      0x00000010 /* First UNC is Fatal */
+#define  PCI_ERR_ROOT_NONFATAL_RCV     0x00000020 /* Non-Fatal Received */
+#define  PCI_ERR_ROOT_FATAL_RCV                0x00000040 /* Fatal Received */
+#define  PCI_ERR_ROOT_AER_IRQ          0xf8000000 /* Advanced Error Interrupt Message Number */
 #define PCI_ERR_ROOT_ERR_SRC   52      /* Error Source Identification */
 
 /* Virtual Channel */
 
 /* Page Request Interface */
 #define PCI_PRI_CTRL           0x04    /* PRI control register */
-#define  PCI_PRI_CTRL_ENABLE   0x01    /* Enable */
-#define  PCI_PRI_CTRL_RESET    0x02    /* Reset */
+#define  PCI_PRI_CTRL_ENABLE   0x0001  /* Enable */
+#define  PCI_PRI_CTRL_RESET    0x0002  /* Reset */
 #define PCI_PRI_STATUS         0x06    /* PRI status register */
-#define  PCI_PRI_STATUS_RF     0x00  /* Response Failure */
-#define  PCI_PRI_STATUS_UPRGI  0x00  /* Unexpected PRG index */
-#define  PCI_PRI_STATUS_STOPPED        0x100   /* PRI Stopped */
+#define  PCI_PRI_STATUS_RF     0x0001  /* Response Failure */
+#define  PCI_PRI_STATUS_UPRGI  0x0002  /* Unexpected PRG index */
+#define  PCI_PRI_STATUS_STOPPED        0x0100  /* PRI Stopped */
 #define  PCI_PRI_STATUS_PASID  0x8000  /* PRG Response PASID Required */
 #define PCI_PRI_MAX_REQ                0x08    /* PRI max reqs supported */
 #define PCI_PRI_ALLOC_REQ      0x0c    /* PRI max reqs allowed */
 
 /* Single Root I/O Virtualization */
 #define PCI_SRIOV_CAP          0x04    /* SR-IOV Capabilities */
-#define  PCI_SRIOV_CAP_VFM     0x01    /* VF Migration Capable */
+#define  PCI_SRIOV_CAP_VFM     0x00000001  /* VF Migration Capable */
 #define  PCI_SRIOV_CAP_INTR(x) ((x) >> 21) /* Interrupt Message Number */
 #define PCI_SRIOV_CTRL         0x08    /* SR-IOV Control */
-#define  PCI_SRIOV_CTRL_VFE    0x01    /* VF Enable */
-#define  PCI_SRIOV_CTRL_VFM    0x02    /* VF Migration Enable */
-#define  PCI_SRIOV_CTRL_INTR   0x04    /* VF Migration Interrupt Enable */
-#define  PCI_SRIOV_CTRL_MSE    0x08    /* VF Memory Space Enable */
-#define  PCI_SRIOV_CTRL_ARI    0x10    /* ARI Capable Hierarchy */
+#define  PCI_SRIOV_CTRL_VFE    0x0001  /* VF Enable */
+#define  PCI_SRIOV_CTRL_VFM    0x0002  /* VF Migration Enable */
+#define  PCI_SRIOV_CTRL_INTR   0x0004  /* VF Migration Interrupt Enable */
+#define  PCI_SRIOV_CTRL_MSE    0x0008  /* VF Memory Space Enable */
+#define  PCI_SRIOV_CTRL_ARI    0x0010  /* ARI Capable Hierarchy */
 #define PCI_SRIOV_STATUS       0x0a    /* SR-IOV Status */
-#define  PCI_SRIOV_STATUS_VFM  0x01    /* VF Migration Status */
+#define  PCI_SRIOV_STATUS_VFM  0x0001  /* VF Migration Status */
 #define PCI_SRIOV_INITIAL_VF   0x0c    /* Initial VFs */
 #define PCI_SRIOV_TOTAL_VF     0x0e    /* Total VFs */
 #define PCI_SRIOV_NUM_VF       0x10    /* Number of VFs */
 
 /* Access Control Service */
 #define PCI_ACS_CAP            0x04    /* ACS Capability Register */
-#define  PCI_ACS_SV            0x01    /* Source Validation */
-#define  PCI_ACS_TB            0x02    /* Translation Blocking */
-#define  PCI_ACS_RR            0x04    /* P2P Request Redirect */
-#define  PCI_ACS_CR            0x08    /* P2P Completion Redirect */
-#define  PCI_ACS_UF            0x10    /* Upstream Forwarding */
-#define  PCI_ACS_EC            0x20    /* P2P Egress Control */
-#define  PCI_ACS_DT            0x40    /* Direct Translated P2P */
+#define  PCI_ACS_SV            0x0001  /* Source Validation */
+#define  PCI_ACS_TB            0x0002  /* Translation Blocking */
+#define  PCI_ACS_RR            0x0004  /* P2P Request Redirect */
+#define  PCI_ACS_CR            0x0008  /* P2P Completion Redirect */
+#define  PCI_ACS_UF            0x0010  /* Upstream Forwarding */
+#define  PCI_ACS_EC            0x0020  /* P2P Egress Control */
+#define  PCI_ACS_DT            0x0040  /* Direct Translated P2P */
 #define PCI_ACS_EGRESS_BITS    0x05    /* ACS Egress Control Vector Size */
 #define PCI_ACS_CTRL           0x06    /* ACS Control Register */
 #define PCI_ACS_EGRESS_CTL_V   0x08    /* ACS Egress Control Vector */
 #define  PCI_EXP_DPC_CAP_DL_ACTIVE     0x1000  /* ERR_COR signal on DL_Active supported */
 
 #define PCI_EXP_DPC_CTL                        6       /* DPC control */
-#define  PCI_EXP_DPC_CTL_EN_FATAL      0x0001  /* Enable trigger on ERR_FATAL message */
-#define  PCI_EXP_DPC_CTL_EN_NONFATAL   0x0002  /* Enable trigger on ERR_NONFATAL message */
-#define  PCI_EXP_DPC_CTL_INT_EN        0x0008  /* DPC Interrupt Enable */
+#define  PCI_EXP_DPC_CTL_EN_FATAL      0x0001  /* Enable trigger on ERR_FATAL message */
+#define  PCI_EXP_DPC_CTL_EN_NONFATAL   0x0002  /* Enable trigger on ERR_NONFATAL message */
+#define  PCI_EXP_DPC_CTL_INT_EN                0x0008  /* DPC Interrupt Enable */
 
 #define PCI_EXP_DPC_STATUS             8       /* DPC Status */
 #define  PCI_EXP_DPC_STATUS_TRIGGER        0x0001 /* Trigger Status */
index 4f4daf8..c912b5a 100644 (file)
@@ -50,7 +50,7 @@ struct switchtec_ioctl_flash_part_info {
        __u32 active;
 };
 
-struct switchtec_ioctl_event_summary {
+struct switchtec_ioctl_event_summary_legacy {
        __u64 global;
        __u64 part_bitmap;
        __u32 local_part;
@@ -59,6 +59,15 @@ struct switchtec_ioctl_event_summary {
        __u32 pff[48];
 };
 
+struct switchtec_ioctl_event_summary {
+       __u64 global;
+       __u64 part_bitmap;
+       __u32 local_part;
+       __u32 padding;
+       __u32 part[48];
+       __u32 pff[255];
+};
+
 #define SWITCHTEC_IOCTL_EVENT_STACK_ERROR              0
 #define SWITCHTEC_IOCTL_EVENT_PPU_ERROR                        1
 #define SWITCHTEC_IOCTL_EVENT_ISP_ERROR                        2
@@ -127,6 +136,8 @@ struct switchtec_ioctl_pff_port {
        _IOWR('W', 0x41, struct switchtec_ioctl_flash_part_info)
 #define SWITCHTEC_IOCTL_EVENT_SUMMARY \
        _IOR('W', 0x42, struct switchtec_ioctl_event_summary)
+#define SWITCHTEC_IOCTL_EVENT_SUMMARY_LEGACY \
+       _IOR('W', 0x42, struct switchtec_ioctl_event_summary_legacy)
 #define SWITCHTEC_IOCTL_EVENT_CTL \
        _IOWR('W', 0x43, struct switchtec_ioctl_event_ctl)
 #define SWITCHTEC_IOCTL_PFF_TO_PORT \
index 42a8bdc..41db513 100644 (file)
@@ -250,7 +250,7 @@ enum rdma_nldev_command {
 
        RDMA_NLDEV_CMD_PORT_GET, /* can dump */
 
-       RDMA_NLDEV_CMD_SYS_GET, /* can dump */
+       RDMA_NLDEV_CMD_SYS_GET,
        RDMA_NLDEV_CMD_SYS_SET,
 
        /* 8 is free to use */
index 82b84e5..8b9ffe2 100644 (file)
@@ -1752,6 +1752,30 @@ config SLAB_FREELIST_HARDENED
          sacrifies to harden the kernel slab allocator against common
          freelist exploit methods.
 
+config SHUFFLE_PAGE_ALLOCATOR
+       bool "Page allocator randomization"
+       default SLAB_FREELIST_RANDOM && ACPI_NUMA
+       help
+         Randomization of the page allocator improves the average
+         utilization of a direct-mapped memory-side-cache. See section
+         5.2.27 Heterogeneous Memory Attribute Table (HMAT) in the ACPI
+         6.2a specification for an example of how a platform advertises
+         the presence of a memory-side-cache. There are also incidental
+         security benefits as it reduces the predictability of page
+         allocations to compliment SLAB_FREELIST_RANDOM, but the
+         default granularity of shuffling on the "MAX_ORDER - 1" i.e,
+         10th order of pages is selected based on cache utilization
+         benefits on x86.
+
+         While the randomization improves cache utilization it may
+         negatively impact workloads on platforms without a cache. For
+         this reason, by default, the randomization is enabled only
+         after runtime detection of a direct-mapped memory-side-cache.
+         Otherwise, the randomization may be force enabled with the
+         'page_alloc.shuffle' kernel command line parameter.
+
+         Say Y if unsure.
+
 config SLUB_CPU_PARTIAL
        default y
        depends on SLUB && SMP
index 4749e11..435a428 100644 (file)
@@ -513,42 +513,55 @@ static int __init retain_initrd_param(char *str)
 }
 __setup("retain_initrd", retain_initrd_param);
 
+#ifdef CONFIG_ARCH_HAS_KEEPINITRD
+static int __init keepinitrd_setup(char *__unused)
+{
+       do_retain_initrd = 1;
+       return 1;
+}
+__setup("keepinitrd", keepinitrd_setup);
+#endif
+
 extern char __initramfs_start[];
 extern unsigned long __initramfs_size;
 #include <linux/initrd.h>
 #include <linux/kexec.h>
 
-static void __init free_initrd(void)
+void __weak free_initrd_mem(unsigned long start, unsigned long end)
 {
+       free_reserved_area((void *)start, (void *)end, POISON_FREE_INITMEM,
+                       "initrd");
+}
+
 #ifdef CONFIG_KEXEC_CORE
+static bool kexec_free_initrd(void)
+{
        unsigned long crashk_start = (unsigned long)__va(crashk_res.start);
        unsigned long crashk_end   = (unsigned long)__va(crashk_res.end);
-#endif
-       if (do_retain_initrd)
-               goto skip;
 
-#ifdef CONFIG_KEXEC_CORE
        /*
         * If the initrd region is overlapped with crashkernel reserved region,
         * free only memory that is not part of crashkernel region.
         */
-       if (initrd_start < crashk_end && initrd_end > crashk_start) {
-               /*
-                * Initialize initrd memory region since the kexec boot does
-                * not do.
-                */
-               memset((void *)initrd_start, 0, initrd_end - initrd_start);
-               if (initrd_start < crashk_start)
-                       free_initrd_mem(initrd_start, crashk_start);
-               if (initrd_end > crashk_end)
-                       free_initrd_mem(crashk_end, initrd_end);
-       } else
-#endif
-               free_initrd_mem(initrd_start, initrd_end);
-skip:
-       initrd_start = 0;
-       initrd_end = 0;
+       if (initrd_start >= crashk_end || initrd_end <= crashk_start)
+               return false;
+
+       /*
+        * Initialize initrd memory region since the kexec boot does not do.
+        */
+       memset((void *)initrd_start, 0, initrd_end - initrd_start);
+       if (initrd_start < crashk_start)
+               free_initrd_mem(initrd_start, crashk_start);
+       if (initrd_end > crashk_end)
+               free_initrd_mem(crashk_end, initrd_end);
+       return true;
+}
+#else
+static inline bool kexec_free_initrd(void)
+{
+       return false;
 }
+#endif /* CONFIG_KEXEC_CORE */
 
 #ifdef CONFIG_BLK_DEV_RAM
 #define BUF_SIZE 1024
@@ -597,7 +610,38 @@ static void __init clean_rootfs(void)
        ksys_close(fd);
        kfree(buf);
 }
-#endif
+#else
+static inline void clean_rootfs(void)
+{
+}
+#endif /* CONFIG_BLK_DEV_RAM */
+
+#ifdef CONFIG_BLK_DEV_RAM
+static void populate_initrd_image(char *err)
+{
+       ssize_t written;
+       int fd;
+
+       unpack_to_rootfs(__initramfs_start, __initramfs_size);
+
+       printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n",
+                       err);
+       fd = ksys_open("/initrd.image", O_WRONLY | O_CREAT, 0700);
+       if (fd < 0)
+               return;
+
+       written = xwrite(fd, (char *)initrd_start, initrd_end - initrd_start);
+       if (written != initrd_end - initrd_start)
+               pr_err("/initrd.image: incomplete write (%zd != %ld)\n",
+                      written, initrd_end - initrd_start);
+       ksys_close(fd);
+}
+#else
+static void populate_initrd_image(char *err)
+{
+       printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
+}
+#endif /* CONFIG_BLK_DEV_RAM */
 
 static int __init populate_rootfs(void)
 {
@@ -605,46 +649,31 @@ static int __init populate_rootfs(void)
        char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);
        if (err)
                panic("%s", err); /* Failed to decompress INTERNAL initramfs */
-       /* If available load the bootloader supplied initrd */
-       if (initrd_start && !IS_ENABLED(CONFIG_INITRAMFS_FORCE)) {
-#ifdef CONFIG_BLK_DEV_RAM
-               int fd;
+
+       if (!initrd_start || IS_ENABLED(CONFIG_INITRAMFS_FORCE))
+               goto done;
+
+       if (IS_ENABLED(CONFIG_BLK_DEV_RAM))
                printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");
-               err = unpack_to_rootfs((char *)initrd_start,
-                       initrd_end - initrd_start);
-               if (!err) {
-                       free_initrd();
-                       goto done;
-               } else {
-                       clean_rootfs();
-                       unpack_to_rootfs(__initramfs_start, __initramfs_size);
-               }
-               printk(KERN_INFO "rootfs image is not initramfs (%s)"
-                               "; looks like an initrd\n", err);
-               fd = ksys_open("/initrd.image",
-                             O_WRONLY|O_CREAT, 0700);
-               if (fd >= 0) {
-                       ssize_t written = xwrite(fd, (char *)initrd_start,
-                                               initrd_end - initrd_start);
-
-                       if (written != initrd_end - initrd_start)
-                               pr_err("/initrd.image: incomplete write (%zd != %ld)\n",
-                                      written, initrd_end - initrd_start);
-
-                       ksys_close(fd);
-                       free_initrd();
-               }
-       done:
-               /* empty statement */;
-#else
+       else
                printk(KERN_INFO "Unpacking initramfs...\n");
-               err = unpack_to_rootfs((char *)initrd_start,
-                       initrd_end - initrd_start);
-               if (err)
-                       printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
-               free_initrd();
-#endif
+
+       err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start);
+       if (err) {
+               clean_rootfs();
+               populate_initrd_image(err);
        }
+
+done:
+       /*
+        * If the initrd region is overlapped with crashkernel reserved region,
+        * free only memory that is not part of crashkernel region.
+        */
+       if (!do_retain_initrd && !kexec_free_initrd())
+               free_initrd_mem(initrd_start, initrd_end);
+       initrd_start = 0;
+       initrd_end = 0;
+
        flush_delayed_fput();
        return 0;
 }
index 33c87e9..5a2c69b 100644 (file)
@@ -1074,6 +1074,11 @@ static inline void mark_readonly(void)
 }
 #endif
 
+void __weak free_initmem(void)
+{
+       free_initmem_default(POISON_FREE_INITMEM);
+}
+
 static int __ref kernel_init(void *unused)
 {
        int ret;
index 49f9bf4..bfaae45 100644 (file)
@@ -120,7 +120,9 @@ static int proc_ipc_sem_dointvec(struct ctl_table *table, int write,
 static int zero;
 static int one = 1;
 static int int_max = INT_MAX;
-static int ipc_mni = IPCMNI;
+int ipc_mni = IPCMNI;
+int ipc_mni_shift = IPCMNI_SHIFT;
+int ipc_min_cycle = RADIX_TREE_MAP_SIZE;
 
 static struct ctl_table ipc_kern_table[] = {
        {
@@ -246,3 +248,13 @@ static int __init ipc_sysctl_init(void)
 }
 
 device_initcall(ipc_sysctl_init);
+
+static int __init ipc_mni_extend(char *str)
+{
+       ipc_mni = IPCMNI_EXTEND;
+       ipc_mni_shift = IPCMNI_EXTEND_SHIFT;
+       ipc_min_cycle = IPCMNI_EXTEND_MIN_CYCLE;
+       pr_info("IPCMNI extended to %d.\n", ipc_mni);
+       return 0;
+}
+early_param("ipcmni_extend", ipc_mni_extend);
index ba44164..216cad1 100644 (file)
@@ -76,6 +76,7 @@ struct mqueue_inode_info {
        wait_queue_head_t wait_q;
 
        struct rb_root msg_tree;
+       struct rb_node *msg_tree_rightmost;
        struct posix_msg_tree_node *node_cache;
        struct mq_attr attr;
 
@@ -131,6 +132,7 @@ static int msg_insert(struct msg_msg *msg, struct mqueue_inode_info *info)
 {
        struct rb_node **p, *parent = NULL;
        struct posix_msg_tree_node *leaf;
+       bool rightmost = true;
 
        p = &info->msg_tree.rb_node;
        while (*p) {
@@ -139,9 +141,10 @@ static int msg_insert(struct msg_msg *msg, struct mqueue_inode_info *info)
 
                if (likely(leaf->priority == msg->m_type))
                        goto insert_msg;
-               else if (msg->m_type < leaf->priority)
+               else if (msg->m_type < leaf->priority) {
                        p = &(*p)->rb_left;
-               else
+                       rightmost = false;
+               } else
                        p = &(*p)->rb_right;
        }
        if (info->node_cache) {
@@ -154,6 +157,10 @@ static int msg_insert(struct msg_msg *msg, struct mqueue_inode_info *info)
                INIT_LIST_HEAD(&leaf->msg_list);
        }
        leaf->priority = msg->m_type;
+
+       if (rightmost)
+               info->msg_tree_rightmost = &leaf->rb_node;
+
        rb_link_node(&leaf->rb_node, parent, p);
        rb_insert_color(&leaf->rb_node, &info->msg_tree);
 insert_msg:
@@ -163,23 +170,35 @@ insert_msg:
        return 0;
 }
 
+static inline void msg_tree_erase(struct posix_msg_tree_node *leaf,
+                                 struct mqueue_inode_info *info)
+{
+       struct rb_node *node = &leaf->rb_node;
+
+       if (info->msg_tree_rightmost == node)
+               info->msg_tree_rightmost = rb_prev(node);
+
+       rb_erase(node, &info->msg_tree);
+       if (info->node_cache) {
+               kfree(leaf);
+       } else {
+               info->node_cache = leaf;
+       }
+}
+
 static inline struct msg_msg *msg_get(struct mqueue_inode_info *info)
 {
-       struct rb_node **p, *parent = NULL;
+       struct rb_node *parent = NULL;
        struct posix_msg_tree_node *leaf;
        struct msg_msg *msg;
 
 try_again:
-       p = &info->msg_tree.rb_node;
-       while (*p) {
-               parent = *p;
-               /*
-                * During insert, low priorities go to the left and high to the
-                * right.  On receive, we want the highest priorities first, so
-                * walk all the way to the right.
-                */
-               p = &(*p)->rb_right;
-       }
+       /*
+        * During insert, low priorities go to the left and high to the
+        * right.  On receive, we want the highest priorities first, so
+        * walk all the way to the right.
+        */
+       parent = info->msg_tree_rightmost;
        if (!parent) {
                if (info->attr.mq_curmsgs) {
                        pr_warn_once("Inconsistency in POSIX message queue, "
@@ -194,24 +213,14 @@ try_again:
                pr_warn_once("Inconsistency in POSIX message queue, "
                             "empty leaf node but we haven't implemented "
                             "lazy leaf delete!\n");
-               rb_erase(&leaf->rb_node, &info->msg_tree);
-               if (info->node_cache) {
-                       kfree(leaf);
-               } else {
-                       info->node_cache = leaf;
-               }
+               msg_tree_erase(leaf, info);
                goto try_again;
        } else {
                msg = list_first_entry(&leaf->msg_list,
                                       struct msg_msg, m_list);
                list_del(&msg->m_list);
                if (list_empty(&leaf->msg_list)) {
-                       rb_erase(&leaf->rb_node, &info->msg_tree);
-                       if (info->node_cache) {
-                               kfree(leaf);
-                       } else {
-                               info->node_cache = leaf;
-                       }
+                       msg_tree_erase(leaf, info);
                }
        }
        info->attr.mq_curmsgs--;
@@ -254,6 +263,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
                info->qsize = 0;
                info->user = NULL;      /* set when all is ok */
                info->msg_tree = RB_ROOT;
+               info->msg_tree_rightmost = NULL;
                info->node_cache = NULL;
                memset(&info->attr, 0, sizeof(info->attr));
                info->attr.mq_maxmsg = min(ipc_ns->mq_msg_max,
@@ -430,7 +440,8 @@ static void mqueue_evict_inode(struct inode *inode)
        struct user_struct *user;
        unsigned long mq_bytes, mq_treesize;
        struct ipc_namespace *ipc_ns;
-       struct msg_msg *msg;
+       struct msg_msg *msg, *nmsg;
+       LIST_HEAD(tmp_msg);
 
        clear_inode(inode);
 
@@ -441,10 +452,15 @@ static void mqueue_evict_inode(struct inode *inode)
        info = MQUEUE_I(inode);
        spin_lock(&info->lock);
        while ((msg = msg_get(info)) != NULL)
-               free_msg(msg);
+               list_add_tail(&msg->m_list, &tmp_msg);
        kfree(info->node_cache);
        spin_unlock(&info->lock);
 
+       list_for_each_entry_safe(msg, nmsg, &tmp_msg, m_list) {
+               list_del(&msg->m_list);
+               free_msg(msg);
+       }
+
        /* Total amount of bytes accounted for the mqueue */
        mq_treesize = info->attr.mq_maxmsg * sizeof(struct msg_msg) +
                min_t(unsigned int, info->attr.mq_maxmsg, MQ_PRIO_MAX) *
@@ -605,8 +621,6 @@ static void wq_add(struct mqueue_inode_info *info, int sr,
 {
        struct ext_wait_queue *walk;
 
-       ewp->task = current;
-
        list_for_each_entry(walk, &info->e_wait_q[sr].list, list) {
                if (walk->task->prio <= current->prio) {
                        list_add_tail(&ewp->list, &walk->list);
index 8459802..e655937 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/utsname.h>
 #include <linux/proc_ns.h>
 #include <linux/uaccess.h>
+#include <linux/sched.h>
 
 #include "util.h"
 
@@ -64,6 +65,9 @@ static struct msg_msg *alloc_msg(size_t len)
        pseg = &msg->next;
        while (len > 0) {
                struct msg_msgseg *seg;
+
+               cond_resched();
+
                alen = min(len, DATALEN_SEG);
                seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL_ACCOUNT);
                if (seg == NULL)
@@ -176,6 +180,8 @@ void free_msg(struct msg_msg *msg)
        kfree(msg);
        while (seg != NULL) {
                struct msg_msgseg *tmp = seg->next;
+
+               cond_resched();
                kfree(seg);
                seg = tmp;
        }
index 095274a..d126d15 100644 (file)
@@ -109,7 +109,7 @@ static const struct rhashtable_params ipc_kht_params = {
  * @ids: ipc identifier set
  *
  * Set up the sequence range to use for the ipc identifier range (limited
- * below IPCMNI) then initialise the keys hashtable and ids idr.
+ * below ipc_mni) then initialise the keys hashtable and ids idr.
  */
 void ipc_init_ids(struct ipc_ids *ids)
 {
@@ -119,6 +119,7 @@ void ipc_init_ids(struct ipc_ids *ids)
        rhashtable_init(&ids->key_ht, &ipc_kht_params);
        idr_init(&ids->ipcs_idr);
        ids->max_idx = -1;
+       ids->last_idx = -1;
 #ifdef CONFIG_CHECKPOINT_RESTORE
        ids->next_id = -1;
 #endif
@@ -192,6 +193,10 @@ static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
  *
  * The caller must own kern_ipc_perm.lock.of the new object.
  * On error, the function returns a (negative) error code.
+ *
+ * To conserve sequence number space, especially with extended ipc_mni,
+ * the sequence number is incremented only when the returned ID is less than
+ * the last one.
  */
 static inline int ipc_idr_alloc(struct ipc_ids *ids, struct kern_ipc_perm *new)
 {
@@ -215,17 +220,42 @@ static inline int ipc_idr_alloc(struct ipc_ids *ids, struct kern_ipc_perm *new)
         */
 
        if (next_id < 0) { /* !CHECKPOINT_RESTORE or next_id is unset */
-               new->seq = ids->seq++;
-               if (ids->seq > IPCID_SEQ_MAX)
-                       ids->seq = 0;
-               idx = idr_alloc(&ids->ipcs_idr, new, 0, 0, GFP_NOWAIT);
+               int max_idx;
+
+               max_idx = max(ids->in_use*3/2, ipc_min_cycle);
+               max_idx = min(max_idx, ipc_mni);
+
+               /* allocate the idx, with a NULL struct kern_ipc_perm */
+               idx = idr_alloc_cyclic(&ids->ipcs_idr, NULL, 0, max_idx,
+                                       GFP_NOWAIT);
+
+               if (idx >= 0) {
+                       /*
+                        * idx got allocated successfully.
+                        * Now calculate the sequence number and set the
+                        * pointer for real.
+                        */
+                       if (idx <= ids->last_idx) {
+                               ids->seq++;
+                               if (ids->seq >= ipcid_seq_max())
+                                       ids->seq = 0;
+                       }
+                       ids->last_idx = idx;
+
+                       new->seq = ids->seq;
+                       /* no need for smp_wmb(), this is done
+                        * inside idr_replace, as part of
+                        * rcu_assign_pointer
+                        */
+                       idr_replace(&ids->ipcs_idr, new, idx);
+               }
        } else {
                new->seq = ipcid_to_seqx(next_id);
                idx = idr_alloc(&ids->ipcs_idr, new, ipcid_to_idx(next_id),
                                0, GFP_NOWAIT);
        }
        if (idx >= 0)
-               new->id = SEQ_MULTIPLIER * new->seq + idx;
+               new->id = (new->seq << ipcmni_seq_shift()) + idx;
        return idx;
 }
 
@@ -253,8 +283,8 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int limit)
        /* 1) Initialize the refcount so that ipc_rcu_putref works */
        refcount_set(&new->refcount, 1);
 
-       if (limit > IPCMNI)
-               limit = IPCMNI;
+       if (limit > ipc_mni)
+               limit = ipc_mni;
 
        if (ids->in_use >= limit)
                return -ENOSPC;
@@ -737,7 +767,7 @@ static struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t pos,
        if (total >= ids->in_use)
                return NULL;
 
-       for (; pos < IPCMNI; pos++) {
+       for (; pos < ipc_mni; pos++) {
                ipc = idr_find(&ids->ipcs_idr, pos);
                if (ipc != NULL) {
                        *new_pos = pos + 1;
index e272be6..0fcf8e7 100644 (file)
 #include <linux/err.h>
 #include <linux/ipc_namespace.h>
 
-#define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl changes) */
-#define SEQ_MULTIPLIER (IPCMNI)
+/*
+ * The IPC ID contains 2 separate numbers - index and sequence number.
+ * By default,
+ *   bits  0-14: index (32k, 15 bits)
+ *   bits 15-30: sequence number (64k, 16 bits)
+ *
+ * When IPCMNI extension mode is turned on, the composition changes:
+ *   bits  0-23: index (16M, 24 bits)
+ *   bits 24-30: sequence number (128, 7 bits)
+ */
+#define IPCMNI_SHIFT           15
+#define IPCMNI_EXTEND_SHIFT    24
+#define IPCMNI_EXTEND_MIN_CYCLE        (RADIX_TREE_MAP_SIZE * RADIX_TREE_MAP_SIZE)
+#define IPCMNI                 (1 << IPCMNI_SHIFT)
+#define IPCMNI_EXTEND          (1 << IPCMNI_EXTEND_SHIFT)
+
+#ifdef CONFIG_SYSVIPC_SYSCTL
+extern int ipc_mni;
+extern int ipc_mni_shift;
+extern int ipc_min_cycle;
+
+#define ipcmni_seq_shift()     ipc_mni_shift
+#define IPCMNI_IDX_MASK                ((1 << ipc_mni_shift) - 1)
+
+#else /* CONFIG_SYSVIPC_SYSCTL */
+
+#define ipc_mni                        IPCMNI
+#define ipc_min_cycle          ((int)RADIX_TREE_MAP_SIZE)
+#define ipcmni_seq_shift()     IPCMNI_SHIFT
+#define IPCMNI_IDX_MASK                ((1 << IPCMNI_SHIFT) - 1)
+#endif /* CONFIG_SYSVIPC_SYSCTL */
 
 void sem_init(void);
 void msg_init(void);
@@ -96,9 +125,9 @@ struct pid_namespace *ipc_seq_pid_ns(struct seq_file *);
 #define IPC_MSG_IDS    1
 #define IPC_SHM_IDS    2
 
-#define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
-#define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER)
-#define IPCID_SEQ_MAX min_t(int, INT_MAX/SEQ_MULTIPLIER, USHRT_MAX)
+#define ipcid_to_idx(id)  ((id) & IPCMNI_IDX_MASK)
+#define ipcid_to_seqx(id) ((id) >> ipcmni_seq_shift())
+#define ipcid_seq_max()          (INT_MAX >> ipcmni_seq_shift())
 
 /* must be called with ids->rwsem acquired for writing */
 int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
@@ -123,8 +152,8 @@ static inline int ipc_get_maxidx(struct ipc_ids *ids)
        if (ids->in_use == 0)
                return -1;
 
-       if (ids->in_use == IPCMNI)
-               return IPCMNI - 1;
+       if (ids->in_use == ipc_mni)
+               return ipc_mni - 1;
 
        return ids->max_idx;
 }
@@ -216,10 +245,10 @@ void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
 
 static inline int sem_check_semmni(struct ipc_namespace *ns) {
        /*
-        * Check semmni range [0, IPCMNI]
+        * Check semmni range [0, ipc_mni]
         * semmni is the last element of sem_ctls[4] array
         */
-       return ((ns->sem_ctls[3] < 0) || (ns->sem_ctls[3] > IPCMNI))
+       return ((ns->sem_ctls[3] < 0) || (ns->sem_ctls[3] > ipc_mni))
                ? -ERANGE : 0;
 }
 
index 298437b..33824f0 100644 (file)
@@ -127,7 +127,7 @@ $(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE
 $(obj)/kheaders.o: $(obj)/kheaders_data.tar.xz
 
 quiet_cmd_genikh = CHK     $(obj)/kheaders_data.tar.xz
-cmd_genikh = $(srctree)/kernel/gen_ikh_data.sh $@
+cmd_genikh = $(CONFIG_SHELL) $(srctree)/kernel/gen_ikh_data.sh $@
 $(obj)/kheaders_data.tar.xz: FORCE
        $(call cmd,genikh)
 
index 3ba56e7..242a643 100644 (file)
@@ -338,7 +338,7 @@ int bpf_prog_calc_tag(struct bpf_prog *fp)
 }
 
 static int bpf_adj_delta_to_imm(struct bpf_insn *insn, u32 pos, s32 end_old,
-                               s32 end_new, u32 curr, const bool probe_pass)
+                               s32 end_new, s32 curr, const bool probe_pass)
 {
        const s64 imm_min = S32_MIN, imm_max = S32_MAX;
        s32 delta = end_new - end_old;
@@ -356,7 +356,7 @@ static int bpf_adj_delta_to_imm(struct bpf_insn *insn, u32 pos, s32 end_old,
 }
 
 static int bpf_adj_delta_to_off(struct bpf_insn *insn, u32 pos, s32 end_old,
-                               s32 end_new, u32 curr, const bool probe_pass)
+                               s32 end_new, s32 curr, const bool probe_pass)
 {
        const s32 off_min = S16_MIN, off_max = S16_MAX;
        s32 delta = end_new - end_old;
index 7b05e89..95f9354 100644 (file)
@@ -7599,7 +7599,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
                                                                        insn->dst_reg,
                                                                        shift);
                                insn_buf[cnt++] = BPF_ALU64_IMM(BPF_AND, insn->dst_reg,
-                                                               (1 << size * 8) - 1);
+                                                               (1ULL << size * 8) - 1);
                        }
                }
 
index 327f37c..217cec4 100644 (file)
@@ -3540,17 +3540,84 @@ static int cpu_stat_show(struct seq_file *seq, void *v)
 #ifdef CONFIG_PSI
 static int cgroup_io_pressure_show(struct seq_file *seq, void *v)
 {
-       return psi_show(seq, &seq_css(seq)->cgroup->psi, PSI_IO);
+       struct cgroup *cgroup = seq_css(seq)->cgroup;
+       struct psi_group *psi = cgroup->id == 1 ? &psi_system : &cgroup->psi;
+
+       return psi_show(seq, psi, PSI_IO);
 }
 static int cgroup_memory_pressure_show(struct seq_file *seq, void *v)
 {
-       return psi_show(seq, &seq_css(seq)->cgroup->psi, PSI_MEM);
+       struct cgroup *cgroup = seq_css(seq)->cgroup;
+       struct psi_group *psi = cgroup->id == 1 ? &psi_system : &cgroup->psi;
+
+       return psi_show(seq, psi, PSI_MEM);
 }
 static int cgroup_cpu_pressure_show(struct seq_file *seq, void *v)
 {
-       return psi_show(seq, &seq_css(seq)->cgroup->psi, PSI_CPU);
+       struct cgroup *cgroup = seq_css(seq)->cgroup;
+       struct psi_group *psi = cgroup->id == 1 ? &psi_system : &cgroup->psi;
+
+       return psi_show(seq, psi, PSI_CPU);
 }
-#endif
+
+static ssize_t cgroup_pressure_write(struct kernfs_open_file *of, char *buf,
+                                         size_t nbytes, enum psi_res res)
+{
+       struct psi_trigger *new;
+       struct cgroup *cgrp;
+
+       cgrp = cgroup_kn_lock_live(of->kn, false);
+       if (!cgrp)
+               return -ENODEV;
+
+       cgroup_get(cgrp);
+       cgroup_kn_unlock(of->kn);
+
+       new = psi_trigger_create(&cgrp->psi, buf, nbytes, res);
+       if (IS_ERR(new)) {
+               cgroup_put(cgrp);
+               return PTR_ERR(new);
+       }
+
+       psi_trigger_replace(&of->priv, new);
+
+       cgroup_put(cgrp);
+
+       return nbytes;
+}
+
+static ssize_t cgroup_io_pressure_write(struct kernfs_open_file *of,
+                                         char *buf, size_t nbytes,
+                                         loff_t off)
+{
+       return cgroup_pressure_write(of, buf, nbytes, PSI_IO);
+}
+
+static ssize_t cgroup_memory_pressure_write(struct kernfs_open_file *of,
+                                         char *buf, size_t nbytes,
+                                         loff_t off)
+{
+       return cgroup_pressure_write(of, buf, nbytes, PSI_MEM);
+}
+
+static ssize_t cgroup_cpu_pressure_write(struct kernfs_open_file *of,
+                                         char *buf, size_t nbytes,
+                                         loff_t off)
+{
+       return cgroup_pressure_write(of, buf, nbytes, PSI_CPU);
+}
+
+static __poll_t cgroup_pressure_poll(struct kernfs_open_file *of,
+                                         poll_table *pt)
+{
+       return psi_trigger_poll(&of->priv, of->file, pt);
+}
+
+static void cgroup_pressure_release(struct kernfs_open_file *of)
+{
+       psi_trigger_replace(&of->priv, NULL);
+}
+#endif /* CONFIG_PSI */
 
 static int cgroup_freeze_show(struct seq_file *seq, void *v)
 {
@@ -4743,20 +4810,26 @@ static struct cftype cgroup_base_files[] = {
 #ifdef CONFIG_PSI
        {
                .name = "io.pressure",
-               .flags = CFTYPE_NOT_ON_ROOT,
                .seq_show = cgroup_io_pressure_show,
+               .write = cgroup_io_pressure_write,
+               .poll = cgroup_pressure_poll,
+               .release = cgroup_pressure_release,
        },
        {
                .name = "memory.pressure",
-               .flags = CFTYPE_NOT_ON_ROOT,
                .seq_show = cgroup_memory_pressure_show,
+               .write = cgroup_memory_pressure_write,
+               .poll = cgroup_pressure_poll,
+               .release = cgroup_pressure_release,
        },
        {
                .name = "cpu.pressure",
-               .flags = CFTYPE_NOT_ON_ROOT,
                .seq_show = cgroup_cpu_pressure_show,
+               .write = cgroup_cpu_pressure_write,
+               .poll = cgroup_pressure_poll,
+               .release = cgroup_pressure_release,
        },
-#endif
+#endif /* CONFIG_PSI */
        { }     /* terminate */
 };
 
index d8a36c6..b5f7063 100644 (file)
@@ -346,8 +346,11 @@ get_compat_sigset(sigset_t *set, const compat_sigset_t __user *compat)
                return -EFAULT;
        switch (_NSIG_WORDS) {
        case 4: set->sig[3] = v.sig[6] | (((long)v.sig[7]) << 32 );
+               /* fall through */
        case 3: set->sig[2] = v.sig[4] | (((long)v.sig[5]) << 32 );
+               /* fall through */
        case 2: set->sig[1] = v.sig[2] | (((long)v.sig[3]) << 32 );
+               /* fall through */
        case 1: set->sig[0] = v.sig[0] | (((long)v.sig[1]) << 32 );
        }
 #else
index 7510dc6..4b280fc 100644 (file)
@@ -1033,13 +1033,14 @@ int gdb_serial_stub(struct kgdb_state *ks)
                                return DBG_PASS_EVENT;
                        }
 #endif
+                       /* Fall through */
                case 'C': /* Exception passing */
                        tmp = gdb_cmd_exception_pass(ks);
                        if (tmp > 0)
                                goto default_handle;
                        if (tmp == 0)
                                break;
-                       /* Fall through on tmp < 0 */
+                       /* Fall through on tmp < 0 */
                case 'c': /* Continue packet */
                case 's': /* Single step packet */
                        if (kgdb_contthread && kgdb_contthread != current) {
@@ -1048,7 +1049,7 @@ int gdb_serial_stub(struct kgdb_state *ks)
                                break;
                        }
                        dbg_activate_sw_breakpoints();
-                       /* Fall through to default processing */
+                       /* Fall through to default processing */
                default:
 default_handle:
                        error = kgdb_arch_handle_exception(ks->ex_vector,
@@ -1094,10 +1095,10 @@ int gdbstub_state(struct kgdb_state *ks, char *cmd)
                return error;
        case 's':
        case 'c':
-               strcpy(remcom_in_buffer, cmd);
+               strscpy(remcom_in_buffer, cmd, sizeof(remcom_in_buffer));
                return 0;
        case '$':
-               strcpy(remcom_in_buffer, cmd);
+               strscpy(remcom_in_buffer, cmd, sizeof(remcom_in_buffer));
                gdbstub_use_prev_in_buf = strlen(remcom_in_buffer);
                gdbstub_prev_in_buf_pos = 0;
                return 0;
index d4fc58f..efac857 100644 (file)
@@ -6,7 +6,6 @@
 # Copyright (c) 2009 Wind River Systems, Inc. All Rights Reserved.
 #
 
-CCVERSION      := $(shell $(CC) -v 2>&1 | sed -ne '$$p')
 obj-y := kdb_io.o kdb_main.o kdb_support.o kdb_bt.o gen-kdb_cmds.o kdb_bp.o kdb_debugger.o
 obj-$(CONFIG_KDB_KEYBOARD)    += kdb_keyboard.o
 
index 6a4b414..3a5184e 100644 (file)
@@ -446,7 +446,7 @@ poll_again:
 char *kdb_getstr(char *buffer, size_t bufsize, const char *prompt)
 {
        if (prompt && kdb_prompt_str != prompt)
-               strncpy(kdb_prompt_str, prompt, CMD_BUFLEN);
+               strscpy(kdb_prompt_str, prompt, CMD_BUFLEN);
        kdb_printf(kdb_prompt_str);
        kdb_nextline = 1;       /* Prompt and input resets line number */
        return kdb_read(buffer, bufsize);
index 82a3b32..9ecfa37 100644 (file)
@@ -2522,7 +2522,6 @@ static int kdb_summary(int argc, const char **argv)
        kdb_printf("machine    %s\n", init_uts_ns.name.machine);
        kdb_printf("nodename   %s\n", init_uts_ns.name.nodename);
        kdb_printf("domainname %s\n", init_uts_ns.name.domainname);
-       kdb_printf("ccversion  %s\n", __stringify(CCVERSION));
 
        now = __ktime_get_real_seconds();
        time64_to_tm(now, 0, &tm);
@@ -2584,7 +2583,7 @@ static int kdb_per_cpu(int argc, const char **argv)
                diag = kdbgetularg(argv[3], &whichcpu);
                if (diag)
                        return diag;
-               if (!cpu_online(whichcpu)) {
+               if (whichcpu >= nr_cpu_ids || !cpu_online(whichcpu)) {
                        kdb_printf("cpu %ld is not online\n", whichcpu);
                        return KDB_BADCPUNUM;
                }
index 50bf9b1..b8e6306 100644 (file)
@@ -192,7 +192,7 @@ int kallsyms_symbol_complete(char *prefix_name, int max_len)
 
        while ((name = kdb_walk_kallsyms(&pos))) {
                if (strncmp(name, prefix_name, prefix_len) == 0) {
-                       strcpy(ks_namebuf, name);
+                       strscpy(ks_namebuf, name, sizeof(ks_namebuf));
                        /* Work out the longest name that matches the prefix */
                        if (++number == 1) {
                                prev_len = min_t(int, max_len-1,
index 4ca7364..78f61bf 100644 (file)
@@ -161,7 +161,8 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
        struct mmu_notifier_range range;
        struct mem_cgroup *memcg;
 
-       mmu_notifier_range_init(&range, mm, addr, addr + PAGE_SIZE);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, mm, addr,
+                               addr + PAGE_SIZE);
 
        VM_BUG_ON_PAGE(PageTransHuge(old_page), old_page);
 
index 2166c2d..8361a56 100644 (file)
@@ -422,7 +422,7 @@ retry:
         * freed task structure.
         */
        if (atomic_read(&mm->mm_users) <= 1) {
-               mm->owner = NULL;
+               WRITE_ONCE(mm->owner, NULL);
                return;
        }
 
@@ -462,7 +462,7 @@ retry:
         * most likely racing with swapoff (try_to_unuse()) or /proc or
         * ptrace or page migration (get_task_mm()).  Mark owner as NULL.
         */
-       mm->owner = NULL;
+       WRITE_ONCE(mm->owner, NULL);
        return;
 
 assign_new_owner:
@@ -483,7 +483,7 @@ assign_new_owner:
                put_task_struct(c);
                goto retry;
        }
-       mm->owner = c;
+       WRITE_ONCE(mm->owner, c);
        task_unlock(c);
        put_task_struct(c);
 }
index 737db18..b4cba95 100644 (file)
@@ -955,6 +955,15 @@ static void mm_init_aio(struct mm_struct *mm)
 #endif
 }
 
+static __always_inline void mm_clear_owner(struct mm_struct *mm,
+                                          struct task_struct *p)
+{
+#ifdef CONFIG_MEMCG
+       if (mm->owner == p)
+               WRITE_ONCE(mm->owner, NULL);
+#endif
+}
+
 static void mm_init_owner(struct mm_struct *mm, struct task_struct *p)
 {
 #ifdef CONFIG_MEMCG
@@ -1343,6 +1352,7 @@ static struct mm_struct *dup_mm(struct task_struct *tsk,
 free_pt:
        /* don't put binfmt in mmput, we haven't got module yet */
        mm->binfmt = NULL;
+       mm_init_owner(mm, NULL);
        mmput(mm);
 
 fail_nomem:
@@ -1726,6 +1736,21 @@ static int pidfd_create(struct pid *pid)
        return fd;
 }
 
+static void __delayed_free_task(struct rcu_head *rhp)
+{
+       struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
+
+       free_task(tsk);
+}
+
+static __always_inline void delayed_free_task(struct task_struct *tsk)
+{
+       if (IS_ENABLED(CONFIG_MEMCG))
+               call_rcu(&tsk->rcu, __delayed_free_task);
+       else
+               free_task(tsk);
+}
+
 /*
  * This creates a new process as a copy of the old one,
  * but does not actually start it yet.
@@ -2068,7 +2093,7 @@ static __latent_entropy struct task_struct *copy_process(
 #ifdef TIF_SYSCALL_EMU
        clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);
 #endif
-       clear_all_latency_tracing(p);
+       clear_tsk_latency_tracing(p);
 
        /* ok, now we should be set up.. */
        p->pid = pid_nr(pid);
@@ -2233,8 +2258,10 @@ bad_fork_cleanup_io:
 bad_fork_cleanup_namespaces:
        exit_task_namespaces(p);
 bad_fork_cleanup_mm:
-       if (p->mm)
+       if (p->mm) {
+               mm_clear_owner(p->mm, p);
                mmput(p->mm);
+       }
 bad_fork_cleanup_signal:
        if (!(clone_flags & CLONE_THREAD))
                free_signal_struct(p->signal);
@@ -2265,7 +2292,7 @@ bad_fork_cleanup_count:
 bad_fork_free:
        p->state = TASK_DEAD;
        put_task_stack(p);
-       free_task(p);
+       delayed_free_task(p);
 fork_out:
        spin_lock_irq(&current->sighand->siglock);
        hlist_del_init(&delayed.node);
index 6262f15..2268b97 100644 (file)
@@ -543,7 +543,7 @@ again:
        if (unlikely(should_fail_futex(fshared)))
                return -EFAULT;
 
-       err = get_user_pages_fast(address, 1, 1, &page);
+       err = get_user_pages_fast(address, 1, FOLL_WRITE, &page);
        /*
         * If write access is not required (eg. FUTEX_WAIT), try
         * and get read-only access.
index 1e3823f..f71c1ad 100644 (file)
@@ -53,6 +53,7 @@ config GCOV_PROFILE_ALL
 choice
        prompt "Specify GCOV format"
        depends on GCOV_KERNEL
+       depends on CC_IS_GCC
        ---help---
        The gcov format is usually determined by the GCC version, and the
        default is chosen according to your GCC version. However, there are
@@ -62,7 +63,7 @@ choice
 
 config GCOV_FORMAT_3_4
        bool "GCC 3.4 format"
-       depends on CC_IS_GCC && GCC_VERSION < 40700
+       depends on GCC_VERSION < 40700
        ---help---
        Select this option to use the format defined by GCC 3.4.
 
index ff06d64..d66a74b 100644 (file)
@@ -2,5 +2,6 @@
 ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
 
 obj-y := base.o fs.o
-obj-$(CONFIG_GCOV_FORMAT_3_4) += gcc_3_4.o
-obj-$(CONFIG_GCOV_FORMAT_4_7) += gcc_4_7.o
+obj-$(CONFIG_GCOV_FORMAT_3_4) += gcc_base.o gcc_3_4.o
+obj-$(CONFIG_GCOV_FORMAT_4_7) += gcc_base.o gcc_4_7.o
+obj-$(CONFIG_CC_IS_CLANG) += clang.o
index 9c7c8d5..0ffe9f1 100644 (file)
 #include <linux/sched.h>
 #include "gcov.h"
 
-static int gcov_events_enabled;
-static DEFINE_MUTEX(gcov_lock);
-
-/*
- * __gcov_init is called by gcc-generated constructor code for each object
- * file compiled with -fprofile-arcs.
- */
-void __gcov_init(struct gcov_info *info)
-{
-       static unsigned int gcov_version;
-
-       mutex_lock(&gcov_lock);
-       if (gcov_version == 0) {
-               gcov_version = gcov_info_version(info);
-               /*
-                * Printing gcc's version magic may prove useful for debugging
-                * incompatibility reports.
-                */
-               pr_info("version magic: 0x%x\n", gcov_version);
-       }
-       /*
-        * Add new profiling data structure to list and inform event
-        * listener.
-        */
-       gcov_info_link(info);
-       if (gcov_events_enabled)
-               gcov_event(GCOV_ADD, info);
-       mutex_unlock(&gcov_lock);
-}
-EXPORT_SYMBOL(__gcov_init);
-
-/*
- * These functions may be referenced by gcc-generated profiling code but serve
- * no function for kernel profiling.
- */
-void __gcov_flush(void)
-{
-       /* Unused. */
-}
-EXPORT_SYMBOL(__gcov_flush);
-
-void __gcov_merge_add(gcov_type *counters, unsigned int n_counters)
-{
-       /* Unused. */
-}
-EXPORT_SYMBOL(__gcov_merge_add);
-
-void __gcov_merge_single(gcov_type *counters, unsigned int n_counters)
-{
-       /* Unused. */
-}
-EXPORT_SYMBOL(__gcov_merge_single);
-
-void __gcov_merge_delta(gcov_type *counters, unsigned int n_counters)
-{
-       /* Unused. */
-}
-EXPORT_SYMBOL(__gcov_merge_delta);
-
-void __gcov_merge_ior(gcov_type *counters, unsigned int n_counters)
-{
-       /* Unused. */
-}
-EXPORT_SYMBOL(__gcov_merge_ior);
-
-void __gcov_merge_time_profile(gcov_type *counters, unsigned int n_counters)
-{
-       /* Unused. */
-}
-EXPORT_SYMBOL(__gcov_merge_time_profile);
-
-void __gcov_merge_icall_topn(gcov_type *counters, unsigned int n_counters)
-{
-       /* Unused. */
-}
-EXPORT_SYMBOL(__gcov_merge_icall_topn);
-
-void __gcov_exit(void)
-{
-       /* Unused. */
-}
-EXPORT_SYMBOL(__gcov_exit);
+int gcov_events_enabled;
+DEFINE_MUTEX(gcov_lock);
 
 /**
  * gcov_enable_events - enable event reporting through gcov_event()
@@ -144,7 +64,7 @@ static int gcov_module_notifier(struct notifier_block *nb, unsigned long event,
 
        /* Remove entries located in module from linked list. */
        while ((info = gcov_info_next(info))) {
-               if (within_module((unsigned long)info, mod)) {
+               if (gcov_info_within_module(info, mod)) {
                        gcov_info_unlink(prev, info);
                        if (gcov_events_enabled)
                                gcov_event(GCOV_REMOVE, info);
diff --git a/kernel/gcov/clang.c b/kernel/gcov/clang.c
new file mode 100644 (file)
index 0000000..c94b820
--- /dev/null
@@ -0,0 +1,581 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Google, Inc.
+ * modified from kernel/gcov/gcc_4_7.c
+ *
+ * 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.
+ *
+ *
+ * LLVM uses profiling data that's deliberately similar to GCC, but has a
+ * very different way of exporting that data.  LLVM calls llvm_gcov_init() once
+ * per module, and provides a couple of callbacks that we can use to ask for
+ * more data.
+ *
+ * We care about the "writeout" callback, which in turn calls back into
+ * compiler-rt/this module to dump all the gathered coverage data to disk:
+ *
+ *    llvm_gcda_start_file()
+ *      llvm_gcda_emit_function()
+ *      llvm_gcda_emit_arcs()
+ *      llvm_gcda_emit_function()
+ *      llvm_gcda_emit_arcs()
+ *      [... repeats for each function ...]
+ *    llvm_gcda_summary_info()
+ *    llvm_gcda_end_file()
+ *
+ * This design is much more stateless and unstructured than gcc's, and is
+ * intended to run at process exit.  This forces us to keep some local state
+ * about which module we're dealing with at the moment.  On the other hand, it
+ * also means we don't depend as much on how LLVM represents profiling data
+ * internally.
+ *
+ * See LLVM's lib/Transforms/Instrumentation/GCOVProfiling.cpp for more
+ * details on how this works, particularly GCOVProfiler::emitProfileArcs(),
+ * GCOVProfiler::insertCounterWriteout(), and
+ * GCOVProfiler::insertFlush().
+ */
+
+#define pr_fmt(fmt)    "gcov: " fmt
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include "gcov.h"
+
+typedef void (*llvm_gcov_callback)(void);
+
+struct gcov_info {
+       struct list_head head;
+
+       const char *filename;
+       unsigned int version;
+       u32 checksum;
+
+       struct list_head functions;
+};
+
+struct gcov_fn_info {
+       struct list_head head;
+
+       u32 ident;
+       u32 checksum;
+       u8 use_extra_checksum;
+       u32 cfg_checksum;
+
+       u32 num_counters;
+       u64 *counters;
+       const char *function_name;
+};
+
+static struct gcov_info *current_info;
+
+static LIST_HEAD(clang_gcov_list);
+
+void llvm_gcov_init(llvm_gcov_callback writeout, llvm_gcov_callback flush)
+{
+       struct gcov_info *info = kzalloc(sizeof(*info), GFP_KERNEL);
+
+       if (!info)
+               return;
+
+       INIT_LIST_HEAD(&info->head);
+       INIT_LIST_HEAD(&info->functions);
+
+       mutex_lock(&gcov_lock);
+
+       list_add_tail(&info->head, &clang_gcov_list);
+       current_info = info;
+       writeout();
+       current_info = NULL;
+       if (gcov_events_enabled)
+               gcov_event(GCOV_ADD, info);
+
+       mutex_unlock(&gcov_lock);
+}
+EXPORT_SYMBOL(llvm_gcov_init);
+
+void llvm_gcda_start_file(const char *orig_filename, const char version[4],
+               u32 checksum)
+{
+       current_info->filename = orig_filename;
+       memcpy(&current_info->version, version, sizeof(current_info->version));
+       current_info->checksum = checksum;
+}
+EXPORT_SYMBOL(llvm_gcda_start_file);
+
+void llvm_gcda_emit_function(u32 ident, const char *function_name,
+               u32 func_checksum, u8 use_extra_checksum, u32 cfg_checksum)
+{
+       struct gcov_fn_info *info = kzalloc(sizeof(*info), GFP_KERNEL);
+
+       if (!info)
+               return;
+
+       INIT_LIST_HEAD(&info->head);
+       info->ident = ident;
+       info->checksum = func_checksum;
+       info->use_extra_checksum = use_extra_checksum;
+       info->cfg_checksum = cfg_checksum;
+       if (function_name)
+               info->function_name = kstrdup(function_name, GFP_KERNEL);
+
+       list_add_tail(&info->head, &current_info->functions);
+}
+EXPORT_SYMBOL(llvm_gcda_emit_function);
+
+void llvm_gcda_emit_arcs(u32 num_counters, u64 *counters)
+{
+       struct gcov_fn_info *info = list_last_entry(&current_info->functions,
+                       struct gcov_fn_info, head);
+
+       info->num_counters = num_counters;
+       info->counters = counters;
+}
+EXPORT_SYMBOL(llvm_gcda_emit_arcs);
+
+void llvm_gcda_summary_info(void)
+{
+}
+EXPORT_SYMBOL(llvm_gcda_summary_info);
+
+void llvm_gcda_end_file(void)
+{
+}
+EXPORT_SYMBOL(llvm_gcda_end_file);
+
+/**
+ * gcov_info_filename - return info filename
+ * @info: profiling data set
+ */
+const char *gcov_info_filename(struct gcov_info *info)
+{
+       return info->filename;
+}
+
+/**
+ * gcov_info_version - return info version
+ * @info: profiling data set
+ */
+unsigned int gcov_info_version(struct gcov_info *info)
+{
+       return info->version;
+}
+
+/**
+ * gcov_info_next - return next profiling data set
+ * @info: profiling data set
+ *
+ * Returns next gcov_info following @info or first gcov_info in the chain if
+ * @info is %NULL.
+ */
+struct gcov_info *gcov_info_next(struct gcov_info *info)
+{
+       if (!info)
+               return list_first_entry_or_null(&clang_gcov_list,
+                               struct gcov_info, head);
+       if (list_is_last(&info->head, &clang_gcov_list))
+               return NULL;
+       return list_next_entry(info, head);
+}
+
+/**
+ * gcov_info_link - link/add profiling data set to the list
+ * @info: profiling data set
+ */
+void gcov_info_link(struct gcov_info *info)
+{
+       list_add_tail(&info->head, &clang_gcov_list);
+}
+
+/**
+ * gcov_info_unlink - unlink/remove profiling data set from the list
+ * @prev: previous profiling data set
+ * @info: profiling data set
+ */
+void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info)
+{
+       /* Generic code unlinks while iterating. */
+       __list_del_entry(&info->head);
+}
+
+/**
+ * gcov_info_within_module - check if a profiling data set belongs to a module
+ * @info: profiling data set
+ * @mod: module
+ *
+ * Returns true if profiling data belongs module, false otherwise.
+ */
+bool gcov_info_within_module(struct gcov_info *info, struct module *mod)
+{
+       return within_module((unsigned long)info->filename, mod);
+}
+
+/* Symbolic links to be created for each profiling data file. */
+const struct gcov_link gcov_link[] = {
+       { OBJ_TREE, "gcno" },   /* Link to .gcno file in $(objtree). */
+       { 0, NULL},
+};
+
+/**
+ * gcov_info_reset - reset profiling data to zero
+ * @info: profiling data set
+ */
+void gcov_info_reset(struct gcov_info *info)
+{
+       struct gcov_fn_info *fn;
+
+       list_for_each_entry(fn, &info->functions, head)
+               memset(fn->counters, 0,
+                               sizeof(fn->counters[0]) * fn->num_counters);
+}
+
+/**
+ * gcov_info_is_compatible - check if profiling data can be added
+ * @info1: first profiling data set
+ * @info2: second profiling data set
+ *
+ * Returns non-zero if profiling data can be added, zero otherwise.
+ */
+int gcov_info_is_compatible(struct gcov_info *info1, struct gcov_info *info2)
+{
+       struct gcov_fn_info *fn_ptr1 = list_first_entry_or_null(
+                       &info1->functions, struct gcov_fn_info, head);
+       struct gcov_fn_info *fn_ptr2 = list_first_entry_or_null(
+                       &info2->functions, struct gcov_fn_info, head);
+
+       if (info1->checksum != info2->checksum)
+               return false;
+       if (!fn_ptr1)
+               return fn_ptr1 == fn_ptr2;
+       while (!list_is_last(&fn_ptr1->head, &info1->functions) &&
+               !list_is_last(&fn_ptr2->head, &info2->functions)) {
+               if (fn_ptr1->checksum != fn_ptr2->checksum)
+                       return false;
+               if (fn_ptr1->use_extra_checksum != fn_ptr2->use_extra_checksum)
+                       return false;
+               if (fn_ptr1->use_extra_checksum &&
+                       fn_ptr1->cfg_checksum != fn_ptr2->cfg_checksum)
+                       return false;
+               fn_ptr1 = list_next_entry(fn_ptr1, head);
+               fn_ptr2 = list_next_entry(fn_ptr2, head);
+       }
+       return list_is_last(&fn_ptr1->head, &info1->functions) &&
+               list_is_last(&fn_ptr2->head, &info2->functions);
+}
+
+/**
+ * gcov_info_add - add up profiling data
+ * @dest: profiling data set to which data is added
+ * @source: profiling data set which is added
+ *
+ * Adds profiling counts of @source to @dest.
+ */
+void gcov_info_add(struct gcov_info *dst, struct gcov_info *src)
+{
+       struct gcov_fn_info *dfn_ptr;
+       struct gcov_fn_info *sfn_ptr = list_first_entry_or_null(&src->functions,
+                       struct gcov_fn_info, head);
+
+       list_for_each_entry(dfn_ptr, &dst->functions, head) {
+               u32 i;
+
+               for (i = 0; i < sfn_ptr->num_counters; i++)
+                       dfn_ptr->counters[i] += sfn_ptr->counters[i];
+       }
+}
+
+static struct gcov_fn_info *gcov_fn_info_dup(struct gcov_fn_info *fn)
+{
+       size_t cv_size; /* counter values size */
+       struct gcov_fn_info *fn_dup = kmemdup(fn, sizeof(*fn),
+                       GFP_KERNEL);
+       if (!fn_dup)
+               return NULL;
+       INIT_LIST_HEAD(&fn_dup->head);
+
+       fn_dup->function_name = kstrdup(fn->function_name, GFP_KERNEL);
+       if (!fn_dup->function_name)
+               goto err_name;
+
+       cv_size = fn->num_counters * sizeof(fn->counters[0]);
+       fn_dup->counters = vmalloc(cv_size);
+       if (!fn_dup->counters)
+               goto err_counters;
+       memcpy(fn_dup->counters, fn->counters, cv_size);
+
+       return fn_dup;
+
+err_counters:
+       kfree(fn_dup->function_name);
+err_name:
+       kfree(fn_dup);
+       return NULL;
+}
+
+/**
+ * gcov_info_dup - duplicate profiling data set
+ * @info: profiling data set to duplicate
+ *
+ * Return newly allocated duplicate on success, %NULL on error.
+ */
+struct gcov_info *gcov_info_dup(struct gcov_info *info)
+{
+       struct gcov_info *dup;
+       struct gcov_fn_info *fn;
+
+       dup = kmemdup(info, sizeof(*dup), GFP_KERNEL);
+       if (!dup)
+               return NULL;
+       INIT_LIST_HEAD(&dup->head);
+       INIT_LIST_HEAD(&dup->functions);
+       dup->filename = kstrdup(info->filename, GFP_KERNEL);
+       if (!dup->filename)
+               goto err;
+
+       list_for_each_entry(fn, &info->functions, head) {
+               struct gcov_fn_info *fn_dup = gcov_fn_info_dup(fn);
+
+               if (!fn_dup)
+                       goto err;
+               list_add_tail(&fn_dup->head, &dup->functions);
+       }
+
+       return dup;
+
+err:
+       gcov_info_free(dup);
+       return NULL;
+}
+
+/**
+ * gcov_info_free - release memory for profiling data set duplicate
+ * @info: profiling data set duplicate to free
+ */
+void gcov_info_free(struct gcov_info *info)
+{
+       struct gcov_fn_info *fn, *tmp;
+
+       list_for_each_entry_safe(fn, tmp, &info->functions, head) {
+               kfree(fn->function_name);
+               vfree(fn->counters);
+               list_del(&fn->head);
+               kfree(fn);
+       }
+       kfree(info->filename);
+       kfree(info);
+}
+
+#define ITER_STRIDE    PAGE_SIZE
+
+/**
+ * struct gcov_iterator - specifies current file position in logical records
+ * @info: associated profiling data
+ * @buffer: buffer containing file data
+ * @size: size of buffer
+ * @pos: current position in file
+ */
+struct gcov_iterator {
+       struct gcov_info *info;
+       void *buffer;
+       size_t size;
+       loff_t pos;
+};
+
+/**
+ * store_gcov_u32 - store 32 bit number in gcov format to buffer
+ * @buffer: target buffer or NULL
+ * @off: offset into the buffer
+ * @v: value to be stored
+ *
+ * Number format defined by gcc: numbers are recorded in the 32 bit
+ * unsigned binary form of the endianness of the machine generating the
+ * file. Returns the number of bytes stored. If @buffer is %NULL, doesn't
+ * store anything.
+ */
+static size_t store_gcov_u32(void *buffer, size_t off, u32 v)
+{
+       u32 *data;
+
+       if (buffer) {
+               data = buffer + off;
+               *data = v;
+       }
+
+       return sizeof(*data);
+}
+
+/**
+ * store_gcov_u64 - store 64 bit number in gcov format to buffer
+ * @buffer: target buffer or NULL
+ * @off: offset into the buffer
+ * @v: value to be stored
+ *
+ * Number format defined by gcc: numbers are recorded in the 32 bit
+ * unsigned binary form of the endianness of the machine generating the
+ * file. 64 bit numbers are stored as two 32 bit numbers, the low part
+ * first. Returns the number of bytes stored. If @buffer is %NULL, doesn't store
+ * anything.
+ */
+static size_t store_gcov_u64(void *buffer, size_t off, u64 v)
+{
+       u32 *data;
+
+       if (buffer) {
+               data = buffer + off;
+
+               data[0] = (v & 0xffffffffUL);
+               data[1] = (v >> 32);
+       }
+
+       return sizeof(*data) * 2;
+}
+
+/**
+ * convert_to_gcda - convert profiling data set to gcda file format
+ * @buffer: the buffer to store file data or %NULL if no data should be stored
+ * @info: profiling data set to be converted
+ *
+ * Returns the number of bytes that were/would have been stored into the buffer.
+ */
+static size_t convert_to_gcda(char *buffer, struct gcov_info *info)
+{
+       struct gcov_fn_info *fi_ptr;
+       size_t pos = 0;
+
+       /* File header. */
+       pos += store_gcov_u32(buffer, pos, GCOV_DATA_MAGIC);
+       pos += store_gcov_u32(buffer, pos, info->version);
+       pos += store_gcov_u32(buffer, pos, info->checksum);
+
+       list_for_each_entry(fi_ptr, &info->functions, head) {
+               u32 i;
+               u32 len = 2;
+
+               if (fi_ptr->use_extra_checksum)
+                       len++;
+
+               pos += store_gcov_u32(buffer, pos, GCOV_TAG_FUNCTION);
+               pos += store_gcov_u32(buffer, pos, len);
+               pos += store_gcov_u32(buffer, pos, fi_ptr->ident);
+               pos += store_gcov_u32(buffer, pos, fi_ptr->checksum);
+               if (fi_ptr->use_extra_checksum)
+                       pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum);
+
+               pos += store_gcov_u32(buffer, pos, GCOV_TAG_COUNTER_BASE);
+               pos += store_gcov_u32(buffer, pos, fi_ptr->num_counters * 2);
+               for (i = 0; i < fi_ptr->num_counters; i++)
+                       pos += store_gcov_u64(buffer, pos, fi_ptr->counters[i]);
+       }
+
+       return pos;
+}
+
+/**
+ * gcov_iter_new - allocate and initialize profiling data iterator
+ * @info: profiling data set to be iterated
+ *
+ * Return file iterator on success, %NULL otherwise.
+ */
+struct gcov_iterator *gcov_iter_new(struct gcov_info *info)
+{
+       struct gcov_iterator *iter;
+
+       iter = kzalloc(sizeof(struct gcov_iterator), GFP_KERNEL);
+       if (!iter)
+               goto err_free;
+
+       iter->info = info;
+       /* Dry-run to get the actual buffer size. */
+       iter->size = convert_to_gcda(NULL, info);
+       iter->buffer = vmalloc(iter->size);
+       if (!iter->buffer)
+               goto err_free;
+
+       convert_to_gcda(iter->buffer, info);
+
+       return iter;
+
+err_free:
+       kfree(iter);
+       return NULL;
+}
+
+
+/**
+ * gcov_iter_get_info - return profiling data set for given file iterator
+ * @iter: file iterator
+ */
+void gcov_iter_free(struct gcov_iterator *iter)
+{
+       vfree(iter->buffer);
+       kfree(iter);
+}
+
+/**
+ * gcov_iter_get_info - return profiling data set for given file iterator
+ * @iter: file iterator
+ */
+struct gcov_info *gcov_iter_get_info(struct gcov_iterator *iter)
+{
+       return iter->info;
+}
+
+/**
+ * gcov_iter_start - reset file iterator to starting position
+ * @iter: file iterator
+ */
+void gcov_iter_start(struct gcov_iterator *iter)
+{
+       iter->pos = 0;
+}
+
+/**
+ * gcov_iter_next - advance file iterator to next logical record
+ * @iter: file iterator
+ *
+ * Return zero if new position is valid, non-zero if iterator has reached end.
+ */
+int gcov_iter_next(struct gcov_iterator *iter)
+{
+       if (iter->pos < iter->size)
+               iter->pos += ITER_STRIDE;
+
+       if (iter->pos >= iter->size)
+               return -EINVAL;
+
+       return 0;
+}
+
+/**
+ * gcov_iter_write - write data for current pos to seq_file
+ * @iter: file iterator
+ * @seq: seq_file handle
+ *
+ * Return zero on success, non-zero otherwise.
+ */
+int gcov_iter_write(struct gcov_iterator *iter, struct seq_file *seq)
+{
+       size_t len;
+
+       if (iter->pos >= iter->size)
+               return -EINVAL;
+
+       len = ITER_STRIDE;
+       if (iter->pos + len > iter->size)
+               len = iter->size - iter->pos;
+
+       seq_write(seq, iter->buffer + iter->pos, len);
+
+       return 0;
+}
index 2dddecb..801ee4b 100644 (file)
@@ -137,6 +137,18 @@ void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info)
                gcov_info_head = info->next;
 }
 
+/**
+ * gcov_info_within_module - check if a profiling data set belongs to a module
+ * @info: profiling data set
+ * @mod: module
+ *
+ * Returns true if profiling data belongs module, false otherwise.
+ */
+bool gcov_info_within_module(struct gcov_info *info, struct module *mod)
+{
+       return within_module((unsigned long)info, mod);
+}
+
 /* Symbolic links to be created for each profiling data file. */
 const struct gcov_link gcov_link[] = {
        { OBJ_TREE, "gcno" },   /* Link to .gcno file in $(objtree). */
index ca5e5c0..ec37563 100644 (file)
@@ -150,6 +150,18 @@ void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info)
                gcov_info_head = info->next;
 }
 
+/**
+ * gcov_info_within_module - check if a profiling data set belongs to a module
+ * @info: profiling data set
+ * @mod: module
+ *
+ * Returns true if profiling data belongs module, false otherwise.
+ */
+bool gcov_info_within_module(struct gcov_info *info, struct module *mod)
+{
+       return within_module((unsigned long)info, mod);
+}
+
 /* Symbolic links to be created for each profiling data file. */
 const struct gcov_link gcov_link[] = {
        { OBJ_TREE, "gcno" },   /* Link to .gcno file in $(objtree). */
diff --git a/kernel/gcov/gcc_base.c b/kernel/gcov/gcc_base.c
new file mode 100644 (file)
index 0000000..3cf736b
--- /dev/null
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include "gcov.h"
+
+/*
+ * __gcov_init is called by gcc-generated constructor code for each object
+ * file compiled with -fprofile-arcs.
+ */
+void __gcov_init(struct gcov_info *info)
+{
+       static unsigned int gcov_version;
+
+       mutex_lock(&gcov_lock);
+       if (gcov_version == 0) {
+               gcov_version = gcov_info_version(info);
+               /*
+                * Printing gcc's version magic may prove useful for debugging
+                * incompatibility reports.
+                */
+               pr_info("version magic: 0x%x\n", gcov_version);
+       }
+       /*
+        * Add new profiling data structure to list and inform event
+        * listener.
+        */
+       gcov_info_link(info);
+       if (gcov_events_enabled)
+               gcov_event(GCOV_ADD, info);
+       mutex_unlock(&gcov_lock);
+}
+EXPORT_SYMBOL(__gcov_init);
+
+/*
+ * These functions may be referenced by gcc-generated profiling code but serve
+ * no function for kernel profiling.
+ */
+void __gcov_flush(void)
+{
+       /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_flush);
+
+void __gcov_merge_add(gcov_type *counters, unsigned int n_counters)
+{
+       /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_merge_add);
+
+void __gcov_merge_single(gcov_type *counters, unsigned int n_counters)
+{
+       /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_merge_single);
+
+void __gcov_merge_delta(gcov_type *counters, unsigned int n_counters)
+{
+       /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_merge_delta);
+
+void __gcov_merge_ior(gcov_type *counters, unsigned int n_counters)
+{
+       /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_merge_ior);
+
+void __gcov_merge_time_profile(gcov_type *counters, unsigned int n_counters)
+{
+       /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_merge_time_profile);
+
+void __gcov_merge_icall_topn(gcov_type *counters, unsigned int n_counters)
+{
+       /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_merge_icall_topn);
+
+void __gcov_exit(void)
+{
+       /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_exit);
index de118ad..6ab2c18 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef GCOV_H
 #define GCOV_H GCOV_H
 
+#include <linux/module.h>
 #include <linux/types.h>
 
 /*
@@ -46,6 +47,7 @@ unsigned int gcov_info_version(struct gcov_info *info);
 struct gcov_info *gcov_info_next(struct gcov_info *info);
 void gcov_info_link(struct gcov_info *info);
 void gcov_info_unlink(struct gcov_info *prev, struct gcov_info *info);
+bool gcov_info_within_module(struct gcov_info *info, struct module *mod);
 
 /* Base interface. */
 enum gcov_action {
@@ -83,4 +85,7 @@ struct gcov_link {
 };
 extern const struct gcov_link gcov_link[];
 
+extern int gcov_events_enabled;
+extern struct mutex gcov_lock;
+
 #endif /* GCOV_H */
index f7fb8f6..072b6ee 100644 (file)
@@ -500,13 +500,7 @@ static int locate_mem_hole_callback(struct resource *res, void *arg)
        return locate_mem_hole_bottom_up(start, end, kbuf);
 }
 
-#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
-static int kexec_walk_memblock(struct kexec_buf *kbuf,
-                              int (*func)(struct resource *, void *))
-{
-       return 0;
-}
-#else
+#ifdef CONFIG_ARCH_KEEP_MEMBLOCK
 static int kexec_walk_memblock(struct kexec_buf *kbuf,
                               int (*func)(struct resource *, void *))
 {
@@ -550,6 +544,12 @@ static int kexec_walk_memblock(struct kexec_buf *kbuf,
 
        return ret;
 }
+#else
+static int kexec_walk_memblock(struct kexec_buf *kbuf,
+                              int (*func)(struct resource *, void *))
+{
+       return 0;
+}
 #endif
 
 /**
@@ -589,7 +589,7 @@ int kexec_locate_mem_hole(struct kexec_buf *kbuf)
        if (kbuf->mem != KEXEC_BUF_MEM_UNKNOWN)
                return 0;
 
-       if (IS_ENABLED(CONFIG_ARCH_DISCARD_MEMBLOCK))
+       if (!IS_ENABLED(CONFIG_ARCH_KEEP_MEMBLOCK))
                ret = kexec_walk_resources(kbuf, locate_mem_hole_callback);
        else
                ret = kexec_walk_memblock(kbuf, locate_mem_hole_callback);
index 5942eea..be4e879 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kthread.h>
 #include <linux/completion.h>
 #include <linux/err.h>
+#include <linux/cgroup.h>
 #include <linux/cpuset.h>
 #include <linux/unistd.h>
 #include <linux/file.h>
index 99a5b5f..871734e 100644 (file)
@@ -67,13 +67,10 @@ static struct latency_record latency_record[MAXLR];
 
 int latencytop_enabled;
 
-void clear_all_latency_tracing(struct task_struct *p)
+void clear_tsk_latency_tracing(struct task_struct *p)
 {
        unsigned long flags;
 
-       if (!latencytop_enabled)
-               return;
-
        raw_spin_lock_irqsave(&latency_lock, flags);
        memset(&p->latency_record, 0, sizeof(p->latency_record));
        p->latency_record_count = 0;
@@ -96,9 +93,6 @@ account_global_scheduler_latency(struct task_struct *tsk,
        int firstnonnull = MAXLR + 1;
        int i;
 
-       if (!latencytop_enabled)
-               return;
-
        /* skip kernel threads for now */
        if (!tsk->mm)
                return;
index f6fbaff..91cd519 100644 (file)
@@ -1208,14 +1208,6 @@ void klp_module_going(struct module *mod)
 
 static int __init klp_init(void)
 {
-       int ret;
-
-       ret = klp_check_compiler_support();
-       if (ret) {
-               pr_info("Your compiler is too old; turning off.\n");
-               return -EINVAL;
-       }
-
        klp_root_kobj = kobject_create_and_add("livepatch", kernel_kobj);
        if (!klp_root_kobj)
                return -ENOMEM;
index 6b3ee99..0b1f779 100644 (file)
@@ -130,6 +130,7 @@ static void __rwsem_mark_wake(struct rw_semaphore *sem,
 {
        struct rwsem_waiter *waiter, *tmp;
        long oldcount, woken = 0, adjustment = 0;
+       struct list_head wlist;
 
        /*
         * Take a peek at the queue head waiter such that we can determine
@@ -188,18 +189,43 @@ static void __rwsem_mark_wake(struct rw_semaphore *sem,
         * of the queue. We know that woken will be at least 1 as we accounted
         * for above. Note we increment the 'active part' of the count by the
         * number of readers before waking any processes up.
+        *
+        * We have to do wakeup in 2 passes to prevent the possibility that
+        * the reader count may be decremented before it is incremented. It
+        * is because the to-be-woken waiter may not have slept yet. So it
+        * may see waiter->task got cleared, finish its critical section and
+        * do an unlock before the reader count increment.
+        *
+        * 1) Collect the read-waiters in a separate list, count them and
+        *    fully increment the reader count in rwsem.
+        * 2) For each waiters in the new list, clear waiter->task and
+        *    put them into wake_q to be woken up later.
         */
-       list_for_each_entry_safe(waiter, tmp, &sem->wait_list, list) {
-               struct task_struct *tsk;
-
+       list_for_each_entry(waiter, &sem->wait_list, list) {
                if (waiter->type == RWSEM_WAITING_FOR_WRITE)
                        break;
 
                woken++;
-               tsk = waiter->task;
+       }
+       list_cut_before(&wlist, &sem->wait_list, &waiter->list);
+
+       adjustment = woken * RWSEM_ACTIVE_READ_BIAS - adjustment;
+       lockevent_cond_inc(rwsem_wake_reader, woken);
+       if (list_empty(&sem->wait_list)) {
+               /* hit end of list above */
+               adjustment -= RWSEM_WAITING_BIAS;
+       }
+
+       if (adjustment)
+               atomic_long_add(adjustment, &sem->count);
+
+       /* 2nd pass */
+       list_for_each_entry_safe(waiter, tmp, &wlist, list) {
+               struct task_struct *tsk;
 
+               tsk = waiter->task;
                get_task_struct(tsk);
-               list_del(&waiter->list);
+
                /*
                 * Ensure calling get_task_struct() before setting the reader
                 * waiter to nil such that rwsem_down_read_failed() cannot
@@ -213,16 +239,6 @@ static void __rwsem_mark_wake(struct rw_semaphore *sem,
                 */
                wake_q_add_safe(wake_q, tsk);
        }
-
-       adjustment = woken * RWSEM_ACTIVE_READ_BIAS - adjustment;
-       lockevent_cond_inc(rwsem_wake_reader, woken);
-       if (list_empty(&sem->wait_list)) {
-               /* hit end of list above */
-               adjustment -= RWSEM_WAITING_BIAS;
-       }
-
-       if (adjustment)
-               atomic_long_add(adjustment, &sem->count);
 }
 
 /*
index a856cb5..1490e63 100644 (file)
@@ -45,7 +45,6 @@ vm_fault_t device_private_entry_fault(struct vm_area_struct *vma,
         */
        return devmem->page_fault(vma, addr, page, flags, pmdp);
 }
-EXPORT_SYMBOL(device_private_entry_fault);
 #endif /* CONFIG_DEVICE_PRIVATE */
 
 static void pgmap_array_delete(struct resource *res)
@@ -148,6 +147,12 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
                        &pgmap->altmap : NULL;
        struct resource *res = &pgmap->res;
        struct dev_pagemap *conflict_pgmap;
+       struct mhp_restrictions restrictions = {
+               /*
+                * We do not want any optional features only our own memmap
+               */
+               .altmap = altmap,
+       };
        pgprot_t pgprot = PAGE_KERNEL;
        int error, nid, is_ram;
 
@@ -214,7 +219,7 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
         */
        if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
                error = add_pages(nid, align_start >> PAGE_SHIFT,
-                               align_size >> PAGE_SHIFT, NULL, false);
+                               align_size >> PAGE_SHIFT, &restrictions);
        } else {
                error = kasan_add_zero_shadow(__va(align_start), align_size);
                if (error) {
@@ -222,8 +227,8 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
                        goto err_kasan;
                }
 
-               error = arch_add_memory(nid, align_start, align_size, altmap,
-                               false);
+               error = arch_add_memory(nid, align_start, align_size,
+                                       &restrictions);
        }
 
        if (!error) {
index 79c9be2..d354341 100644 (file)
@@ -20,7 +20,7 @@ struct load_info {
        unsigned long len;
        Elf_Shdr *sechdrs;
        char *secstrings, *strtab;
-       unsigned long symoffs, stroffs;
+       unsigned long symoffs, stroffs, init_typeoffs, core_typeoffs;
        struct _ddebug *debug;
        unsigned int num_debug;
        bool sig_ok;
index a9e1e7f..6e6712b 100644 (file)
@@ -2642,6 +2642,8 @@ static void layout_symtab(struct module *mod, struct load_info *info)
        info->symoffs = ALIGN(mod->core_layout.size, symsect->sh_addralign ?: 1);
        info->stroffs = mod->core_layout.size = info->symoffs + ndst * sizeof(Elf_Sym);
        mod->core_layout.size += strtab_size;
+       info->core_typeoffs = mod->core_layout.size;
+       mod->core_layout.size += ndst * sizeof(char);
        mod->core_layout.size = debug_align(mod->core_layout.size);
 
        /* Put string table section at end of init part of module. */
@@ -2655,6 +2657,8 @@ static void layout_symtab(struct module *mod, struct load_info *info)
                                      __alignof__(struct mod_kallsyms));
        info->mod_kallsyms_init_off = mod->init_layout.size;
        mod->init_layout.size += sizeof(struct mod_kallsyms);
+       info->init_typeoffs = mod->init_layout.size;
+       mod->init_layout.size += nsrc * sizeof(char);
        mod->init_layout.size = debug_align(mod->init_layout.size);
 }
 
@@ -2678,20 +2682,23 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)
        mod->kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
        /* Make sure we get permanent strtab: don't use info->strtab. */
        mod->kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
+       mod->kallsyms->typetab = mod->init_layout.base + info->init_typeoffs;
 
-       /* Set types up while we still have access to sections. */
-       for (i = 0; i < mod->kallsyms->num_symtab; i++)
-               mod->kallsyms->symtab[i].st_size
-                       = elf_type(&mod->kallsyms->symtab[i], info);
-
-       /* Now populate the cut down core kallsyms for after init. */
+       /*
+        * Now populate the cut down core kallsyms for after init
+        * and set types up while we still have access to sections.
+        */
        mod->core_kallsyms.symtab = dst = mod->core_layout.base + info->symoffs;
        mod->core_kallsyms.strtab = s = mod->core_layout.base + info->stroffs;
+       mod->core_kallsyms.typetab = mod->core_layout.base + info->core_typeoffs;
        src = mod->kallsyms->symtab;
        for (ndst = i = 0; i < mod->kallsyms->num_symtab; i++) {
+               mod->kallsyms->typetab[i] = elf_type(src + i, info);
                if (i == 0 || is_livepatch_module(mod) ||
                    is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum,
                                   info->index.pcpu)) {
+                       mod->core_kallsyms.typetab[ndst] =
+                           mod->kallsyms->typetab[i];
                        dst[ndst] = src[i];
                        dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
                        s += strlcpy(s, &mod->kallsyms->strtab[src[i].st_name],
@@ -4091,7 +4098,7 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
                        const Elf_Sym *sym = &kallsyms->symtab[symnum];
 
                        *value = kallsyms_symbol_value(sym);
-                       *type = sym->st_size;
+                       *type = kallsyms->typetab[symnum];
                        strlcpy(name, kallsyms_symbol_name(kallsyms, symnum), KSYM_NAME_LEN);
                        strlcpy(module_name, mod->name, MODULE_NAME_LEN);
                        *exported = is_exported(name, *value, mod);
index 6196af8..bfc95b3 100644 (file)
@@ -22,6 +22,7 @@ static int notifier_chain_register(struct notifier_block **nl,
                struct notifier_block *n)
 {
        while ((*nl) != NULL) {
+               WARN_ONCE(((*nl) == n), "double register detected");
                if (n->priority > (*nl)->priority)
                        break;
                nl = &((*nl)->next);
index c1fcaad..8779d64 100644 (file)
@@ -306,6 +306,8 @@ void panic(const char *fmt, ...)
                 * shutting down.  But if there is a chance of
                 * rebooting the system it will be rebooted.
                 */
+               if (panic_reboot_mode != REBOOT_UNDEFINED)
+                       reboot_mode = panic_reboot_mode;
                emergency_restart();
        }
 #ifdef __sparc__
@@ -321,6 +323,9 @@ void panic(const char *fmt, ...)
        disabled_wait();
 #endif
        pr_emerg("---[ end Kernel panic - not syncing: %s ]---\n", buf);
+
+       /* Do not scroll important messages printed above */
+       suppress_printk = 1;
        local_irq_enable();
        for (i = 0; ; i += PANIC_TIMER_STEP) {
                touch_softlockup_watchdog();
index 2088159..89548d3 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/init.h>
 #include <linux/rculist.h>
 #include <linux/memblock.h>
-#include <linux/hash.h>
 #include <linux/pid_namespace.h>
 #include <linux/init_task.h>
 #include <linux/syscalls.h>
index 02ca827..17102fd 100644 (file)
@@ -86,6 +86,12 @@ static DEFINE_SEMAPHORE(console_sem);
 struct console *console_drivers;
 EXPORT_SYMBOL_GPL(console_drivers);
 
+/*
+ * System may need to suppress printk message under certain
+ * circumstances, like after kernel panic happens.
+ */
+int __read_mostly suppress_printk;
+
 #ifdef CONFIG_LOCKDEP
 static struct lockdep_map console_lock_dep_map = {
        .name = "console_lock"
@@ -1943,6 +1949,10 @@ asmlinkage int vprintk_emit(int facility, int level,
        unsigned long flags;
        u64 curr_log_seq;
 
+       /* Suppress unimportant messages after panic happens */
+       if (unlikely(suppress_printk))
+               return 0;
+
        if (level == LOGLEVEL_SCHED) {
                level = LOGLEVEL_DEFAULT;
                in_sched = true;
index 4b58c90..390aab2 100644 (file)
 #define __LINUX_RCU_H
 
 #include <trace/events/rcu.h>
-#ifdef CONFIG_RCU_TRACE
-#define RCU_TRACE(stmt) stmt
-#else /* #ifdef CONFIG_RCU_TRACE */
-#define RCU_TRACE(stmt)
-#endif /* #else #ifdef CONFIG_RCU_TRACE */
 
 /* Offset to allow distinguishing irq vs. task-based idle entry/exit. */
 #define DYNTICK_IRQ_NONIDLE    ((LONG_MAX / 2) + 1)
@@ -216,12 +211,12 @@ static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head)
 
        rcu_lock_acquire(&rcu_callback_map);
        if (__is_kfree_rcu_offset(offset)) {
-               RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset);)
+               trace_rcu_invoke_kfree_callback(rn, head, offset);
                kfree((void *)head - offset);
                rcu_lock_release(&rcu_callback_map);
                return true;
        } else {
-               RCU_TRACE(trace_rcu_invoke_callback(rn, head);)
+               trace_rcu_invoke_callback(rn, head);
                f = head->func;
                WRITE_ONCE(head->func, (rcu_callback_t)0L);
                f(head);
index b4d88a5..980ca3c 100644 (file)
@@ -1969,14 +1969,14 @@ rcu_check_quiescent_state(struct rcu_data *rdp)
  */
 int rcutree_dying_cpu(unsigned int cpu)
 {
-       RCU_TRACE(bool blkd;)
-       RCU_TRACE(struct rcu_data *rdp = this_cpu_ptr(&rcu_data);)
-       RCU_TRACE(struct rcu_node *rnp = rdp->mynode;)
+       bool blkd;
+       struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
+       struct rcu_node *rnp = rdp->mynode;
 
        if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
                return 0;
 
-       RCU_TRACE(blkd = !!(rnp->qsmask & rdp->grpmask);)
+       blkd = !!(rnp->qsmask & rdp->grpmask);
        trace_rcu_grace_period(rcu_state.name, rnp->gp_seq,
                               blkd ? TPS("cpuofl") : TPS("cpuofl-bgp"));
        return 0;
index e1b79b6..b9e79e8 100644 (file)
@@ -31,6 +31,7 @@ EXPORT_SYMBOL(cad_pid);
 #define DEFAULT_REBOOT_MODE
 #endif
 enum reboot_mode reboot_mode DEFAULT_REBOOT_MODE;
+enum reboot_mode panic_reboot_mode = REBOOT_UNDEFINED;
 
 /*
  * This variable is used privately to keep track of whether or not
@@ -519,6 +520,8 @@ EXPORT_SYMBOL_GPL(orderly_reboot);
 static int __init reboot_setup(char *str)
 {
        for (;;) {
+               enum reboot_mode *mode;
+
                /*
                 * Having anything passed on the command line via
                 * reboot= will cause us to disable DMI checking
@@ -526,17 +529,24 @@ static int __init reboot_setup(char *str)
                 */
                reboot_default = 0;
 
+               if (!strncmp(str, "panic_", 6)) {
+                       mode = &panic_reboot_mode;
+                       str += 6;
+               } else {
+                       mode = &reboot_mode;
+               }
+
                switch (*str) {
                case 'w':
-                       reboot_mode = REBOOT_WARM;
+                       *mode = REBOOT_WARM;
                        break;
 
                case 'c':
-                       reboot_mode = REBOOT_COLD;
+                       *mode = REBOOT_COLD;
                        break;
 
                case 'h':
-                       reboot_mode = REBOOT_HARD;
+                       *mode = REBOOT_HARD;
                        break;
 
                case 's':
@@ -553,11 +563,11 @@ static int __init reboot_setup(char *str)
                                if (rc)
                                        return rc;
                        } else
-                               reboot_mode = REBOOT_SOFT;
+                               *mode = REBOOT_SOFT;
                        break;
                }
                case 'g':
-                       reboot_mode = REBOOT_GPIO;
+                       *mode = REBOOT_GPIO;
                        break;
 
                case 'b':
index 0e97ca9..7acc632 100644 (file)
@@ -4,6 +4,9 @@
  * Copyright (c) 2018 Facebook, Inc.
  * Author: Johannes Weiner <hannes@cmpxchg.org>
  *
+ * Polling support by Suren Baghdasaryan <surenb@google.com>
+ * Copyright (c) 2018 Google, Inc.
+ *
  * When CPU, memory and IO are contended, tasks experience delays that
  * reduce throughput and introduce latencies into the workload. Memory
  * and IO contention, in addition, can cause a full loss of forward
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
 #include <linux/seqlock.h>
+#include <linux/uaccess.h>
 #include <linux/cgroup.h>
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/ctype.h>
+#include <linux/file.h>
+#include <linux/poll.h>
 #include <linux/psi.h>
 #include "sched.h"
 
@@ -140,9 +147,9 @@ static int psi_bug __read_mostly;
 DEFINE_STATIC_KEY_FALSE(psi_disabled);
 
 #ifdef CONFIG_PSI_DEFAULT_DISABLED
-bool psi_enable;
+static bool psi_enable;
 #else
-bool psi_enable = true;
+static bool psi_enable = true;
 #endif
 static int __init setup_psi(char *str)
 {
@@ -156,16 +163,21 @@ __setup("psi=", setup_psi);
 #define EXP_60s                1981            /* 1/exp(2s/60s) */
 #define EXP_300s       2034            /* 1/exp(2s/300s) */
 
+/* PSI trigger definitions */
+#define WINDOW_MIN_US 500000   /* Min window size is 500ms */
+#define WINDOW_MAX_US 10000000 /* Max window size is 10s */
+#define UPDATES_PER_WINDOW 10  /* 10 updates per window */
+
 /* Sampling frequency in nanoseconds */
 static u64 psi_period __read_mostly;
 
 /* System-level pressure and stall tracking */
 static DEFINE_PER_CPU(struct psi_group_cpu, system_group_pcpu);
-static struct psi_group psi_system = {
+struct psi_group psi_system = {
        .pcpu = &system_group_pcpu,
 };
 
-static void psi_update_work(struct work_struct *work);
+static void psi_avgs_work(struct work_struct *work);
 
 static void group_init(struct psi_group *group)
 {
@@ -173,9 +185,20 @@ static void group_init(struct psi_group *group)
 
        for_each_possible_cpu(cpu)
                seqcount_init(&per_cpu_ptr(group->pcpu, cpu)->seq);
-       group->next_update = sched_clock() + psi_period;
-       INIT_DELAYED_WORK(&group->clock_work, psi_update_work);
-       mutex_init(&group->stat_lock);
+       group->avg_next_update = sched_clock() + psi_period;
+       INIT_DELAYED_WORK(&group->avgs_work, psi_avgs_work);
+       mutex_init(&group->avgs_lock);
+       /* Init trigger-related members */
+       atomic_set(&group->poll_scheduled, 0);
+       mutex_init(&group->trigger_lock);
+       INIT_LIST_HEAD(&group->triggers);
+       memset(group->nr_triggers, 0, sizeof(group->nr_triggers));
+       group->poll_states = 0;
+       group->poll_min_period = U32_MAX;
+       memset(group->polling_total, 0, sizeof(group->polling_total));
+       group->polling_next_update = ULLONG_MAX;
+       group->polling_until = 0;
+       rcu_assign_pointer(group->poll_kworker, NULL);
 }
 
 void __init psi_init(void)
@@ -210,20 +233,24 @@ static bool test_state(unsigned int *tasks, enum psi_states state)
        }
 }
 
-static void get_recent_times(struct psi_group *group, int cpu, u32 *times)
+static void get_recent_times(struct psi_group *group, int cpu,
+                            enum psi_aggregators aggregator, u32 *times,
+                            u32 *pchanged_states)
 {
        struct psi_group_cpu *groupc = per_cpu_ptr(group->pcpu, cpu);
-       unsigned int tasks[NR_PSI_TASK_COUNTS];
        u64 now, state_start;
+       enum psi_states s;
        unsigned int seq;
-       int s;
+       u32 state_mask;
+
+       *pchanged_states = 0;
 
        /* Snapshot a coherent view of the CPU state */
        do {
                seq = read_seqcount_begin(&groupc->seq);
                now = cpu_clock(cpu);
                memcpy(times, groupc->times, sizeof(groupc->times));
-               memcpy(tasks, groupc->tasks, sizeof(groupc->tasks));
+               state_mask = groupc->state_mask;
                state_start = groupc->state_start;
        } while (read_seqcount_retry(&groupc->seq, seq));
 
@@ -239,13 +266,15 @@ static void get_recent_times(struct psi_group *group, int cpu, u32 *times)
                 * (u32) and our reported pressure close to what's
                 * actually happening.
                 */
-               if (test_state(tasks, s))
+               if (state_mask & (1 << s))
                        times[s] += now - state_start;
 
-               delta = times[s] - groupc->times_prev[s];
-               groupc->times_prev[s] = times[s];
+               delta = times[s] - groupc->times_prev[aggregator][s];
+               groupc->times_prev[aggregator][s] = times[s];
 
                times[s] = delta;
+               if (delta)
+                       *pchanged_states |= (1 << s);
        }
 }
 
@@ -269,17 +298,16 @@ static void calc_avgs(unsigned long avg[3], int missed_periods,
        avg[2] = calc_load(avg[2], EXP_300s, pct);
 }
 
-static bool update_stats(struct psi_group *group)
+static void collect_percpu_times(struct psi_group *group,
+                                enum psi_aggregators aggregator,
+                                u32 *pchanged_states)
 {
        u64 deltas[NR_PSI_STATES - 1] = { 0, };
-       unsigned long missed_periods = 0;
        unsigned long nonidle_total = 0;
-       u64 now, expires, period;
+       u32 changed_states = 0;
        int cpu;
        int s;
 
-       mutex_lock(&group->stat_lock);
-
        /*
         * Collect the per-cpu time buckets and average them into a
         * single time sample that is normalized to wallclock time.
@@ -291,8 +319,11 @@ static bool update_stats(struct psi_group *group)
        for_each_possible_cpu(cpu) {
                u32 times[NR_PSI_STATES];
                u32 nonidle;
+               u32 cpu_changed_states;
 
-               get_recent_times(group, cpu, times);
+               get_recent_times(group, cpu, aggregator, times,
+                               &cpu_changed_states);
+               changed_states |= cpu_changed_states;
 
                nonidle = nsecs_to_jiffies(times[PSI_NONIDLE]);
                nonidle_total += nonidle;
@@ -315,13 +346,22 @@ static bool update_stats(struct psi_group *group)
 
        /* total= */
        for (s = 0; s < NR_PSI_STATES - 1; s++)
-               group->total[s] += div_u64(deltas[s], max(nonidle_total, 1UL));
+               group->total[aggregator][s] +=
+                               div_u64(deltas[s], max(nonidle_total, 1UL));
+
+       if (pchanged_states)
+               *pchanged_states = changed_states;
+}
+
+static u64 update_averages(struct psi_group *group, u64 now)
+{
+       unsigned long missed_periods = 0;
+       u64 expires, period;
+       u64 avg_next_update;
+       int s;
 
        /* avgX= */
-       now = sched_clock();
-       expires = group->next_update;
-       if (now < expires)
-               goto out;
+       expires = group->avg_next_update;
        if (now - expires >= psi_period)
                missed_periods = div_u64(now - expires, psi_period);
 
@@ -332,14 +372,14 @@ static bool update_stats(struct psi_group *group)
         * But the deltas we sample out of the per-cpu buckets above
         * are based on the actual time elapsing between clock ticks.
         */
-       group->next_update = expires + ((1 + missed_periods) * psi_period);
-       period = now - (group->last_update + (missed_periods * psi_period));
-       group->last_update = now;
+       avg_next_update = expires + ((1 + missed_periods) * psi_period);
+       period = now - (group->avg_last_update + (missed_periods * psi_period));
+       group->avg_last_update = now;
 
        for (s = 0; s < NR_PSI_STATES - 1; s++) {
                u32 sample;
 
-               sample = group->total[s] - group->total_prev[s];
+               sample = group->total[PSI_AVGS][s] - group->avg_total[s];
                /*
                 * Due to the lockless sampling of the time buckets,
                 * recorded time deltas can slip into the next period,
@@ -359,23 +399,30 @@ static bool update_stats(struct psi_group *group)
                 */
                if (sample > period)
                        sample = period;
-               group->total_prev[s] += sample;
+               group->avg_total[s] += sample;
                calc_avgs(group->avg[s], missed_periods, sample, period);
        }
-out:
-       mutex_unlock(&group->stat_lock);
-       return nonidle_total;
+
+       return avg_next_update;
 }
 
-static void psi_update_work(struct work_struct *work)
+static void psi_avgs_work(struct work_struct *work)
 {
        struct delayed_work *dwork;
        struct psi_group *group;
+       u32 changed_states;
        bool nonidle;
+       u64 now;
 
        dwork = to_delayed_work(work);
-       group = container_of(dwork, struct psi_group, clock_work);
+       group = container_of(dwork, struct psi_group, avgs_work);
+
+       mutex_lock(&group->avgs_lock);
 
+       now = sched_clock();
+
+       collect_percpu_times(group, PSI_AVGS, &changed_states);
+       nonidle = changed_states & (1 << PSI_NONIDLE);
        /*
         * If there is task activity, periodically fold the per-cpu
         * times and feed samples into the running averages. If things
@@ -383,18 +430,196 @@ static void psi_update_work(struct work_struct *work)
         * Once restarted, we'll catch up the running averages in one
         * go - see calc_avgs() and missed_periods.
         */
-
-       nonidle = update_stats(group);
+       if (now >= group->avg_next_update)
+               group->avg_next_update = update_averages(group, now);
 
        if (nonidle) {
-               unsigned long delay = 0;
-               u64 now;
+               schedule_delayed_work(dwork, nsecs_to_jiffies(
+                               group->avg_next_update - now) + 1);
+       }
+
+       mutex_unlock(&group->avgs_lock);
+}
+
+/* Trigger tracking window manupulations */
+static void window_reset(struct psi_window *win, u64 now, u64 value,
+                        u64 prev_growth)
+{
+       win->start_time = now;
+       win->start_value = value;
+       win->prev_growth = prev_growth;
+}
+
+/*
+ * PSI growth tracking window update and growth calculation routine.
+ *
+ * This approximates a sliding tracking window by interpolating
+ * partially elapsed windows using historical growth data from the
+ * previous intervals. This minimizes memory requirements (by not storing
+ * all the intermediate values in the previous window) and simplifies
+ * the calculations. It works well because PSI signal changes only in
+ * positive direction and over relatively small window sizes the growth
+ * is close to linear.
+ */
+static u64 window_update(struct psi_window *win, u64 now, u64 value)
+{
+       u64 elapsed;
+       u64 growth;
+
+       elapsed = now - win->start_time;
+       growth = value - win->start_value;
+       /*
+        * After each tracking window passes win->start_value and
+        * win->start_time get reset and win->prev_growth stores
+        * the average per-window growth of the previous window.
+        * win->prev_growth is then used to interpolate additional
+        * growth from the previous window assuming it was linear.
+        */
+       if (elapsed > win->size)
+               window_reset(win, now, value, growth);
+       else {
+               u32 remaining;
+
+               remaining = win->size - elapsed;
+               growth += div_u64(win->prev_growth * remaining, win->size);
+       }
+
+       return growth;
+}
+
+static void init_triggers(struct psi_group *group, u64 now)
+{
+       struct psi_trigger *t;
+
+       list_for_each_entry(t, &group->triggers, node)
+               window_reset(&t->win, now,
+                               group->total[PSI_POLL][t->state], 0);
+       memcpy(group->polling_total, group->total[PSI_POLL],
+                  sizeof(group->polling_total));
+       group->polling_next_update = now + group->poll_min_period;
+}
+
+static u64 update_triggers(struct psi_group *group, u64 now)
+{
+       struct psi_trigger *t;
+       bool new_stall = false;
+       u64 *total = group->total[PSI_POLL];
+
+       /*
+        * On subsequent updates, calculate growth deltas and let
+        * watchers know when their specified thresholds are exceeded.
+        */
+       list_for_each_entry(t, &group->triggers, node) {
+               u64 growth;
+
+               /* Check for stall activity */
+               if (group->polling_total[t->state] == total[t->state])
+                       continue;
+
+               /*
+                * Multiple triggers might be looking at the same state,
+                * remember to update group->polling_total[] once we've
+                * been through all of them. Also remember to extend the
+                * polling time if we see new stall activity.
+                */
+               new_stall = true;
+
+               /* Calculate growth since last update */
+               growth = window_update(&t->win, now, total[t->state]);
+               if (growth < t->threshold)
+                       continue;
+
+               /* Limit event signaling to once per window */
+               if (now < t->last_event_time + t->win.size)
+                       continue;
+
+               /* Generate an event */
+               if (cmpxchg(&t->event, 0, 1) == 0)
+                       wake_up_interruptible(&t->event_wait);
+               t->last_event_time = now;
+       }
+
+       if (new_stall)
+               memcpy(group->polling_total, total,
+                               sizeof(group->polling_total));
+
+       return now + group->poll_min_period;
+}
+
+/*
+ * Schedule polling if it's not already scheduled. It's safe to call even from
+ * hotpath because even though kthread_queue_delayed_work takes worker->lock
+ * spinlock that spinlock is never contended due to poll_scheduled atomic
+ * preventing such competition.
+ */
+static void psi_schedule_poll_work(struct psi_group *group, unsigned long delay)
+{
+       struct kthread_worker *kworker;
+
+       /* Do not reschedule if already scheduled */
+       if (atomic_cmpxchg(&group->poll_scheduled, 0, 1) != 0)
+               return;
+
+       rcu_read_lock();
 
-               now = sched_clock();
-               if (group->next_update > now)
-                       delay = nsecs_to_jiffies(group->next_update - now) + 1;
-               schedule_delayed_work(dwork, delay);
+       kworker = rcu_dereference(group->poll_kworker);
+       /*
+        * kworker might be NULL in case psi_trigger_destroy races with
+        * psi_task_change (hotpath) which can't use locks
+        */
+       if (likely(kworker))
+               kthread_queue_delayed_work(kworker, &group->poll_work, delay);
+       else
+               atomic_set(&group->poll_scheduled, 0);
+
+       rcu_read_unlock();
+}
+
+static void psi_poll_work(struct kthread_work *work)
+{
+       struct kthread_delayed_work *dwork;
+       struct psi_group *group;
+       u32 changed_states;
+       u64 now;
+
+       dwork = container_of(work, struct kthread_delayed_work, work);
+       group = container_of(dwork, struct psi_group, poll_work);
+
+       atomic_set(&group->poll_scheduled, 0);
+
+       mutex_lock(&group->trigger_lock);
+
+       now = sched_clock();
+
+       collect_percpu_times(group, PSI_POLL, &changed_states);
+
+       if (changed_states & group->poll_states) {
+               /* Initialize trigger windows when entering polling mode */
+               if (now > group->polling_until)
+                       init_triggers(group, now);
+
+               /*
+                * Keep the monitor active for at least the duration of the
+                * minimum tracking window as long as monitor states are
+                * changing.
+                */
+               group->polling_until = now +
+                       group->poll_min_period * UPDATES_PER_WINDOW;
+       }
+
+       if (now > group->polling_until) {
+               group->polling_next_update = ULLONG_MAX;
+               goto out;
        }
+
+       if (now >= group->polling_next_update)
+               group->polling_next_update = update_triggers(group, now);
+
+       psi_schedule_poll_work(group,
+               nsecs_to_jiffies(group->polling_next_update - now) + 1);
+
+out:
+       mutex_unlock(&group->trigger_lock);
 }
 
 static void record_times(struct psi_group_cpu *groupc, int cpu,
@@ -407,15 +632,15 @@ static void record_times(struct psi_group_cpu *groupc, int cpu,
        delta = now - groupc->state_start;
        groupc->state_start = now;
 
-       if (test_state(groupc->tasks, PSI_IO_SOME)) {
+       if (groupc->state_mask & (1 << PSI_IO_SOME)) {
                groupc->times[PSI_IO_SOME] += delta;
-               if (test_state(groupc->tasks, PSI_IO_FULL))
+               if (groupc->state_mask & (1 << PSI_IO_FULL))
                        groupc->times[PSI_IO_FULL] += delta;
        }
 
-       if (test_state(groupc->tasks, PSI_MEM_SOME)) {
+       if (groupc->state_mask & (1 << PSI_MEM_SOME)) {
                groupc->times[PSI_MEM_SOME] += delta;
-               if (test_state(groupc->tasks, PSI_MEM_FULL))
+               if (groupc->state_mask & (1 << PSI_MEM_FULL))
                        groupc->times[PSI_MEM_FULL] += delta;
                else if (memstall_tick) {
                        u32 sample;
@@ -436,18 +661,20 @@ static void record_times(struct psi_group_cpu *groupc, int cpu,
                }
        }
 
-       if (test_state(groupc->tasks, PSI_CPU_SOME))
+       if (groupc->state_mask & (1 << PSI_CPU_SOME))
                groupc->times[PSI_CPU_SOME] += delta;
 
-       if (test_state(groupc->tasks, PSI_NONIDLE))
+       if (groupc->state_mask & (1 << PSI_NONIDLE))
                groupc->times[PSI_NONIDLE] += delta;
 }
 
-static void psi_group_change(struct psi_group *group, int cpu,
-                            unsigned int clear, unsigned int set)
+static u32 psi_group_change(struct psi_group *group, int cpu,
+                           unsigned int clear, unsigned int set)
 {
        struct psi_group_cpu *groupc;
        unsigned int t, m;
+       enum psi_states s;
+       u32 state_mask = 0;
 
        groupc = per_cpu_ptr(group->pcpu, cpu);
 
@@ -480,7 +707,16 @@ static void psi_group_change(struct psi_group *group, int cpu,
                if (set & (1 << t))
                        groupc->tasks[t]++;
 
+       /* Calculate state mask representing active states */
+       for (s = 0; s < NR_PSI_STATES; s++) {
+               if (test_state(groupc->tasks, s))
+                       state_mask |= (1 << s);
+       }
+       groupc->state_mask = state_mask;
+
        write_seqcount_end(&groupc->seq);
+
+       return state_mask;
 }
 
 static struct psi_group *iterate_groups(struct task_struct *task, void **iter)
@@ -537,13 +773,17 @@ void psi_task_change(struct task_struct *task, int clear, int set)
         */
        if (unlikely((clear & TSK_RUNNING) &&
                     (task->flags & PF_WQ_WORKER) &&
-                    wq_worker_last_func(task) == psi_update_work))
+                    wq_worker_last_func(task) == psi_avgs_work))
                wake_clock = false;
 
        while ((group = iterate_groups(task, &iter))) {
-               psi_group_change(group, cpu, clear, set);
-               if (wake_clock && !delayed_work_pending(&group->clock_work))
-                       schedule_delayed_work(&group->clock_work, PSI_FREQ);
+               u32 state_mask = psi_group_change(group, cpu, clear, set);
+
+               if (state_mask & group->poll_states)
+                       psi_schedule_poll_work(group, 1);
+
+               if (wake_clock && !delayed_work_pending(&group->avgs_work))
+                       schedule_delayed_work(&group->avgs_work, PSI_FREQ);
        }
 }
 
@@ -640,8 +880,10 @@ void psi_cgroup_free(struct cgroup *cgroup)
        if (static_branch_likely(&psi_disabled))
                return;
 
-       cancel_delayed_work_sync(&cgroup->psi.clock_work);
+       cancel_delayed_work_sync(&cgroup->psi.avgs_work);
        free_percpu(cgroup->psi.pcpu);
+       /* All triggers must be removed by now */
+       WARN_ONCE(cgroup->psi.poll_states, "psi: trigger leak\n");
 }
 
 /**
@@ -697,11 +939,18 @@ void cgroup_move_task(struct task_struct *task, struct css_set *to)
 int psi_show(struct seq_file *m, struct psi_group *group, enum psi_res res)
 {
        int full;
+       u64 now;
 
        if (static_branch_likely(&psi_disabled))
                return -EOPNOTSUPP;
 
-       update_stats(group);
+       /* Update averages before reporting them */
+       mutex_lock(&group->avgs_lock);
+       now = sched_clock();
+       collect_percpu_times(group, PSI_AVGS, NULL);
+       if (now >= group->avg_next_update)
+               group->avg_next_update = update_averages(group, now);
+       mutex_unlock(&group->avgs_lock);
 
        for (full = 0; full < 2 - (res == PSI_CPU); full++) {
                unsigned long avg[3];
@@ -710,7 +959,8 @@ int psi_show(struct seq_file *m, struct psi_group *group, enum psi_res res)
 
                for (w = 0; w < 3; w++)
                        avg[w] = group->avg[res * 2 + full][w];
-               total = div_u64(group->total[res * 2 + full], NSEC_PER_USEC);
+               total = div_u64(group->total[PSI_AVGS][res * 2 + full],
+                               NSEC_PER_USEC);
 
                seq_printf(m, "%s avg10=%lu.%02lu avg60=%lu.%02lu avg300=%lu.%02lu total=%llu\n",
                           full ? "full" : "some",
@@ -753,25 +1003,270 @@ static int psi_cpu_open(struct inode *inode, struct file *file)
        return single_open(file, psi_cpu_show, NULL);
 }
 
+struct psi_trigger *psi_trigger_create(struct psi_group *group,
+                       char *buf, size_t nbytes, enum psi_res res)
+{
+       struct psi_trigger *t;
+       enum psi_states state;
+       u32 threshold_us;
+       u32 window_us;
+
+       if (static_branch_likely(&psi_disabled))
+               return ERR_PTR(-EOPNOTSUPP);
+
+       if (sscanf(buf, "some %u %u", &threshold_us, &window_us) == 2)
+               state = PSI_IO_SOME + res * 2;
+       else if (sscanf(buf, "full %u %u", &threshold_us, &window_us) == 2)
+               state = PSI_IO_FULL + res * 2;
+       else
+               return ERR_PTR(-EINVAL);
+
+       if (state >= PSI_NONIDLE)
+               return ERR_PTR(-EINVAL);
+
+       if (window_us < WINDOW_MIN_US ||
+               window_us > WINDOW_MAX_US)
+               return ERR_PTR(-EINVAL);
+
+       /* Check threshold */
+       if (threshold_us == 0 || threshold_us > window_us)
+               return ERR_PTR(-EINVAL);
+
+       t = kmalloc(sizeof(*t), GFP_KERNEL);
+       if (!t)
+               return ERR_PTR(-ENOMEM);
+
+       t->group = group;
+       t->state = state;
+       t->threshold = threshold_us * NSEC_PER_USEC;
+       t->win.size = window_us * NSEC_PER_USEC;
+       window_reset(&t->win, 0, 0, 0);
+
+       t->event = 0;
+       t->last_event_time = 0;
+       init_waitqueue_head(&t->event_wait);
+       kref_init(&t->refcount);
+
+       mutex_lock(&group->trigger_lock);
+
+       if (!rcu_access_pointer(group->poll_kworker)) {
+               struct sched_param param = {
+                       .sched_priority = MAX_RT_PRIO - 1,
+               };
+               struct kthread_worker *kworker;
+
+               kworker = kthread_create_worker(0, "psimon");
+               if (IS_ERR(kworker)) {
+                       kfree(t);
+                       mutex_unlock(&group->trigger_lock);
+                       return ERR_CAST(kworker);
+               }
+               sched_setscheduler(kworker->task, SCHED_FIFO, &param);
+               kthread_init_delayed_work(&group->poll_work,
+                               psi_poll_work);
+               rcu_assign_pointer(group->poll_kworker, kworker);
+       }
+
+       list_add(&t->node, &group->triggers);
+       group->poll_min_period = min(group->poll_min_period,
+               div_u64(t->win.size, UPDATES_PER_WINDOW));
+       group->nr_triggers[t->state]++;
+       group->poll_states |= (1 << t->state);
+
+       mutex_unlock(&group->trigger_lock);
+
+       return t;
+}
+
+static void psi_trigger_destroy(struct kref *ref)
+{
+       struct psi_trigger *t = container_of(ref, struct psi_trigger, refcount);
+       struct psi_group *group = t->group;
+       struct kthread_worker *kworker_to_destroy = NULL;
+
+       if (static_branch_likely(&psi_disabled))
+               return;
+
+       /*
+        * Wakeup waiters to stop polling. Can happen if cgroup is deleted
+        * from under a polling process.
+        */
+       wake_up_interruptible(&t->event_wait);
+
+       mutex_lock(&group->trigger_lock);
+
+       if (!list_empty(&t->node)) {
+               struct psi_trigger *tmp;
+               u64 period = ULLONG_MAX;
+
+               list_del(&t->node);
+               group->nr_triggers[t->state]--;
+               if (!group->nr_triggers[t->state])
+                       group->poll_states &= ~(1 << t->state);
+               /* reset min update period for the remaining triggers */
+               list_for_each_entry(tmp, &group->triggers, node)
+                       period = min(period, div_u64(tmp->win.size,
+                                       UPDATES_PER_WINDOW));
+               group->poll_min_period = period;
+               /* Destroy poll_kworker when the last trigger is destroyed */
+               if (group->poll_states == 0) {
+                       group->polling_until = 0;
+                       kworker_to_destroy = rcu_dereference_protected(
+                                       group->poll_kworker,
+                                       lockdep_is_held(&group->trigger_lock));
+                       rcu_assign_pointer(group->poll_kworker, NULL);
+               }
+       }
+
+       mutex_unlock(&group->trigger_lock);
+
+       /*
+        * Wait for both *trigger_ptr from psi_trigger_replace and
+        * poll_kworker RCUs to complete their read-side critical sections
+        * before destroying the trigger and optionally the poll_kworker
+        */
+       synchronize_rcu();
+       /*
+        * Destroy the kworker after releasing trigger_lock to prevent a
+        * deadlock while waiting for psi_poll_work to acquire trigger_lock
+        */
+       if (kworker_to_destroy) {
+               kthread_cancel_delayed_work_sync(&group->poll_work);
+               kthread_destroy_worker(kworker_to_destroy);
+       }
+       kfree(t);
+}
+
+void psi_trigger_replace(void **trigger_ptr, struct psi_trigger *new)
+{
+       struct psi_trigger *old = *trigger_ptr;
+
+       if (static_branch_likely(&psi_disabled))
+               return;
+
+       rcu_assign_pointer(*trigger_ptr, new);
+       if (old)
+               kref_put(&old->refcount, psi_trigger_destroy);
+}
+
+__poll_t psi_trigger_poll(void **trigger_ptr,
+                               struct file *file, poll_table *wait)
+{
+       __poll_t ret = DEFAULT_POLLMASK;
+       struct psi_trigger *t;
+
+       if (static_branch_likely(&psi_disabled))
+               return DEFAULT_POLLMASK | EPOLLERR | EPOLLPRI;
+
+       rcu_read_lock();
+
+       t = rcu_dereference(*(void __rcu __force **)trigger_ptr);
+       if (!t) {
+               rcu_read_unlock();
+               return DEFAULT_POLLMASK | EPOLLERR | EPOLLPRI;
+       }
+       kref_get(&t->refcount);
+
+       rcu_read_unlock();
+
+       poll_wait(file, &t->event_wait, wait);
+
+       if (cmpxchg(&t->event, 1, 0) == 1)
+               ret |= EPOLLPRI;
+
+       kref_put(&t->refcount, psi_trigger_destroy);
+
+       return ret;
+}
+
+static ssize_t psi_write(struct file *file, const char __user *user_buf,
+                        size_t nbytes, enum psi_res res)
+{
+       char buf[32];
+       size_t buf_size;
+       struct seq_file *seq;
+       struct psi_trigger *new;
+
+       if (static_branch_likely(&psi_disabled))
+               return -EOPNOTSUPP;
+
+       buf_size = min(nbytes, (sizeof(buf) - 1));
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+
+       buf[buf_size - 1] = '\0';
+
+       new = psi_trigger_create(&psi_system, buf, nbytes, res);
+       if (IS_ERR(new))
+               return PTR_ERR(new);
+
+       seq = file->private_data;
+       /* Take seq->lock to protect seq->private from concurrent writes */
+       mutex_lock(&seq->lock);
+       psi_trigger_replace(&seq->private, new);
+       mutex_unlock(&seq->lock);
+
+       return nbytes;
+}
+
+static ssize_t psi_io_write(struct file *file, const char __user *user_buf,
+                           size_t nbytes, loff_t *ppos)
+{
+       return psi_write(file, user_buf, nbytes, PSI_IO);
+}
+
+static ssize_t psi_memory_write(struct file *file, const char __user *user_buf,
+                               size_t nbytes, loff_t *ppos)
+{
+       return psi_write(file, user_buf, nbytes, PSI_MEM);
+}
+
+static ssize_t psi_cpu_write(struct file *file, const char __user *user_buf,
+                            size_t nbytes, loff_t *ppos)
+{
+       return psi_write(file, user_buf, nbytes, PSI_CPU);
+}
+
+static __poll_t psi_fop_poll(struct file *file, poll_table *wait)
+{
+       struct seq_file *seq = file->private_data;
+
+       return psi_trigger_poll(&seq->private, file, wait);
+}
+
+static int psi_fop_release(struct inode *inode, struct file *file)
+{
+       struct seq_file *seq = file->private_data;
+
+       psi_trigger_replace(&seq->private, NULL);
+       return single_release(inode, file);
+}
+
 static const struct file_operations psi_io_fops = {
        .open           = psi_io_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = single_release,
+       .write          = psi_io_write,
+       .poll           = psi_fop_poll,
+       .release        = psi_fop_release,
 };
 
 static const struct file_operations psi_memory_fops = {
        .open           = psi_memory_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = single_release,
+       .write          = psi_memory_write,
+       .poll           = psi_fop_poll,
+       .release        = psi_fop_release,
 };
 
 static const struct file_operations psi_cpu_fops = {
        .open           = psi_cpu_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = single_release,
+       .write          = psi_cpu_write,
+       .poll           = psi_fop_poll,
+       .release        = psi_fop_release,
 };
 
 static int __init psi_proc_init(void)
index 62f9aea..a1eb44d 100644 (file)
@@ -840,6 +840,7 @@ static int check_kill_permission(int sig, struct kernel_siginfo *info,
                         */
                        if (!sid || sid == task_session(current))
                                break;
+                       /* fall through */
                default:
                        return -EPERM;
                }
@@ -2112,6 +2113,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, kernel_siginfo_t
                preempt_enable_no_resched();
                cgroup_enter_frozen();
                freezable_schedule();
+               cgroup_leave_frozen(true);
        } else {
                /*
                 * By the time we got the lock, our tracer went away.
index 12df0e5..bdbfe8d 100644 (file)
@@ -1924,7 +1924,7 @@ static int validate_prctl_map(struct prctl_mm_map *prctl_map)
        ((unsigned long)prctl_map->__m1 __op                            \
         (unsigned long)prctl_map->__m2) ? 0 : -EINVAL
        error  = __prctl_check_order(start_code, <, end_code);
-       error |= __prctl_check_order(start_data, <, end_data);
+       error |= __prctl_check_order(start_data,<=, end_data);
        error |= __prctl_check_order(start_brk, <=, brk);
        error |= __prctl_check_order(arg_start, <=, arg_end);
        error |= __prctl_check_order(env_start, <=, env_end);
index 599510a..943c891 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/kexec.h>
 #include <linux/bpf.h>
 #include <linux/mount.h>
+#include <linux/userfaultfd_k.h>
 
 #include "../lib/kstrtox.h"
 
@@ -1719,6 +1720,17 @@ static struct ctl_table vm_table[] = {
                .extra1         = (void *)&mmap_rnd_compat_bits_min,
                .extra2         = (void *)&mmap_rnd_compat_bits_max,
        },
+#endif
+#ifdef CONFIG_USERFAULTFD
+       {
+               .procname       = "unprivileged_userfaultfd",
+               .data           = &sysctl_unprivileged_userfaultfd,
+               .maxlen         = sizeof(sysctl_unprivileged_userfaultfd),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
 #endif
        { }
 };
@@ -2874,8 +2886,10 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
                        if (neg)
                                continue;
                        val = convmul * val / convdiv;
-                       if ((min && val < *min) || (max && val > *max))
-                               continue;
+                       if ((min && val < *min) || (max && val > *max)) {
+                               err = -EINVAL;
+                               break;
+                       }
                        *i = val;
                } else {
                        val = convdiv * (*i) / convmul;
@@ -3158,17 +3172,19 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
 
        if (write) {
                char *kbuf, *p;
+               size_t skipped = 0;
 
-               if (left > PAGE_SIZE - 1)
+               if (left > PAGE_SIZE - 1) {
                        left = PAGE_SIZE - 1;
+                       /* How much of the buffer we'll skip this pass */
+                       skipped = *lenp - left;
+               }
 
                p = kbuf = memdup_user_nul(buffer, left);
                if (IS_ERR(kbuf))
                        return PTR_ERR(kbuf);
 
-               tmp_bitmap = kcalloc(BITS_TO_LONGS(bitmap_len),
-                                    sizeof(unsigned long),
-                                    GFP_KERNEL);
+               tmp_bitmap = bitmap_zalloc(bitmap_len, GFP_KERNEL);
                if (!tmp_bitmap) {
                        kfree(kbuf);
                        return -ENOMEM;
@@ -3177,9 +3193,22 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
                while (!err && left) {
                        unsigned long val_a, val_b;
                        bool neg;
+                       size_t saved_left;
 
+                       /* In case we stop parsing mid-number, we can reset */
+                       saved_left = left;
                        err = proc_get_long(&p, &left, &val_a, &neg, tr_a,
                                             sizeof(tr_a), &c);
+                       /*
+                        * If we consumed the entirety of a truncated buffer or
+                        * only one char is left (may be a "-"), then stop here,
+                        * reset, & come back for more.
+                        */
+                       if ((left <= 1) && skipped) {
+                               left = saved_left;
+                               break;
+                       }
+
                        if (err)
                                break;
                        if (val_a >= bitmap_len || neg) {
@@ -3197,6 +3226,15 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
                                err = proc_get_long(&p, &left, &val_b,
                                                     &neg, tr_b, sizeof(tr_b),
                                                     &c);
+                               /*
+                                * If we consumed all of a truncated buffer or
+                                * then stop here, reset, & come back for more.
+                                */
+                               if (!left && skipped) {
+                                       left = saved_left;
+                                       break;
+                               }
+
                                if (err)
                                        break;
                                if (val_b >= bitmap_len || neg ||
@@ -3215,6 +3253,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
                        proc_skip_char(&p, &left, '\n');
                }
                kfree(kbuf);
+               left += skipped;
        } else {
                unsigned long bit_a, bit_b = 0;
 
@@ -3259,7 +3298,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
                *ppos += *lenp;
        }
 
-       kfree(tmp_bitmap);
+       bitmap_free(tmp_bitmap);
        return err;
 }
 
index ac5555e..8de4f78 100644 (file)
@@ -691,7 +691,7 @@ static inline void process_adjtimex_modes(const struct __kernel_timex *txc,
                time_constant = max(time_constant, 0l);
        }
 
-       if (txc->modes & ADJ_TAI && txc->constant > 0)
+       if (txc->modes & ADJ_TAI && txc->constant >= 0)
                *time_tai = txc->constant;
 
        if (txc->modes & ADJ_OFFSET)
index b920358..a12aff8 100644 (file)
 #define INIT_OPS_HASH(opsname) \
        .func_hash              = &opsname.local_hash,                  \
        .local_hash.regex_lock  = __MUTEX_INITIALIZER(opsname.local_hash.regex_lock),
-#define ASSIGN_OPS_HASH(opsname, val) \
-       .func_hash              = val, \
-       .local_hash.regex_lock  = __MUTEX_INITIALIZER(opsname.local_hash.regex_lock),
 #else
 #define INIT_OPS_HASH(opsname)
-#define ASSIGN_OPS_HASH(opsname, val)
 #endif
 
 enum {
@@ -3880,7 +3876,7 @@ static int ftrace_hash_move_and_update_ops(struct ftrace_ops *ops,
 static bool module_exists(const char *module)
 {
        /* All modules have the symbol __this_module */
-       const char this_mod[] = "__this_module";
+       static const char this_mod[] = "__this_module";
        char modname[MAX_PARAM_PREFIX_LEN + sizeof(this_mod) + 2];
        unsigned long val;
        int n;
@@ -6265,6 +6261,9 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
        preempt_disable_notrace();
 
        do_for_each_ftrace_op(op, ftrace_ops_list) {
+               /* Stub functions don't need to be called nor tested */
+               if (op->flags & FTRACE_OPS_FL_STUB)
+                       continue;
                /*
                 * Check the following for each ops before calling their func:
                 *  if RCU flag is set, then rcu_is_watching() must be true
index 4ee8d8a..05b0b31 100644 (file)
@@ -4979,7 +4979,7 @@ static __init int rb_write_something(struct rb_test_data *data, bool nested)
        cnt = data->cnt + (nested ? 27 : 0);
 
        /* Multiply cnt by ~e, to make some unique increment */
-       size = (data->cnt * 68 / 25) % (sizeof(rb_string) - 1);
+       size = (cnt * 68 / 25) % (sizeof(rb_string) - 1);
 
        len = size + sizeof(struct rb_item);
 
index ffba678..0564f6d 100644 (file)
@@ -362,7 +362,7 @@ static void ring_buffer_producer(void)
                        hit--; /* make it non zero */
                }
 
-               /* Caculate the average time in nanosecs */
+               /* Calculate the average time in nanosecs */
                avg = NSEC_PER_MSEC / (hit + missed);
                trace_printk("%ld ns per entry\n", avg);
        }
index ec43999..2c92b3d 100644 (file)
@@ -1727,6 +1727,10 @@ static __init int init_trace_selftests(void)
        pr_info("Running postponed tracer tests:\n");
 
        list_for_each_entry_safe(p, n, &postponed_selftests, list) {
+               /* This loop can take minutes when sanitizers are enabled, so
+                * lets make sure we allow RCU processing.
+                */
+               cond_resched();
                ret = run_tracer_selftest(p->type);
                /* If the test fails, then warn and remove from available_tracers */
                if (ret < 0) {
@@ -3045,6 +3049,7 @@ void trace_printk_init_buffers(void)
        if (global_trace.trace_buffer.buffer)
                tracing_start_cmdline_record();
 }
+EXPORT_SYMBOL_GPL(trace_printk_init_buffers);
 
 void trace_printk_start_comm(void)
 {
@@ -3205,6 +3210,7 @@ int trace_array_printk(struct trace_array *tr,
        va_end(ap);
        return ret;
 }
+EXPORT_SYMBOL_GPL(trace_array_printk);
 
 __printf(3, 4)
 int trace_array_printk_buf(struct ring_buffer *buffer,
@@ -3482,34 +3488,69 @@ static void s_stop(struct seq_file *m, void *p)
        trace_event_read_unlock();
 }
 
+static void
+get_total_entries_cpu(struct trace_buffer *buf, unsigned long *total,
+                     unsigned long *entries, int cpu)
+{
+       unsigned long count;
+
+       count = ring_buffer_entries_cpu(buf->buffer, cpu);
+       /*
+        * If this buffer has skipped entries, then we hold all
+        * entries for the trace and we need to ignore the
+        * ones before the time stamp.
+        */
+       if (per_cpu_ptr(buf->data, cpu)->skipped_entries) {
+               count -= per_cpu_ptr(buf->data, cpu)->skipped_entries;
+               /* total is the same as the entries */
+               *total = count;
+       } else
+               *total = count +
+                       ring_buffer_overrun_cpu(buf->buffer, cpu);
+       *entries = count;
+}
+
 static void
 get_total_entries(struct trace_buffer *buf,
                  unsigned long *total, unsigned long *entries)
 {
-       unsigned long count;
+       unsigned long t, e;
        int cpu;
 
        *total = 0;
        *entries = 0;
 
        for_each_tracing_cpu(cpu) {
-               count = ring_buffer_entries_cpu(buf->buffer, cpu);
-               /*
-                * If this buffer has skipped entries, then we hold all
-                * entries for the trace and we need to ignore the
-                * ones before the time stamp.
-                */
-               if (per_cpu_ptr(buf->data, cpu)->skipped_entries) {
-                       count -= per_cpu_ptr(buf->data, cpu)->skipped_entries;
-                       /* total is the same as the entries */
-                       *total += count;
-               } else
-                       *total += count +
-                               ring_buffer_overrun_cpu(buf->buffer, cpu);
-               *entries += count;
+               get_total_entries_cpu(buf, &t, &e, cpu);
+               *total += t;
+               *entries += e;
        }
 }
 
+unsigned long trace_total_entries_cpu(struct trace_array *tr, int cpu)
+{
+       unsigned long total, entries;
+
+       if (!tr)
+               tr = &global_trace;
+
+       get_total_entries_cpu(&tr->trace_buffer, &total, &entries, cpu);
+
+       return entries;
+}
+
+unsigned long trace_total_entries(struct trace_array *tr)
+{
+       unsigned long total, entries;
+
+       if (!tr)
+               tr = &global_trace;
+
+       get_total_entries(&tr->trace_buffer, &total, &entries);
+
+       return entries;
+}
+
 static void print_lat_help_header(struct seq_file *m)
 {
        seq_puts(m, "#                  _------=> CPU#            \n"
@@ -3548,25 +3589,18 @@ static void print_func_help_header_irq(struct trace_buffer *buf, struct seq_file
                                       unsigned int flags)
 {
        bool tgid = flags & TRACE_ITER_RECORD_TGID;
-       const char tgid_space[] = "          ";
-       const char space[] = "  ";
+       const char *space = "          ";
+       int prec = tgid ? 10 : 2;
 
        print_event_info(buf, m);
 
-       seq_printf(m, "#                          %s  _-----=> irqs-off\n",
-                  tgid ? tgid_space : space);
-       seq_printf(m, "#                          %s / _----=> need-resched\n",
-                  tgid ? tgid_space : space);
-       seq_printf(m, "#                          %s| / _---=> hardirq/softirq\n",
-                  tgid ? tgid_space : space);
-       seq_printf(m, "#                          %s|| / _--=> preempt-depth\n",
-                  tgid ? tgid_space : space);
-       seq_printf(m, "#                          %s||| /     delay\n",
-                  tgid ? tgid_space : space);
-       seq_printf(m, "#           TASK-PID %sCPU#  ||||    TIMESTAMP  FUNCTION\n",
-                  tgid ? "   TGID   " : space);
-       seq_printf(m, "#              | |   %s  |   ||||       |         |\n",
-                  tgid ? "     |    " : space);
+       seq_printf(m, "#                          %.*s  _-----=> irqs-off\n", prec, space);
+       seq_printf(m, "#                          %.*s / _----=> need-resched\n", prec, space);
+       seq_printf(m, "#                          %.*s| / _---=> hardirq/softirq\n", prec, space);
+       seq_printf(m, "#                          %.*s|| / _--=> preempt-depth\n", prec, space);
+       seq_printf(m, "#                          %.*s||| /     delay\n", prec, space);
+       seq_printf(m, "#           TASK-PID %.*sCPU#  ||||    TIMESTAMP  FUNCTION\n", prec, "   TGID   ");
+       seq_printf(m, "#              | |   %.*s  |   ||||       |         |\n", prec, "     |    ");
 }
 
 void
@@ -4692,6 +4726,7 @@ static const char readme_msg[] =
        "  trace_pipe\t\t- A consuming read to see the contents of the buffer\n"
        "  current_tracer\t- function and latency tracers\n"
        "  available_tracers\t- list of configured tracers for current_tracer\n"
+       "  error_log\t- error log for failed commands (that support it)\n"
        "  buffer_size_kb\t- view and modify size of per cpu buffer\n"
        "  buffer_total_size_kb  - view total size of all cpu buffers\n\n"
        "  trace_clock\t\t-change the clock used to order events\n"
@@ -4712,7 +4747,7 @@ static const char readme_msg[] =
        "  instances\t\t- Make sub-buffers with: mkdir instances/foo\n"
        "\t\t\t  Remove sub-buffer with rmdir\n"
        "  trace_options\t\t- Set format or modify how tracing happens\n"
-       "\t\t\t  Disable an option by adding a suffix 'no' to the\n"
+       "\t\t\t  Disable an option by prefixing 'no' to the\n"
        "\t\t\t  option name\n"
        "  saved_cmdlines_size\t- echo command number in here to store comm-pid list\n"
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -6296,13 +6331,13 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
        struct ring_buffer *buffer;
        struct print_entry *entry;
        unsigned long irq_flags;
-       const char faulted[] = "<faulted>";
        ssize_t written;
        int size;
        int len;
 
 /* Used in tracing_mark_raw_write() as well */
-#define FAULTED_SIZE (sizeof(faulted) - 1) /* '\0' is already accounted for */
+#define FAULTED_STR "<faulted>"
+#define FAULTED_SIZE (sizeof(FAULTED_STR) - 1) /* '\0' is already accounted for */
 
        if (tracing_disabled)
                return -EINVAL;
@@ -6334,7 +6369,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
 
        len = __copy_from_user_inatomic(&entry->buf, ubuf, cnt);
        if (len) {
-               memcpy(&entry->buf, faulted, FAULTED_SIZE);
+               memcpy(&entry->buf, FAULTED_STR, FAULTED_SIZE);
                cnt = FAULTED_SIZE;
                written = -EFAULT;
        } else
@@ -6375,7 +6410,6 @@ tracing_mark_raw_write(struct file *filp, const char __user *ubuf,
        struct ring_buffer_event *event;
        struct ring_buffer *buffer;
        struct raw_data_entry *entry;
-       const char faulted[] = "<faulted>";
        unsigned long irq_flags;
        ssize_t written;
        int size;
@@ -6415,7 +6449,7 @@ tracing_mark_raw_write(struct file *filp, const char __user *ubuf,
        len = __copy_from_user_inatomic(&entry->id, ubuf, cnt);
        if (len) {
                entry->id = -1;
-               memcpy(&entry->buf, faulted, FAULTED_SIZE);
+               memcpy(&entry->buf, FAULTED_STR, FAULTED_SIZE);
                written = -EFAULT;
        } else
                written = cnt;
@@ -6868,6 +6902,238 @@ static const struct file_operations snapshot_raw_fops = {
 
 #endif /* CONFIG_TRACER_SNAPSHOT */
 
+#define TRACING_LOG_ERRS_MAX   8
+#define TRACING_LOG_LOC_MAX    128
+
+#define CMD_PREFIX "  Command: "
+
+struct err_info {
+       const char      **errs; /* ptr to loc-specific array of err strings */
+       u8              type;   /* index into errs -> specific err string */
+       u8              pos;    /* MAX_FILTER_STR_VAL = 256 */
+       u64             ts;
+};
+
+struct tracing_log_err {
+       struct list_head        list;
+       struct err_info         info;
+       char                    loc[TRACING_LOG_LOC_MAX]; /* err location */
+       char                    cmd[MAX_FILTER_STR_VAL]; /* what caused err */
+};
+
+static DEFINE_MUTEX(tracing_err_log_lock);
+
+struct tracing_log_err *get_tracing_log_err(struct trace_array *tr)
+{
+       struct tracing_log_err *err;
+
+       if (tr->n_err_log_entries < TRACING_LOG_ERRS_MAX) {
+               err = kzalloc(sizeof(*err), GFP_KERNEL);
+               if (!err)
+                       err = ERR_PTR(-ENOMEM);
+               tr->n_err_log_entries++;
+
+               return err;
+       }
+
+       err = list_first_entry(&tr->err_log, struct tracing_log_err, list);
+       list_del(&err->list);
+
+       return err;
+}
+
+/**
+ * err_pos - find the position of a string within a command for error careting
+ * @cmd: The tracing command that caused the error
+ * @str: The string to position the caret at within @cmd
+ *
+ * Finds the position of the first occurence of @str within @cmd.  The
+ * return value can be passed to tracing_log_err() for caret placement
+ * within @cmd.
+ *
+ * Returns the index within @cmd of the first occurence of @str or 0
+ * if @str was not found.
+ */
+unsigned int err_pos(char *cmd, const char *str)
+{
+       char *found;
+
+       if (WARN_ON(!strlen(cmd)))
+               return 0;
+
+       found = strstr(cmd, str);
+       if (found)
+               return found - cmd;
+
+       return 0;
+}
+
+/**
+ * tracing_log_err - write an error to the tracing error log
+ * @tr: The associated trace array for the error (NULL for top level array)
+ * @loc: A string describing where the error occurred
+ * @cmd: The tracing command that caused the error
+ * @errs: The array of loc-specific static error strings
+ * @type: The index into errs[], which produces the specific static err string
+ * @pos: The position the caret should be placed in the cmd
+ *
+ * Writes an error into tracing/error_log of the form:
+ *
+ * <loc>: error: <text>
+ *   Command: <cmd>
+ *              ^
+ *
+ * tracing/error_log is a small log file containing the last
+ * TRACING_LOG_ERRS_MAX errors (8).  Memory for errors isn't allocated
+ * unless there has been a tracing error, and the error log can be
+ * cleared and have its memory freed by writing the empty string in
+ * truncation mode to it i.e. echo > tracing/error_log.
+ *
+ * NOTE: the @errs array along with the @type param are used to
+ * produce a static error string - this string is not copied and saved
+ * when the error is logged - only a pointer to it is saved.  See
+ * existing callers for examples of how static strings are typically
+ * defined for use with tracing_log_err().
+ */
+void tracing_log_err(struct trace_array *tr,
+                    const char *loc, const char *cmd,
+                    const char **errs, u8 type, u8 pos)
+{
+       struct tracing_log_err *err;
+
+       if (!tr)
+               tr = &global_trace;
+
+       mutex_lock(&tracing_err_log_lock);
+       err = get_tracing_log_err(tr);
+       if (PTR_ERR(err) == -ENOMEM) {
+               mutex_unlock(&tracing_err_log_lock);
+               return;
+       }
+
+       snprintf(err->loc, TRACING_LOG_LOC_MAX, "%s: error: ", loc);
+       snprintf(err->cmd, MAX_FILTER_STR_VAL,"\n" CMD_PREFIX "%s\n", cmd);
+
+       err->info.errs = errs;
+       err->info.type = type;
+       err->info.pos = pos;
+       err->info.ts = local_clock();
+
+       list_add_tail(&err->list, &tr->err_log);
+       mutex_unlock(&tracing_err_log_lock);
+}
+
+static void clear_tracing_err_log(struct trace_array *tr)
+{
+       struct tracing_log_err *err, *next;
+
+       mutex_lock(&tracing_err_log_lock);
+       list_for_each_entry_safe(err, next, &tr->err_log, list) {
+               list_del(&err->list);
+               kfree(err);
+       }
+
+       tr->n_err_log_entries = 0;
+       mutex_unlock(&tracing_err_log_lock);
+}
+
+static void *tracing_err_log_seq_start(struct seq_file *m, loff_t *pos)
+{
+       struct trace_array *tr = m->private;
+
+       mutex_lock(&tracing_err_log_lock);
+
+       return seq_list_start(&tr->err_log, *pos);
+}
+
+static void *tracing_err_log_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       struct trace_array *tr = m->private;
+
+       return seq_list_next(v, &tr->err_log, pos);
+}
+
+static void tracing_err_log_seq_stop(struct seq_file *m, void *v)
+{
+       mutex_unlock(&tracing_err_log_lock);
+}
+
+static void tracing_err_log_show_pos(struct seq_file *m, u8 pos)
+{
+       u8 i;
+
+       for (i = 0; i < sizeof(CMD_PREFIX) - 1; i++)
+               seq_putc(m, ' ');
+       for (i = 0; i < pos; i++)
+               seq_putc(m, ' ');
+       seq_puts(m, "^\n");
+}
+
+static int tracing_err_log_seq_show(struct seq_file *m, void *v)
+{
+       struct tracing_log_err *err = v;
+
+       if (err) {
+               const char *err_text = err->info.errs[err->info.type];
+               u64 sec = err->info.ts;
+               u32 nsec;
+
+               nsec = do_div(sec, NSEC_PER_SEC);
+               seq_printf(m, "[%5llu.%06u] %s%s", sec, nsec / 1000,
+                          err->loc, err_text);
+               seq_printf(m, "%s", err->cmd);
+               tracing_err_log_show_pos(m, err->info.pos);
+       }
+
+       return 0;
+}
+
+static const struct seq_operations tracing_err_log_seq_ops = {
+       .start  = tracing_err_log_seq_start,
+       .next   = tracing_err_log_seq_next,
+       .stop   = tracing_err_log_seq_stop,
+       .show   = tracing_err_log_seq_show
+};
+
+static int tracing_err_log_open(struct inode *inode, struct file *file)
+{
+       struct trace_array *tr = inode->i_private;
+       int ret = 0;
+
+       if (trace_array_get(tr) < 0)
+               return -ENODEV;
+
+       /* If this file was opened for write, then erase contents */
+       if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC))
+               clear_tracing_err_log(tr);
+
+       if (file->f_mode & FMODE_READ) {
+               ret = seq_open(file, &tracing_err_log_seq_ops);
+               if (!ret) {
+                       struct seq_file *m = file->private_data;
+                       m->private = tr;
+               } else {
+                       trace_array_put(tr);
+               }
+       }
+       return ret;
+}
+
+static ssize_t tracing_err_log_write(struct file *file,
+                                    const char __user *buffer,
+                                    size_t count, loff_t *ppos)
+{
+       return count;
+}
+
+static const struct file_operations tracing_err_log_fops = {
+       .open           = tracing_err_log_open,
+       .write          = tracing_err_log_write,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = tracing_release_generic_tr,
+};
+
 static int tracing_buffers_open(struct inode *inode, struct file *filp)
 {
        struct trace_array *tr = inode->i_private;
@@ -8033,7 +8299,7 @@ static void update_tracer_options(struct trace_array *tr)
        mutex_unlock(&trace_types_lock);
 }
 
-static int instance_mkdir(const char *name)
+struct trace_array *trace_array_create(const char *name)
 {
        struct trace_array *tr;
        int ret;
@@ -8072,6 +8338,7 @@ static int instance_mkdir(const char *name)
        INIT_LIST_HEAD(&tr->systems);
        INIT_LIST_HEAD(&tr->events);
        INIT_LIST_HEAD(&tr->hist_vars);
+       INIT_LIST_HEAD(&tr->err_log);
 
        if (allocate_trace_buffers(tr, trace_buf_size) < 0)
                goto out_free_tr;
@@ -8097,7 +8364,7 @@ static int instance_mkdir(const char *name)
        mutex_unlock(&trace_types_lock);
        mutex_unlock(&event_mutex);
 
-       return 0;
+       return tr;
 
  out_free_tr:
        free_trace_buffers(tr);
@@ -8109,33 +8376,21 @@ static int instance_mkdir(const char *name)
        mutex_unlock(&trace_types_lock);
        mutex_unlock(&event_mutex);
 
-       return ret;
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(trace_array_create);
 
+static int instance_mkdir(const char *name)
+{
+       return PTR_ERR_OR_ZERO(trace_array_create(name));
 }
 
-static int instance_rmdir(const char *name)
+static int __remove_instance(struct trace_array *tr)
 {
-       struct trace_array *tr;
-       int found = 0;
-       int ret;
        int i;
 
-       mutex_lock(&event_mutex);
-       mutex_lock(&trace_types_lock);
-
-       ret = -ENODEV;
-       list_for_each_entry(tr, &ftrace_trace_arrays, list) {
-               if (tr->name && strcmp(tr->name, name) == 0) {
-                       found = 1;
-                       break;
-               }
-       }
-       if (!found)
-               goto out_unlock;
-
-       ret = -EBUSY;
        if (tr->ref || (tr->current_trace && tr->current_trace->ref))
-               goto out_unlock;
+               return -EBUSY;
 
        list_del(&tr->list);
 
@@ -8161,10 +8416,46 @@ static int instance_rmdir(const char *name)
        free_cpumask_var(tr->tracing_cpumask);
        kfree(tr->name);
        kfree(tr);
+       tr = NULL;
 
-       ret = 0;
+       return 0;
+}
+
+int trace_array_destroy(struct trace_array *tr)
+{
+       int ret;
+
+       if (!tr)
+               return -EINVAL;
+
+       mutex_lock(&event_mutex);
+       mutex_lock(&trace_types_lock);
+
+       ret = __remove_instance(tr);
+
+       mutex_unlock(&trace_types_lock);
+       mutex_unlock(&event_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(trace_array_destroy);
+
+static int instance_rmdir(const char *name)
+{
+       struct trace_array *tr;
+       int ret;
+
+       mutex_lock(&event_mutex);
+       mutex_lock(&trace_types_lock);
+
+       ret = -ENODEV;
+       list_for_each_entry(tr, &ftrace_trace_arrays, list) {
+               if (tr->name && strcmp(tr->name, name) == 0) {
+                       ret = __remove_instance(tr);
+                       break;
+               }
+       }
 
- out_unlock:
        mutex_unlock(&trace_types_lock);
        mutex_unlock(&event_mutex);
 
@@ -8254,6 +8545,9 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
                          tr, &snapshot_fops);
 #endif
 
+       trace_create_file("error_log", 0644, d_tracer,
+                         tr, &tracing_err_log_fops);
+
        for_each_tracing_cpu(cpu)
                tracing_init_tracefs_percpu(tr, cpu);
 
@@ -8839,6 +9133,7 @@ __init static int tracer_alloc_buffers(void)
        INIT_LIST_HEAD(&global_trace.systems);
        INIT_LIST_HEAD(&global_trace.events);
        INIT_LIST_HEAD(&global_trace.hist_vars);
+       INIT_LIST_HEAD(&global_trace.err_log);
        list_add(&global_trace.list, &ftrace_trace_arrays);
 
        apply_trace_boot_options();
index 639047b..1974ce8 100644 (file)
@@ -293,11 +293,13 @@ struct trace_array {
        int                     nr_topts;
        bool                    clear_trace;
        int                     buffer_percent;
+       unsigned int            n_err_log_entries;
        struct tracer           *current_trace;
        unsigned int            trace_flags;
        unsigned char           trace_flags_index[TRACE_FLAGS_MAX_SIZE];
        unsigned int            flags;
        raw_spinlock_t          start_lock;
+       struct list_head        err_log;
        struct dentry           *dir;
        struct dentry           *options;
        struct dentry           *percpu_dir;
@@ -719,6 +721,9 @@ void trace_init_global_iter(struct trace_iterator *iter);
 
 void tracing_iter_reset(struct trace_iterator *iter, int cpu);
 
+unsigned long trace_total_entries_cpu(struct trace_array *tr, int cpu);
+unsigned long trace_total_entries(struct trace_array *tr);
+
 void trace_function(struct trace_array *tr,
                    unsigned long ip,
                    unsigned long parent_ip,
@@ -1545,7 +1550,8 @@ extern int apply_subsystem_event_filter(struct trace_subsystem_dir *dir,
 extern void print_subsystem_event_filter(struct event_subsystem *system,
                                         struct trace_seq *s);
 extern int filter_assign_type(const char *type);
-extern int create_event_filter(struct trace_event_call *call,
+extern int create_event_filter(struct trace_array *tr,
+                              struct trace_event_call *call,
                               char *filter_str, bool set_str,
                               struct event_filter **filterp);
 extern void free_event_filter(struct event_filter *filter);
@@ -1876,6 +1882,11 @@ extern ssize_t trace_parse_run_command(struct file *file,
                const char __user *buffer, size_t count, loff_t *ppos,
                int (*createfn)(int, char**));
 
+extern unsigned int err_pos(char *cmd, const char *str);
+extern void tracing_log_err(struct trace_array *tr,
+                           const char *loc, const char *cmd,
+                           const char **errs, u8 type, u8 pos);
+
 /*
  * Normal trace_printk() and friends allocates special buffers
  * to do the manipulation, as well as saves the print formats
index 5b3b0c3..0ce3db6 100644 (file)
@@ -832,6 +832,7 @@ static int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(ftrace_set_clr_event);
 
 /**
  * trace_set_clr_event - enable or disable an event
@@ -1318,9 +1319,6 @@ event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
        char buf[32];
        int len;
 
-       if (*ppos)
-               return 0;
-
        if (unlikely(!id))
                return -ENODEV;
 
index 05a6649..d3e5931 100644 (file)
@@ -66,7 +66,8 @@ static const char * ops[] = { OPS };
        C(INVALID_FILTER,       "Meaningless filter expression"),       \
        C(IP_FIELD_ONLY,        "Only 'ip' field is supported for function trace"), \
        C(INVALID_VALUE,        "Invalid value (did you forget quotes)?"), \
-       C(NO_FILTER,            "No filter found"),
+       C(ERRNO,                "Error"),                               \
+       C(NO_FILTER,            "No filter found")
 
 #undef C
 #define C(a, b)                FILT_ERR_##a
@@ -76,7 +77,7 @@ enum { ERRORS };
 #undef C
 #define C(a, b)                b
 
-static char *err_text[] = { ERRORS };
+static const char *err_text[] = { ERRORS };
 
 /* Called after a '!' character but "!=" and "!~" are not "not"s */
 static bool is_not(const char *str)
@@ -919,7 +920,8 @@ static void remove_filter_string(struct event_filter *filter)
        filter->filter_string = NULL;
 }
 
-static void append_filter_err(struct filter_parse_error *pe,
+static void append_filter_err(struct trace_array *tr,
+                             struct filter_parse_error *pe,
                              struct event_filter *filter)
 {
        struct trace_seq *s;
@@ -947,8 +949,14 @@ static void append_filter_err(struct filter_parse_error *pe,
        if (pe->lasterr > 0) {
                trace_seq_printf(s, "\n%*s", pos, "^");
                trace_seq_printf(s, "\nparse_error: %s\n", err_text[pe->lasterr]);
+               tracing_log_err(tr, "event filter parse error",
+                               filter->filter_string, err_text,
+                               pe->lasterr, pe->lasterr_pos);
        } else {
                trace_seq_printf(s, "\nError: (%d)\n", pe->lasterr);
+               tracing_log_err(tr, "event filter parse error",
+                               filter->filter_string, err_text,
+                               FILT_ERR_ERRNO, 0);
        }
        trace_seq_putc(s, 0);
        buf = kmemdup_nul(s->buffer, s->seq.len, GFP_KERNEL);
@@ -1214,30 +1222,30 @@ static int parse_pred(const char *str, void *data,
                 * (perf doesn't use it) and grab everything.
                 */
                if (strcmp(field->name, "ip") != 0) {
-                        parse_error(pe, FILT_ERR_IP_FIELD_ONLY, pos + i);
-                        goto err_free;
-                }
-                pred->fn = filter_pred_none;
-
-                /*
-                 * Quotes are not required, but if they exist then we need
-                 * to read them till we hit a matching one.
-                 */
-                if (str[i] == '\'' || str[i] == '"')
-                        q = str[i];
-                else
-                        q = 0;
-
-                for (i++; str[i]; i++) {
-                        if (q && str[i] == q)
-                                break;
-                        if (!q && (str[i] == ')' || str[i] == '&' ||
-                                   str[i] == '|'))
-                                break;
-                }
-                /* Skip quotes */
-                if (q)
-                        s++;
+                       parse_error(pe, FILT_ERR_IP_FIELD_ONLY, pos + i);
+                       goto err_free;
+               }
+               pred->fn = filter_pred_none;
+
+               /*
+                * Quotes are not required, but if they exist then we need
+                * to read them till we hit a matching one.
+                */
+               if (str[i] == '\'' || str[i] == '"')
+                       q = str[i];
+               else
+                       q = 0;
+
+               for (i++; str[i]; i++) {
+                       if (q && str[i] == q)
+                               break;
+                       if (!q && (str[i] == ')' || str[i] == '&' ||
+                                  str[i] == '|'))
+                               break;
+               }
+               /* Skip quotes */
+               if (q)
+                       s++;
                len = i - s;
                if (len >= MAX_FILTER_STR_VAL) {
                        parse_error(pe, FILT_ERR_OPERAND_TOO_LONG, pos + i);
@@ -1600,7 +1608,7 @@ static int process_system_preds(struct trace_subsystem_dir *dir,
                if (err) {
                        filter_disable(file);
                        parse_error(pe, FILT_ERR_BAD_SUBSYS_FILTER, 0);
-                       append_filter_err(pe, filter);
+                       append_filter_err(tr, pe, filter);
                } else
                        event_set_filtered_flag(file);
 
@@ -1712,7 +1720,8 @@ static void create_filter_finish(struct filter_parse_error *pe)
  * information if @set_str is %true and the caller is responsible for
  * freeing it.
  */
-static int create_filter(struct trace_event_call *call,
+static int create_filter(struct trace_array *tr,
+                        struct trace_event_call *call,
                         char *filter_string, bool set_str,
                         struct event_filter **filterp)
 {
@@ -1729,17 +1738,18 @@ static int create_filter(struct trace_event_call *call,
 
        err = process_preds(call, filter_string, *filterp, pe);
        if (err && set_str)
-               append_filter_err(pe, *filterp);
+               append_filter_err(tr, pe, *filterp);
        create_filter_finish(pe);
 
        return err;
 }
 
-int create_event_filter(struct trace_event_call *call,
+int create_event_filter(struct trace_array *tr,
+                       struct trace_event_call *call,
                        char *filter_str, bool set_str,
                        struct event_filter **filterp)
 {
-       return create_filter(call, filter_str, set_str, filterp);
+       return create_filter(tr, call, filter_str, set_str, filterp);
 }
 
 /**
@@ -1766,7 +1776,7 @@ static int create_system_filter(struct trace_subsystem_dir *dir,
                        kfree((*filterp)->filter_string);
                        (*filterp)->filter_string = NULL;
                } else {
-                       append_filter_err(pe, *filterp);
+                       append_filter_err(tr, pe, *filterp);
                }
        }
        create_filter_finish(pe);
@@ -1797,7 +1807,7 @@ int apply_event_filter(struct trace_event_file *file, char *filter_string)
                return 0;
        }
 
-       err = create_filter(call, filter_string, true, &filter);
+       err = create_filter(file->tr, call, filter_string, true, &filter);
 
        /*
         * Always swap the call filter with the new filter
@@ -2053,7 +2063,7 @@ int ftrace_profile_set_filter(struct perf_event *event, int event_id,
        if (event->filter)
                goto out_unlock;
 
-       err = create_filter(call, filter_str, false, &filter);
+       err = create_filter(NULL, call, filter_str, false, &filter);
        if (err)
                goto free_filter;
 
@@ -2202,8 +2212,8 @@ static __init int ftrace_test_event_filter(void)
                struct test_filter_data_t *d = &test_filter_data[i];
                int err;
 
-               err = create_filter(&event_ftrace_test_filter, d->filter,
-                                   false, &filter);
+               err = create_filter(NULL, &event_ftrace_test_filter,
+                                   d->filter, false, &filter);
                if (err) {
                        printk(KERN_INFO
                               "Failed to get filter for '%s', err %d\n",
index a1d2042..7fca345 100644 (file)
 
 #define STR_VAR_LEN_MAX                32 /* must be multiple of sizeof(u64) */
 
+#define ERRORS                                                         \
+       C(NONE,                 "No error"),                            \
+       C(DUPLICATE_VAR,        "Variable already defined"),            \
+       C(VAR_NOT_UNIQUE,       "Variable name not unique, need to use fully qualified name (subsys.event.var) for variable"), \
+       C(TOO_MANY_VARS,        "Too many variables defined"),          \
+       C(MALFORMED_ASSIGNMENT, "Malformed assignment"),                \
+       C(NAMED_MISMATCH,       "Named hist trigger doesn't match existing named trigger (includes variables)"), \
+       C(TRIGGER_EEXIST,       "Hist trigger already exists"),         \
+       C(TRIGGER_ENOENT_CLEAR, "Can't clear or continue a nonexistent hist trigger"), \
+       C(SET_CLOCK_FAIL,       "Couldn't set trace_clock"),            \
+       C(BAD_FIELD_MODIFIER,   "Invalid field modifier"),              \
+       C(TOO_MANY_SUBEXPR,     "Too many subexpressions (3 max)"),     \
+       C(TIMESTAMP_MISMATCH,   "Timestamp units in expression don't match"), \
+       C(TOO_MANY_FIELD_VARS,  "Too many field variables defined"),    \
+       C(EVENT_FILE_NOT_FOUND, "Event file not found"),                \
+       C(HIST_NOT_FOUND,       "Matching event histogram not found"),  \
+       C(HIST_CREATE_FAIL,     "Couldn't create histogram for field"), \
+       C(SYNTH_VAR_NOT_FOUND,  "Couldn't find synthetic variable"),    \
+       C(SYNTH_EVENT_NOT_FOUND,"Couldn't find synthetic event"),       \
+       C(SYNTH_TYPE_MISMATCH,  "Param type doesn't match synthetic event field type"), \
+       C(SYNTH_COUNT_MISMATCH, "Param count doesn't match synthetic event field count"), \
+       C(FIELD_VAR_PARSE_FAIL, "Couldn't parse field variable"),       \
+       C(VAR_CREATE_FIND_FAIL, "Couldn't create or find variable"),    \
+       C(ONX_NOT_VAR,          "For onmax(x) or onchange(x), x must be a variable"), \
+       C(ONX_VAR_NOT_FOUND,    "Couldn't find onmax or onchange variable"), \
+       C(ONX_VAR_CREATE_FAIL,  "Couldn't create onmax or onchange variable"), \
+       C(FIELD_VAR_CREATE_FAIL,"Couldn't create field variable"),      \
+       C(TOO_MANY_PARAMS,      "Too many action params"),              \
+       C(PARAM_NOT_FOUND,      "Couldn't find param"),                 \
+       C(INVALID_PARAM,        "Invalid action param"),                \
+       C(ACTION_NOT_FOUND,     "No action found"),                     \
+       C(NO_SAVE_PARAMS,       "No params found for save()"),          \
+       C(TOO_MANY_SAVE_ACTIONS,"Can't have more than one save() action per hist"), \
+       C(ACTION_MISMATCH,      "Handler doesn't support action"),      \
+       C(NO_CLOSING_PAREN,     "No closing paren found"),              \
+       C(SUBSYS_NOT_FOUND,     "Missing subsystem"),                   \
+       C(INVALID_SUBSYS_EVENT, "Invalid subsystem or event name"),     \
+       C(INVALID_REF_KEY,      "Using variable references as keys not supported"), \
+       C(VAR_NOT_FOUND,        "Couldn't find variable"),              \
+       C(FIELD_NOT_FOUND,      "Couldn't find field"),
+
+#undef C
+#define C(a, b)                HIST_ERR_##a
+
+enum { ERRORS };
+
+#undef C
+#define C(a, b)                b
+
+static const char *err_text[] = { ERRORS };
+
 struct hist_field;
 
 typedef u64 (*hist_field_fn_t) (struct hist_field *field,
@@ -535,62 +586,49 @@ static struct track_data *track_data_alloc(unsigned int key_len,
        return data;
 }
 
-static char last_hist_cmd[MAX_FILTER_STR_VAL];
-static char hist_err_str[MAX_FILTER_STR_VAL];
+static char last_cmd[MAX_FILTER_STR_VAL];
+static char last_cmd_loc[MAX_FILTER_STR_VAL];
 
-static void last_cmd_set(char *str)
+static int errpos(char *str)
 {
-       if (!str)
-               return;
-
-       strncpy(last_hist_cmd, str, MAX_FILTER_STR_VAL - 1);
+       return err_pos(last_cmd, str);
 }
 
-static void hist_err(char *str, char *var)
+static void last_cmd_set(struct trace_event_file *file, char *str)
 {
-       int maxlen = MAX_FILTER_STR_VAL - 1;
+       const char *system = NULL, *name = NULL;
+       struct trace_event_call *call;
 
        if (!str)
                return;
 
-       if (strlen(hist_err_str))
-               return;
+       strncpy(last_cmd, str, MAX_FILTER_STR_VAL - 1);
 
-       if (!var)
-               var = "";
+       if (file) {
+               call = file->event_call;
 
-       if (strlen(hist_err_str) + strlen(str) + strlen(var) > maxlen)
-               return;
+               system = call->class->system;
+               if (system) {
+                       name = trace_event_name(call);
+                       if (!name)
+                               system = NULL;
+               }
+       }
 
-       strcat(hist_err_str, str);
-       strcat(hist_err_str, var);
+       if (system)
+               snprintf(last_cmd_loc, MAX_FILTER_STR_VAL, "hist:%s:%s", system, name);
 }
 
-static void hist_err_event(char *str, char *system, char *event, char *var)
+static void hist_err(struct trace_array *tr, u8 err_type, u8 err_pos)
 {
-       char err[MAX_FILTER_STR_VAL];
-
-       if (system && var)
-               snprintf(err, MAX_FILTER_STR_VAL, "%s.%s.%s", system, event, var);
-       else if (system)
-               snprintf(err, MAX_FILTER_STR_VAL, "%s.%s", system, event);
-       else
-               strscpy(err, var, MAX_FILTER_STR_VAL);
-
-       hist_err(str, err);
+       tracing_log_err(tr, last_cmd_loc, last_cmd, err_text,
+                       err_type, err_pos);
 }
 
 static void hist_err_clear(void)
 {
-       hist_err_str[0] = '\0';
-}
-
-static bool have_hist_err(void)
-{
-       if (strlen(hist_err_str))
-               return true;
-
-       return false;
+       last_cmd[0] = '\0';
+       last_cmd_loc[0] = '\0';
 }
 
 struct synth_trace_event {
@@ -1719,7 +1757,7 @@ static struct trace_event_file *find_var_file(struct trace_array *tr,
 
                if (find_var_field(var_hist_data, var_name)) {
                        if (found) {
-                               hist_err_event("Variable name not unique, need to use fully qualified name (subsys.event.var) for variable: ", system, event_name, var_name);
+                               hist_err(tr, HIST_ERR_VAR_NOT_UNIQUE, errpos(var_name));
                                return NULL;
                        }
 
@@ -1770,7 +1808,8 @@ find_match_var(struct hist_trigger_data *hist_data, char *var_name)
                        hist_field = find_file_var(file, var_name);
                        if (hist_field) {
                                if (found) {
-                                       hist_err_event("Variable name not unique, need to use fully qualified name (subsys.event.var) for variable: ", system, event_name, var_name);
+                                       hist_err(tr, HIST_ERR_VAR_NOT_UNIQUE,
+                                                errpos(var_name));
                                        return ERR_PTR(-EINVAL);
                                }
 
@@ -2002,11 +2041,11 @@ static int parse_action(char *str, struct hist_trigger_attrs *attrs)
                attrs->n_actions++;
                ret = 0;
        }
-
        return ret;
 }
 
-static int parse_assignment(char *str, struct hist_trigger_attrs *attrs)
+static int parse_assignment(struct trace_array *tr,
+                           char *str, struct hist_trigger_attrs *attrs)
 {
        int ret = 0;
 
@@ -2062,7 +2101,7 @@ static int parse_assignment(char *str, struct hist_trigger_attrs *attrs)
                char *assignment;
 
                if (attrs->n_assignments == TRACING_MAP_VARS_MAX) {
-                       hist_err("Too many variables defined: ", str);
+                       hist_err(tr, HIST_ERR_TOO_MANY_VARS, errpos(str));
                        ret = -EINVAL;
                        goto out;
                }
@@ -2079,7 +2118,8 @@ static int parse_assignment(char *str, struct hist_trigger_attrs *attrs)
        return ret;
 }
 
-static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str)
+static struct hist_trigger_attrs *
+parse_hist_trigger_attrs(struct trace_array *tr, char *trigger_str)
 {
        struct hist_trigger_attrs *attrs;
        int ret = 0;
@@ -2092,7 +2132,7 @@ static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str)
                char *str = strsep(&trigger_str, ":");
 
                if (strchr(str, '=')) {
-                       ret = parse_assignment(str, attrs);
+                       ret = parse_assignment(tr, str, attrs);
                        if (ret)
                                goto free;
                } else if (strcmp(str, "pause") == 0)
@@ -2648,6 +2688,7 @@ static struct hist_field *parse_var_ref(struct hist_trigger_data *hist_data,
                                        char *var_name)
 {
        struct hist_field *var_field = NULL, *ref_field = NULL;
+       struct trace_array *tr = hist_data->event_file->tr;
 
        if (!is_var_ref(var_name))
                return NULL;
@@ -2660,8 +2701,7 @@ static struct hist_field *parse_var_ref(struct hist_trigger_data *hist_data,
                                           system, event_name);
 
        if (!ref_field)
-               hist_err_event("Couldn't find variable: $",
-                              system, event_name, var_name);
+               hist_err(tr, HIST_ERR_VAR_NOT_FOUND, errpos(var_name));
 
        return ref_field;
 }
@@ -2672,6 +2712,7 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
 {
        struct ftrace_event_field *field = NULL;
        char *field_name, *modifier, *str;
+       struct trace_array *tr = file->tr;
 
        modifier = str = kstrdup(field_str, GFP_KERNEL);
        if (!modifier)
@@ -2695,7 +2736,7 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
                else if (strcmp(modifier, "usecs") == 0)
                        *flags |= HIST_FIELD_FL_TIMESTAMP_USECS;
                else {
-                       hist_err("Invalid field modifier: ", modifier);
+                       hist_err(tr, HIST_ERR_BAD_FIELD_MODIFIER, errpos(modifier));
                        field = ERR_PTR(-EINVAL);
                        goto out;
                }
@@ -2711,7 +2752,7 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
        else {
                field = trace_find_event_field(file->event_call, field_name);
                if (!field || !field->size) {
-                       hist_err("Couldn't find field: ", field_name);
+                       hist_err(tr, HIST_ERR_FIELD_NOT_FOUND, errpos(field_name));
                        field = ERR_PTR(-EINVAL);
                        goto out;
                }
@@ -2773,7 +2814,8 @@ static struct hist_field *parse_atom(struct hist_trigger_data *hist_data,
 
        s = local_field_var_ref(hist_data, ref_system, ref_event, ref_var);
        if (!s) {
-               hist_field = parse_var_ref(hist_data, ref_system, ref_event, ref_var);
+               hist_field = parse_var_ref(hist_data, ref_system,
+                                          ref_event, ref_var);
                if (hist_field) {
                        if (var_name) {
                                hist_field = create_alias(hist_data, hist_field, var_name);
@@ -2822,7 +2864,7 @@ static struct hist_field *parse_unary(struct hist_trigger_data *hist_data,
        /* we support only -(xxx) i.e. explicit parens required */
 
        if (level > 3) {
-               hist_err("Too many subexpressions (3 max): ", str);
+               hist_err(file->tr, HIST_ERR_TOO_MANY_SUBEXPR, errpos(str));
                ret = -EINVAL;
                goto free;
        }
@@ -2877,7 +2919,8 @@ static struct hist_field *parse_unary(struct hist_trigger_data *hist_data,
        return ERR_PTR(ret);
 }
 
-static int check_expr_operands(struct hist_field *operand1,
+static int check_expr_operands(struct trace_array *tr,
+                              struct hist_field *operand1,
                               struct hist_field *operand2)
 {
        unsigned long operand1_flags = operand1->flags;
@@ -2905,7 +2948,7 @@ static int check_expr_operands(struct hist_field *operand1,
 
        if ((operand1_flags & HIST_FIELD_FL_TIMESTAMP_USECS) !=
            (operand2_flags & HIST_FIELD_FL_TIMESTAMP_USECS)) {
-               hist_err("Timestamp units in expression don't match", NULL);
+               hist_err(tr, HIST_ERR_TIMESTAMP_MISMATCH, 0);
                return -EINVAL;
        }
 
@@ -2923,7 +2966,7 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data,
        char *sep, *operand1_str;
 
        if (level > 3) {
-               hist_err("Too many subexpressions (3 max): ", str);
+               hist_err(file->tr, HIST_ERR_TOO_MANY_SUBEXPR, errpos(str));
                return ERR_PTR(-EINVAL);
        }
 
@@ -2968,7 +3011,7 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data,
                goto free;
        }
 
-       ret = check_expr_operands(operand1, operand2);
+       ret = check_expr_operands(file->tr, operand1, operand2);
        if (ret)
                goto free;
 
@@ -3161,16 +3204,14 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,
        int ret;
 
        if (target_hist_data->n_field_var_hists >= SYNTH_FIELDS_MAX) {
-               hist_err_event("trace action: Too many field variables defined: ",
-                              subsys_name, event_name, field_name);
+               hist_err(tr, HIST_ERR_TOO_MANY_FIELD_VARS, errpos(field_name));
                return ERR_PTR(-EINVAL);
        }
 
        file = event_file(tr, subsys_name, event_name);
 
        if (IS_ERR(file)) {
-               hist_err_event("trace action: Event file not found: ",
-                              subsys_name, event_name, field_name);
+               hist_err(tr, HIST_ERR_EVENT_FILE_NOT_FOUND, errpos(field_name));
                ret = PTR_ERR(file);
                return ERR_PTR(ret);
        }
@@ -3183,8 +3224,7 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,
         */
        hist_data = find_compatible_hist(target_hist_data, file);
        if (!hist_data) {
-               hist_err_event("trace action: Matching event histogram not found: ",
-                              subsys_name, event_name, field_name);
+               hist_err(tr, HIST_ERR_HIST_NOT_FOUND, errpos(field_name));
                return ERR_PTR(-EINVAL);
        }
 
@@ -3245,8 +3285,7 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,
                kfree(cmd);
                kfree(var_hist->cmd);
                kfree(var_hist);
-               hist_err_event("trace action: Couldn't create histogram for field: ",
-                              subsys_name, event_name, field_name);
+               hist_err(tr, HIST_ERR_HIST_CREATE_FAIL, errpos(field_name));
                return ERR_PTR(ret);
        }
 
@@ -3258,8 +3297,7 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,
        if (IS_ERR_OR_NULL(event_var)) {
                kfree(var_hist->cmd);
                kfree(var_hist);
-               hist_err_event("trace action: Couldn't find synthetic variable: ",
-                              subsys_name, event_name, field_name);
+               hist_err(tr, HIST_ERR_SYNTH_VAR_NOT_FOUND, errpos(field_name));
                return ERR_PTR(-EINVAL);
        }
 
@@ -3392,25 +3430,26 @@ static struct field_var *create_field_var(struct hist_trigger_data *hist_data,
 {
        struct hist_field *val = NULL, *var = NULL;
        unsigned long flags = HIST_FIELD_FL_VAR;
+       struct trace_array *tr = file->tr;
        struct field_var *field_var;
        int ret = 0;
 
        if (hist_data->n_field_vars >= SYNTH_FIELDS_MAX) {
-               hist_err("Too many field variables defined: ", field_name);
+               hist_err(tr, HIST_ERR_TOO_MANY_FIELD_VARS, errpos(field_name));
                ret = -EINVAL;
                goto err;
        }
 
        val = parse_atom(hist_data, file, field_name, &flags, NULL);
        if (IS_ERR(val)) {
-               hist_err("Couldn't parse field variable: ", field_name);
+               hist_err(tr, HIST_ERR_FIELD_VAR_PARSE_FAIL, errpos(field_name));
                ret = PTR_ERR(val);
                goto err;
        }
 
        var = create_var(hist_data, file, field_name, val->size, val->type);
        if (IS_ERR(var)) {
-               hist_err("Couldn't create or find variable: ", field_name);
+               hist_err(tr, HIST_ERR_VAR_CREATE_FIND_FAIL, errpos(field_name));
                kfree(val);
                ret = PTR_ERR(var);
                goto err;
@@ -3737,19 +3776,20 @@ static int track_data_create(struct hist_trigger_data *hist_data,
 {
        struct hist_field *var_field, *ref_field, *track_var = NULL;
        struct trace_event_file *file = hist_data->event_file;
+       struct trace_array *tr = file->tr;
        char *track_data_var_str;
        int ret = 0;
 
        track_data_var_str = data->track_data.var_str;
        if (track_data_var_str[0] != '$') {
-               hist_err("For onmax(x) or onchange(x), x must be a variable: ", track_data_var_str);
+               hist_err(tr, HIST_ERR_ONX_NOT_VAR, errpos(track_data_var_str));
                return -EINVAL;
        }
        track_data_var_str++;
 
        var_field = find_target_event_var(hist_data, NULL, NULL, track_data_var_str);
        if (!var_field) {
-               hist_err("Couldn't find onmax or onchange variable: ", track_data_var_str);
+               hist_err(tr, HIST_ERR_ONX_VAR_NOT_FOUND, errpos(track_data_var_str));
                return -EINVAL;
        }
 
@@ -3762,7 +3802,7 @@ static int track_data_create(struct hist_trigger_data *hist_data,
        if (data->handler == HANDLER_ONMAX)
                track_var = create_var(hist_data, file, "__max", sizeof(u64), "u64");
        if (IS_ERR(track_var)) {
-               hist_err("Couldn't create onmax variable: ", "__max");
+               hist_err(tr, HIST_ERR_ONX_VAR_CREATE_FAIL, 0);
                ret = PTR_ERR(track_var);
                goto out;
        }
@@ -3770,7 +3810,7 @@ static int track_data_create(struct hist_trigger_data *hist_data,
        if (data->handler == HANDLER_ONCHANGE)
                track_var = create_var(hist_data, file, "__change", sizeof(u64), "u64");
        if (IS_ERR(track_var)) {
-               hist_err("Couldn't create onchange variable: ", "__change");
+               hist_err(tr, HIST_ERR_ONX_VAR_CREATE_FAIL, 0);
                ret = PTR_ERR(track_var);
                goto out;
        }
@@ -3781,7 +3821,8 @@ static int track_data_create(struct hist_trigger_data *hist_data,
        return ret;
 }
 
-static int parse_action_params(char *params, struct action_data *data)
+static int parse_action_params(struct trace_array *tr, char *params,
+                              struct action_data *data)
 {
        char *param, *saved_param;
        bool first_param = true;
@@ -3789,20 +3830,20 @@ static int parse_action_params(char *params, struct action_data *data)
 
        while (params) {
                if (data->n_params >= SYNTH_FIELDS_MAX) {
-                       hist_err("Too many action params", "");
+                       hist_err(tr, HIST_ERR_TOO_MANY_PARAMS, 0);
                        goto out;
                }
 
                param = strsep(&params, ",");
                if (!param) {
-                       hist_err("No action param found", "");
+                       hist_err(tr, HIST_ERR_PARAM_NOT_FOUND, 0);
                        ret = -EINVAL;
                        goto out;
                }
 
                param = strstrip(param);
                if (strlen(param) < 2) {
-                       hist_err("Invalid action param: ", param);
+                       hist_err(tr, HIST_ERR_INVALID_PARAM, errpos(param));
                        ret = -EINVAL;
                        goto out;
                }
@@ -3826,7 +3867,7 @@ static int parse_action_params(char *params, struct action_data *data)
        return ret;
 }
 
-static int action_parse(char *str, struct action_data *data,
+static int action_parse(struct trace_array *tr, char *str, struct action_data *data,
                        enum handler_id handler)
 {
        char *action_name;
@@ -3834,14 +3875,14 @@ static int action_parse(char *str, struct action_data *data,
 
        strsep(&str, ".");
        if (!str) {
-               hist_err("action parsing: No action found", "");
+               hist_err(tr, HIST_ERR_ACTION_NOT_FOUND, 0);
                ret = -EINVAL;
                goto out;
        }
 
        action_name = strsep(&str, "(");
        if (!action_name || !str) {
-               hist_err("action parsing: No action found", "");
+               hist_err(tr, HIST_ERR_ACTION_NOT_FOUND, 0);
                ret = -EINVAL;
                goto out;
        }
@@ -3850,12 +3891,12 @@ static int action_parse(char *str, struct action_data *data,
                char *params = strsep(&str, ")");
 
                if (!params) {
-                       hist_err("action parsing: No params found for %s", "save");
+                       hist_err(tr, HIST_ERR_NO_SAVE_PARAMS, 0);
                        ret = -EINVAL;
                        goto out;
                }
 
-               ret = parse_action_params(params, data);
+               ret = parse_action_params(tr, params, data);
                if (ret)
                        goto out;
 
@@ -3864,7 +3905,7 @@ static int action_parse(char *str, struct action_data *data,
                else if (handler == HANDLER_ONCHANGE)
                        data->track_data.check_val = check_track_val_changed;
                else {
-                       hist_err("action parsing: Handler doesn't support action: ", action_name);
+                       hist_err(tr, HIST_ERR_ACTION_MISMATCH, errpos(action_name));
                        ret = -EINVAL;
                        goto out;
                }
@@ -3876,7 +3917,7 @@ static int action_parse(char *str, struct action_data *data,
                char *params = strsep(&str, ")");
 
                if (!str) {
-                       hist_err("action parsing: No closing paren found: %s", params);
+                       hist_err(tr, HIST_ERR_NO_CLOSING_PAREN, errpos(params));
                        ret = -EINVAL;
                        goto out;
                }
@@ -3886,7 +3927,7 @@ static int action_parse(char *str, struct action_data *data,
                else if (handler == HANDLER_ONCHANGE)
                        data->track_data.check_val = check_track_val_changed;
                else {
-                       hist_err("action parsing: Handler doesn't support action: ", action_name);
+                       hist_err(tr, HIST_ERR_ACTION_MISMATCH, errpos(action_name));
                        ret = -EINVAL;
                        goto out;
                }
@@ -3901,7 +3942,7 @@ static int action_parse(char *str, struct action_data *data,
                        data->use_trace_keyword = true;
 
                if (params) {
-                       ret = parse_action_params(params, data);
+                       ret = parse_action_params(tr, params, data);
                        if (ret)
                                goto out;
                }
@@ -3954,7 +3995,7 @@ static struct action_data *track_data_parse(struct hist_trigger_data *hist_data,
                goto free;
        }
 
-       ret = action_parse(str, data, handler);
+       ret = action_parse(hist_data->event_file->tr, str, data, handler);
        if (ret)
                goto free;
  out:
@@ -4024,6 +4065,7 @@ trace_action_find_var(struct hist_trigger_data *hist_data,
                      struct action_data *data,
                      char *system, char *event, char *var)
 {
+       struct trace_array *tr = hist_data->event_file->tr;
        struct hist_field *hist_field;
 
        var++; /* skip '$' */
@@ -4039,7 +4081,7 @@ trace_action_find_var(struct hist_trigger_data *hist_data,
        }
 
        if (!hist_field)
-               hist_err_event("trace action: Couldn't find param: $", system, event, var);
+               hist_err(tr, HIST_ERR_PARAM_NOT_FOUND, errpos(var));
 
        return hist_field;
 }
@@ -4097,6 +4139,7 @@ trace_action_create_field_var(struct hist_trigger_data *hist_data,
 static int trace_action_create(struct hist_trigger_data *hist_data,
                               struct action_data *data)
 {
+       struct trace_array *tr = hist_data->event_file->tr;
        char *event_name, *param, *system = NULL;
        struct hist_field *hist_field, *var_ref;
        unsigned int i, var_ref_idx;
@@ -4114,7 +4157,7 @@ static int trace_action_create(struct hist_trigger_data *hist_data,
 
        event = find_synth_event(synth_event_name);
        if (!event) {
-               hist_err("trace action: Couldn't find synthetic event: ", synth_event_name);
+               hist_err(tr, HIST_ERR_SYNTH_EVENT_NOT_FOUND, errpos(synth_event_name));
                return -EINVAL;
        }
 
@@ -4175,15 +4218,14 @@ static int trace_action_create(struct hist_trigger_data *hist_data,
                        continue;
                }
 
-               hist_err_event("trace action: Param type doesn't match synthetic event field type: ",
-                              system, event_name, param);
+               hist_err(tr, HIST_ERR_SYNTH_TYPE_MISMATCH, errpos(param));
                kfree(p);
                ret = -EINVAL;
                goto err;
        }
 
        if (field_pos != event->n_fields) {
-               hist_err("trace action: Param count doesn't match synthetic event field count: ", event->name);
+               hist_err(tr, HIST_ERR_SYNTH_COUNT_MISMATCH, errpos(event->name));
                ret = -EINVAL;
                goto err;
        }
@@ -4202,6 +4244,7 @@ static int action_create(struct hist_trigger_data *hist_data,
                         struct action_data *data)
 {
        struct trace_event_file *file = hist_data->event_file;
+       struct trace_array *tr = file->tr;
        struct track_data *track_data;
        struct field_var *field_var;
        unsigned int i;
@@ -4229,7 +4272,7 @@ static int action_create(struct hist_trigger_data *hist_data,
        if (data->action == ACTION_SAVE) {
                if (hist_data->n_save_vars) {
                        ret = -EEXIST;
-                       hist_err("save action: Can't have more than one save() action per hist", "");
+                       hist_err(tr, HIST_ERR_TOO_MANY_SAVE_ACTIONS, 0);
                        goto out;
                }
 
@@ -4242,7 +4285,8 @@ static int action_create(struct hist_trigger_data *hist_data,
 
                        field_var = create_target_field_var(hist_data, NULL, NULL, param);
                        if (IS_ERR(field_var)) {
-                               hist_err("save action: Couldn't create field variable: ", param);
+                               hist_err(tr, HIST_ERR_FIELD_VAR_CREATE_FAIL,
+                                        errpos(param));
                                ret = PTR_ERR(field_var);
                                kfree(param);
                                goto out;
@@ -4276,19 +4320,18 @@ static struct action_data *onmatch_parse(struct trace_array *tr, char *str)
 
        match_event = strsep(&str, ")");
        if (!match_event || !str) {
-               hist_err("onmatch: Missing closing paren: ", match_event);
+               hist_err(tr, HIST_ERR_NO_CLOSING_PAREN, errpos(match_event));
                goto free;
        }
 
        match_event_system = strsep(&match_event, ".");
        if (!match_event) {
-               hist_err("onmatch: Missing subsystem for match event: ", match_event_system);
+               hist_err(tr, HIST_ERR_SUBSYS_NOT_FOUND, errpos(match_event_system));
                goto free;
        }
 
        if (IS_ERR(event_file(tr, match_event_system, match_event))) {
-               hist_err_event("onmatch: Invalid subsystem or event name: ",
-                              match_event_system, match_event, NULL);
+               hist_err(tr, HIST_ERR_INVALID_SUBSYS_EVENT, errpos(match_event));
                goto free;
        }
 
@@ -4304,7 +4347,7 @@ static struct action_data *onmatch_parse(struct trace_array *tr, char *str)
                goto free;
        }
 
-       ret = action_parse(str, data, HANDLER_ONMATCH);
+       ret = action_parse(tr, str, data, HANDLER_ONMATCH);
        if (ret)
                goto free;
  out:
@@ -4373,13 +4416,14 @@ static int create_var_field(struct hist_trigger_data *hist_data,
                            struct trace_event_file *file,
                            char *var_name, char *expr_str)
 {
+       struct trace_array *tr = hist_data->event_file->tr;
        unsigned long flags = 0;
 
        if (WARN_ON(val_idx >= TRACING_MAP_VALS_MAX + TRACING_MAP_VARS_MAX))
                return -EINVAL;
 
        if (find_var(hist_data, file, var_name) && !hist_data->remove) {
-               hist_err("Variable already defined: ", var_name);
+               hist_err(tr, HIST_ERR_DUPLICATE_VAR, errpos(var_name));
                return -EINVAL;
        }
 
@@ -4436,8 +4480,8 @@ static int create_key_field(struct hist_trigger_data *hist_data,
                            struct trace_event_file *file,
                            char *field_str)
 {
+       struct trace_array *tr = hist_data->event_file->tr;
        struct hist_field *hist_field = NULL;
-
        unsigned long flags = 0;
        unsigned int key_size;
        int ret = 0;
@@ -4460,7 +4504,7 @@ static int create_key_field(struct hist_trigger_data *hist_data,
                }
 
                if (hist_field->flags & HIST_FIELD_FL_VAR_REF) {
-                       hist_err("Using variable references as keys not supported: ", field_str);
+                       hist_err(tr, HIST_ERR_INVALID_REF_KEY, errpos(field_str));
                        destroy_hist_field(hist_field, 0);
                        ret = -EINVAL;
                        goto out;
@@ -4561,6 +4605,7 @@ static void free_var_defs(struct hist_trigger_data *hist_data)
 
 static int parse_var_defs(struct hist_trigger_data *hist_data)
 {
+       struct trace_array *tr = hist_data->event_file->tr;
        char *s, *str, *var_name, *field_str;
        unsigned int i, j, n_vars = 0;
        int ret = 0;
@@ -4574,13 +4619,14 @@ static int parse_var_defs(struct hist_trigger_data *hist_data)
 
                        var_name = strsep(&field_str, "=");
                        if (!var_name || !field_str) {
-                               hist_err("Malformed assignment: ", var_name);
+                               hist_err(tr, HIST_ERR_MALFORMED_ASSIGNMENT,
+                                        errpos(var_name));
                                ret = -EINVAL;
                                goto free;
                        }
 
                        if (n_vars == TRACING_MAP_VARS_MAX) {
-                               hist_err("Too many variables defined: ", var_name);
+                               hist_err(tr, HIST_ERR_TOO_MANY_VARS, errpos(var_name));
                                ret = -EINVAL;
                                goto free;
                        }
@@ -5431,11 +5477,6 @@ static int hist_show(struct seq_file *m, void *v)
                        hist_trigger_show(m, data, n++);
        }
 
-       if (have_hist_err()) {
-               seq_printf(m, "\nERROR: %s\n", hist_err_str);
-               seq_printf(m, "  Last command: %s\n", last_hist_cmd);
-       }
-
  out_unlock:
        mutex_unlock(&event_mutex);
 
@@ -5800,6 +5841,7 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops,
 {
        struct hist_trigger_data *hist_data = data->private_data;
        struct event_trigger_data *test, *named_data = NULL;
+       struct trace_array *tr = file->tr;
        int ret = 0;
 
        if (hist_data->attrs->name) {
@@ -5807,7 +5849,7 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops,
                if (named_data) {
                        if (!hist_trigger_match(data, named_data, named_data,
                                                true)) {
-                               hist_err("Named hist trigger doesn't match existing named trigger (includes variables): ", hist_data->attrs->name);
+                               hist_err(tr, HIST_ERR_NAMED_MISMATCH, errpos(hist_data->attrs->name));
                                ret = -EINVAL;
                                goto out;
                        }
@@ -5828,7 +5870,7 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops,
                        else if (hist_data->attrs->clear)
                                hist_clear(test);
                        else {
-                               hist_err("Hist trigger already exists", NULL);
+                               hist_err(tr, HIST_ERR_TRIGGER_EEXIST, 0);
                                ret = -EEXIST;
                        }
                        goto out;
@@ -5836,7 +5878,7 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops,
        }
  new:
        if (hist_data->attrs->cont || hist_data->attrs->clear) {
-               hist_err("Can't clear or continue a nonexistent hist trigger", NULL);
+               hist_err(tr, HIST_ERR_TRIGGER_ENOENT_CLEAR, 0);
                ret = -ENOENT;
                goto out;
        }
@@ -5861,7 +5903,7 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops,
 
                ret = tracing_set_clock(file->tr, hist_data->attrs->clock);
                if (ret) {
-                       hist_err("Couldn't set trace_clock: ", clock);
+                       hist_err(tr, HIST_ERR_SET_CLOCK_FAIL, errpos(clock));
                        goto out;
                }
 
@@ -6037,8 +6079,8 @@ static int event_hist_trigger_func(struct event_command *cmd_ops,
        lockdep_assert_held(&event_mutex);
 
        if (glob && strlen(glob)) {
-               last_cmd_set(param);
                hist_err_clear();
+               last_cmd_set(file, param);
        }
 
        if (!param)
@@ -6079,7 +6121,7 @@ static int event_hist_trigger_func(struct event_command *cmd_ops,
                trigger = strstrip(trigger);
        }
 
-       attrs = parse_hist_trigger_attrs(trigger);
+       attrs = parse_hist_trigger_attrs(file->tr, trigger);
        if (IS_ERR(attrs))
                return PTR_ERR(attrs);
 
index cd12ecb..2a2912c 100644 (file)
@@ -731,7 +731,8 @@ int set_trigger_filter(char *filter_str,
                goto out;
 
        /* The filter is for the 'trigger' event, not the triggered event */
-       ret = create_event_filter(file->event_call, filter_str, false, &filter);
+       ret = create_event_filter(file->tr, file->event_call,
+                                 filter_str, false, &filter);
        /*
         * If create_event_filter() fails, filter still needs to be freed.
         * Which the calling code will do with data->filter.
index 810d78a..6c1ae6b 100644 (file)
 #include "trace.h"
 #include "trace_output.h"
 
-static void ftrace_dump_buf(int skip_lines, long cpu_file)
+static struct trace_iterator iter;
+static struct ring_buffer_iter *buffer_iter[CONFIG_NR_CPUS];
+
+static void ftrace_dump_buf(int skip_entries, long cpu_file)
 {
-       /* use static because iter can be a bit big for the stack */
-       static struct trace_iterator iter;
-       static struct ring_buffer_iter *buffer_iter[CONFIG_NR_CPUS];
        struct trace_array *tr;
        unsigned int old_userobj;
        int cnt = 0, cpu;
 
-       trace_init_global_iter(&iter);
-       iter.buffer_iter = buffer_iter;
        tr = iter.tr;
 
-       for_each_tracing_cpu(cpu) {
-               atomic_inc(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);
-       }
-
        old_userobj = tr->trace_flags;
 
        /* don't look at user memory in panic mode */
        tr->trace_flags &= ~TRACE_ITER_SYM_USEROBJ;
 
        kdb_printf("Dumping ftrace buffer:\n");
+       if (skip_entries)
+               kdb_printf("(skipping %d entries)\n", skip_entries);
 
        /* reset all but tr, trace, and overruns */
        memset(&iter.seq, 0,
@@ -70,11 +66,11 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file)
                        kdb_printf("---------------------------------\n");
                cnt++;
 
-               if (!skip_lines) {
+               if (!skip_entries) {
                        print_trace_line(&iter);
                        trace_printk_seq(&iter.seq);
                } else {
-                       skip_lines--;
+                       skip_entries--;
                }
 
                if (KDB_FLAG(CMD_INTERRUPT))
@@ -89,10 +85,6 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file)
 out:
        tr->trace_flags = old_userobj;
 
-       for_each_tracing_cpu(cpu) {
-               atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);
-       }
-
        for_each_tracing_cpu(cpu) {
                if (iter.buffer_iter[cpu]) {
                        ring_buffer_read_finish(iter.buffer_iter[cpu]);
@@ -106,17 +98,19 @@ out:
  */
 static int kdb_ftdump(int argc, const char **argv)
 {
-       int skip_lines = 0;
+       int skip_entries = 0;
        long cpu_file;
        char *cp;
+       int cnt;
+       int cpu;
 
        if (argc > 2)
                return KDB_ARGCOUNT;
 
        if (argc) {
-               skip_lines = simple_strtol(argv[1], &cp, 0);
+               skip_entries = simple_strtol(argv[1], &cp, 0);
                if (*cp)
-                       skip_lines = 0;
+                       skip_entries = 0;
        }
 
        if (argc == 2) {
@@ -129,7 +123,29 @@ static int kdb_ftdump(int argc, const char **argv)
        }
 
        kdb_trap_printk++;
-       ftrace_dump_buf(skip_lines, cpu_file);
+
+       trace_init_global_iter(&iter);
+       iter.buffer_iter = buffer_iter;
+
+       for_each_tracing_cpu(cpu) {
+               atomic_inc(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);
+       }
+
+       /* A negative skip_entries means skip all but the last entries */
+       if (skip_entries < 0) {
+               if (cpu_file == RING_BUFFER_ALL_CPUS)
+                       cnt = trace_total_entries(NULL);
+               else
+                       cnt = trace_total_entries_cpu(NULL, cpu_file);
+               skip_entries = max(cnt + skip_entries, 0);
+       }
+
+       ftrace_dump_buf(skip_entries, cpu_file);
+
+       for_each_tracing_cpu(cpu) {
+               atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);
+       }
+
        kdb_trap_printk--;
 
        return 0;
@@ -137,8 +153,9 @@ static int kdb_ftdump(int argc, const char **argv)
 
 static __init int kdb_ftrace_register(void)
 {
-       kdb_register_flags("ftdump", kdb_ftdump, "[skip_#lines] [cpu]",
-                           "Dump ftrace log", 0, KDB_ENABLE_ALWAYS_SAFE);
+       kdb_register_flags("ftdump", kdb_ftdump, "[skip_#entries] [cpu]",
+                           "Dump ftrace log; -skip dumps last #entries", 0,
+                           KDB_ENABLE_ALWAYS_SAFE);
        return 0;
 }
 
index 5d5129b..7d73624 100644 (file)
@@ -441,13 +441,8 @@ static int __register_trace_kprobe(struct trace_kprobe *tk)
        else
                ret = register_kprobe(&tk->rp.kp);
 
-       if (ret == 0) {
+       if (ret == 0)
                tk->tp.flags |= TP_FLAG_REGISTERED;
-       } else if (ret == -EILSEQ) {
-               pr_warn("Probing address(0x%p) is not an instruction boundary.\n",
-                       tk->rp.kp.addr);
-               ret = -EINVAL;
-       }
        return ret;
 }
 
@@ -591,7 +586,7 @@ static int trace_kprobe_create(int argc, const char *argv[])
         * Type of args:
         *  FETCHARG:TYPE : use TYPE instead of unsigned long.
         */
-       struct trace_kprobe *tk;
+       struct trace_kprobe *tk = NULL;
        int i, len, ret = 0;
        bool is_return = false;
        char *symbol = NULL, *tmp = NULL;
@@ -615,44 +610,50 @@ static int trace_kprobe_create(int argc, const char *argv[])
        if (argc < 2)
                return -ECANCELED;
 
+       trace_probe_log_init("trace_kprobe", argc, argv);
+
        event = strchr(&argv[0][1], ':');
        if (event)
                event++;
 
        if (isdigit(argv[0][1])) {
                if (!is_return) {
-                       pr_info("Maxactive is not for kprobe");
-                       return -EINVAL;
+                       trace_probe_log_err(1, MAXACT_NO_KPROBE);
+                       goto parse_error;
                }
                if (event)
                        len = event - &argv[0][1] - 1;
                else
                        len = strlen(&argv[0][1]);
-               if (len > MAX_EVENT_NAME_LEN - 1)
-                       return -E2BIG;
+               if (len > MAX_EVENT_NAME_LEN - 1) {
+                       trace_probe_log_err(1, BAD_MAXACT);
+                       goto parse_error;
+               }
                memcpy(buf, &argv[0][1], len);
                buf[len] = '\0';
                ret = kstrtouint(buf, 0, &maxactive);
                if (ret || !maxactive) {
-                       pr_info("Invalid maxactive number\n");
-                       return ret;
+                       trace_probe_log_err(1, BAD_MAXACT);
+                       goto parse_error;
                }
                /* kretprobes instances are iterated over via a list. The
                 * maximum should stay reasonable.
                 */
                if (maxactive > KRETPROBE_MAXACTIVE_MAX) {
-                       pr_info("Maxactive is too big (%d > %d).\n",
-                               maxactive, KRETPROBE_MAXACTIVE_MAX);
-                       return -E2BIG;
+                       trace_probe_log_err(1, MAXACT_TOO_BIG);
+                       goto parse_error;
                }
        }
 
        /* try to parse an address. if that fails, try to read the
         * input as a symbol. */
        if (kstrtoul(argv[1], 0, (unsigned long *)&addr)) {
+               trace_probe_log_set_index(1);
                /* Check whether uprobe event specified */
-               if (strchr(argv[1], '/') && strchr(argv[1], ':'))
-                       return -ECANCELED;
+               if (strchr(argv[1], '/') && strchr(argv[1], ':')) {
+                       ret = -ECANCELED;
+                       goto error;
+               }
                /* a symbol specified */
                symbol = kstrdup(argv[1], GFP_KERNEL);
                if (!symbol)
@@ -660,23 +661,23 @@ static int trace_kprobe_create(int argc, const char *argv[])
                /* TODO: support .init module functions */
                ret = traceprobe_split_symbol_offset(symbol, &offset);
                if (ret || offset < 0 || offset > UINT_MAX) {
-                       pr_info("Failed to parse either an address or a symbol.\n");
-                       goto out;
+                       trace_probe_log_err(0, BAD_PROBE_ADDR);
+                       goto parse_error;
                }
                if (kprobe_on_func_entry(NULL, symbol, offset))
                        flags |= TPARG_FL_FENTRY;
                if (offset && is_return && !(flags & TPARG_FL_FENTRY)) {
-                       pr_info("Given offset is not valid for return probe.\n");
-                       ret = -EINVAL;
-                       goto out;
+                       trace_probe_log_err(0, BAD_RETPROBE);
+                       goto parse_error;
                }
        }
-       argc -= 2; argv += 2;
 
+       trace_probe_log_set_index(0);
        if (event) {
-               ret = traceprobe_parse_event_name(&event, &group, buf);
+               ret = traceprobe_parse_event_name(&event, &group, buf,
+                                                 event - argv[0]);
                if (ret)
-                       goto out;
+                       goto parse_error;
        } else {
                /* Make a new event name */
                if (symbol)
@@ -691,13 +692,14 @@ static int trace_kprobe_create(int argc, const char *argv[])
 
        /* setup a probe */
        tk = alloc_trace_kprobe(group, event, addr, symbol, offset, maxactive,
-                              argc, is_return);
+                              argc - 2, is_return);
        if (IS_ERR(tk)) {
                ret = PTR_ERR(tk);
-               /* This must return -ENOMEM otherwise there is a bug */
+               /* This must return -ENOMEM, else there is a bug */
                WARN_ON_ONCE(ret != -ENOMEM);
-               goto out;
+               goto out;       /* We know tk is not allocated */
        }
+       argc -= 2; argv += 2;
 
        /* parse arguments */
        for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
@@ -707,19 +709,32 @@ static int trace_kprobe_create(int argc, const char *argv[])
                        goto error;
                }
 
+               trace_probe_log_set_index(i + 2);
                ret = traceprobe_parse_probe_arg(&tk->tp, i, tmp, flags);
                kfree(tmp);
                if (ret)
-                       goto error;
+                       goto error;     /* This can be -ENOMEM */
        }
 
        ret = register_trace_kprobe(tk);
-       if (ret)
+       if (ret) {
+               trace_probe_log_set_index(1);
+               if (ret == -EILSEQ)
+                       trace_probe_log_err(0, BAD_INSN_BNDRY);
+               else if (ret == -ENOENT)
+                       trace_probe_log_err(0, BAD_PROBE_ADDR);
+               else if (ret != -ENOMEM)
+                       trace_probe_log_err(0, FAIL_REG_PROBE);
                goto error;
+       }
+
 out:
+       trace_probe_log_clear();
        kfree(symbol);
        return ret;
 
+parse_error:
+       ret = -EINVAL;
 error:
        free_trace_kprobe(tk);
        goto out;
index 8f8411e..a347fac 100644 (file)
 
 #include "trace_probe.h"
 
+#undef C
+#define C(a, b)                b
+
+static const char *trace_probe_err_text[] = { ERRORS };
+
 static const char *reserved_field_names[] = {
        "common_type",
        "common_flags",
@@ -133,6 +138,60 @@ fail:
        return NULL;
 }
 
+static struct trace_probe_log trace_probe_log;
+
+void trace_probe_log_init(const char *subsystem, int argc, const char **argv)
+{
+       trace_probe_log.subsystem = subsystem;
+       trace_probe_log.argc = argc;
+       trace_probe_log.argv = argv;
+       trace_probe_log.index = 0;
+}
+
+void trace_probe_log_clear(void)
+{
+       memset(&trace_probe_log, 0, sizeof(trace_probe_log));
+}
+
+void trace_probe_log_set_index(int index)
+{
+       trace_probe_log.index = index;
+}
+
+void __trace_probe_log_err(int offset, int err_type)
+{
+       char *command, *p;
+       int i, len = 0, pos = 0;
+
+       if (!trace_probe_log.argv)
+               return;
+
+       /* Recalcurate the length and allocate buffer */
+       for (i = 0; i < trace_probe_log.argc; i++) {
+               if (i == trace_probe_log.index)
+                       pos = len;
+               len += strlen(trace_probe_log.argv[i]) + 1;
+       }
+       command = kzalloc(len, GFP_KERNEL);
+       if (!command)
+               return;
+
+       /* And make a command string from argv array */
+       p = command;
+       for (i = 0; i < trace_probe_log.argc; i++) {
+               len = strlen(trace_probe_log.argv[i]);
+               strcpy(p, trace_probe_log.argv[i]);
+               p[len] = ' ';
+               p += len + 1;
+       }
+       *(p - 1) = '\0';
+
+       tracing_log_err(NULL, trace_probe_log.subsystem, command,
+                       trace_probe_err_text, err_type, pos + offset);
+
+       kfree(command);
+}
+
 /* Split symbol and offset. */
 int traceprobe_split_symbol_offset(char *symbol, long *offset)
 {
@@ -156,7 +215,7 @@ int traceprobe_split_symbol_offset(char *symbol, long *offset)
 
 /* @buf must has MAX_EVENT_NAME_LEN size */
 int traceprobe_parse_event_name(const char **pevent, const char **pgroup,
-                               char *buf)
+                               char *buf, int offset)
 {
        const char *slash, *event = *pevent;
        int len;
@@ -164,32 +223,33 @@ int traceprobe_parse_event_name(const char **pevent, const char **pgroup,
        slash = strchr(event, '/');
        if (slash) {
                if (slash == event) {
-                       pr_info("Group name is not specified\n");
+                       trace_probe_log_err(offset, NO_GROUP_NAME);
                        return -EINVAL;
                }
                if (slash - event + 1 > MAX_EVENT_NAME_LEN) {
-                       pr_info("Group name is too long\n");
-                       return -E2BIG;
+                       trace_probe_log_err(offset, GROUP_TOO_LONG);
+                       return -EINVAL;
                }
                strlcpy(buf, event, slash - event + 1);
                if (!is_good_name(buf)) {
-                       pr_info("Group name must follow the same rules as C identifiers\n");
+                       trace_probe_log_err(offset, BAD_GROUP_NAME);
                        return -EINVAL;
                }
                *pgroup = buf;
                *pevent = slash + 1;
+               offset += slash - event + 1;
                event = *pevent;
        }
        len = strlen(event);
        if (len == 0) {
-               pr_info("Event name is not specified\n");
+               trace_probe_log_err(offset, NO_EVENT_NAME);
                return -EINVAL;
        } else if (len > MAX_EVENT_NAME_LEN) {
-               pr_info("Event name is too long\n");
-               return -E2BIG;
+               trace_probe_log_err(offset, EVENT_TOO_LONG);
+               return -EINVAL;
        }
        if (!is_good_name(event)) {
-               pr_info("Event name must follow the same rules as C identifiers\n");
+               trace_probe_log_err(offset, BAD_EVENT_NAME);
                return -EINVAL;
        }
        return 0;
@@ -198,56 +258,67 @@ int traceprobe_parse_event_name(const char **pevent, const char **pgroup,
 #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
 
 static int parse_probe_vars(char *arg, const struct fetch_type *t,
-                           struct fetch_insn *code, unsigned int flags)
+                       struct fetch_insn *code, unsigned int flags, int offs)
 {
        unsigned long param;
        int ret = 0;
        int len;
 
        if (strcmp(arg, "retval") == 0) {
-               if (flags & TPARG_FL_RETURN)
+               if (flags & TPARG_FL_RETURN) {
                        code->op = FETCH_OP_RETVAL;
-               else
+               } else {
+                       trace_probe_log_err(offs, RETVAL_ON_PROBE);
                        ret = -EINVAL;
+               }
        } else if ((len = str_has_prefix(arg, "stack"))) {
                if (arg[len] == '\0') {
                        code->op = FETCH_OP_STACKP;
                } else if (isdigit(arg[len])) {
                        ret = kstrtoul(arg + len, 10, &param);
-                       if (ret || ((flags & TPARG_FL_KERNEL) &&
-                                   param > PARAM_MAX_STACK))
+                       if (ret) {
+                               goto inval_var;
+                       } else if ((flags & TPARG_FL_KERNEL) &&
+                                   param > PARAM_MAX_STACK) {
+                               trace_probe_log_err(offs, BAD_STACK_NUM);
                                ret = -EINVAL;
-                       else {
+                       else {
                                code->op = FETCH_OP_STACK;
                                code->param = (unsigned int)param;
                        }
                } else
-                       ret = -EINVAL;
+                       goto inval_var;
        } else if (strcmp(arg, "comm") == 0) {
                code->op = FETCH_OP_COMM;
 #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
        } else if (((flags & TPARG_FL_MASK) ==
                    (TPARG_FL_KERNEL | TPARG_FL_FENTRY)) &&
                   (len = str_has_prefix(arg, "arg"))) {
-               if (!isdigit(arg[len]))
-                       return -EINVAL;
                ret = kstrtoul(arg + len, 10, &param);
-               if (ret || !param || param > PARAM_MAX_STACK)
+               if (ret) {
+                       goto inval_var;
+               } else if (!param || param > PARAM_MAX_STACK) {
+                       trace_probe_log_err(offs, BAD_ARG_NUM);
                        return -EINVAL;
+               }
                code->op = FETCH_OP_ARG;
                code->param = (unsigned int)param - 1;
 #endif
        } else
-               ret = -EINVAL;
+               goto inval_var;
 
        return ret;
+
+inval_var:
+       trace_probe_log_err(offs, BAD_VAR);
+       return -EINVAL;
 }
 
 /* Recursive argument parser */
 static int
 parse_probe_arg(char *arg, const struct fetch_type *type,
                struct fetch_insn **pcode, struct fetch_insn *end,
-               unsigned int flags)
+               unsigned int flags, int offs)
 {
        struct fetch_insn *code = *pcode;
        unsigned long param;
@@ -257,7 +328,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
 
        switch (arg[0]) {
        case '$':
-               ret = parse_probe_vars(arg + 1, type, code, flags);
+               ret = parse_probe_vars(arg + 1, type, code, flags, offs);
                break;
 
        case '%':       /* named register */
@@ -266,47 +337,57 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
                        code->op = FETCH_OP_REG;
                        code->param = (unsigned int)ret;
                        ret = 0;
-               }
+               } else
+                       trace_probe_log_err(offs, BAD_REG_NAME);
                break;
 
        case '@':       /* memory, file-offset or symbol */
                if (isdigit(arg[1])) {
                        ret = kstrtoul(arg + 1, 0, &param);
-                       if (ret)
+                       if (ret) {
+                               trace_probe_log_err(offs, BAD_MEM_ADDR);
                                break;
+                       }
                        /* load address */
                        code->op = FETCH_OP_IMM;
                        code->immediate = param;
                } else if (arg[1] == '+') {
                        /* kprobes don't support file offsets */
-                       if (flags & TPARG_FL_KERNEL)
+                       if (flags & TPARG_FL_KERNEL) {
+                               trace_probe_log_err(offs, FILE_ON_KPROBE);
                                return -EINVAL;
-
+                       }
                        ret = kstrtol(arg + 2, 0, &offset);
-                       if (ret)
+                       if (ret) {
+                               trace_probe_log_err(offs, BAD_FILE_OFFS);
                                break;
+                       }
 
                        code->op = FETCH_OP_FOFFS;
                        code->immediate = (unsigned long)offset;  // imm64?
                } else {
                        /* uprobes don't support symbols */
-                       if (!(flags & TPARG_FL_KERNEL))
+                       if (!(flags & TPARG_FL_KERNEL)) {
+                               trace_probe_log_err(offs, SYM_ON_UPROBE);
                                return -EINVAL;
-
+                       }
                        /* Preserve symbol for updating */
                        code->op = FETCH_NOP_SYMBOL;
                        code->data = kstrdup(arg + 1, GFP_KERNEL);
                        if (!code->data)
                                return -ENOMEM;
-                       if (++code == end)
-                               return -E2BIG;
-
+                       if (++code == end) {
+                               trace_probe_log_err(offs, TOO_MANY_OPS);
+                               return -EINVAL;
+                       }
                        code->op = FETCH_OP_IMM;
                        code->immediate = 0;
                }
                /* These are fetching from memory */
-               if (++code == end)
-                       return -E2BIG;
+               if (++code == end) {
+                       trace_probe_log_err(offs, TOO_MANY_OPS);
+                       return -EINVAL;
+               }
                *pcode = code;
                code->op = FETCH_OP_DEREF;
                code->offset = offset;
@@ -317,28 +398,38 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
                /* fall through */
        case '-':
                tmp = strchr(arg, '(');
-               if (!tmp)
+               if (!tmp) {
+                       trace_probe_log_err(offs, DEREF_NEED_BRACE);
                        return -EINVAL;
-
+               }
                *tmp = '\0';
                ret = kstrtol(arg, 0, &offset);
-               if (ret)
+               if (ret) {
+                       trace_probe_log_err(offs, BAD_DEREF_OFFS);
                        break;
-
+               }
+               offs += (tmp + 1 - arg) + (arg[0] != '-' ? 1 : 0);
                arg = tmp + 1;
                tmp = strrchr(arg, ')');
-
-               if (tmp) {
+               if (!tmp) {
+                       trace_probe_log_err(offs + strlen(arg),
+                                           DEREF_OPEN_BRACE);
+                       return -EINVAL;
+               } else {
                        const struct fetch_type *t2 = find_fetch_type(NULL);
 
                        *tmp = '\0';
-                       ret = parse_probe_arg(arg, t2, &code, end, flags);
+                       ret = parse_probe_arg(arg, t2, &code, end, flags, offs);
                        if (ret)
                                break;
-                       if (code->op == FETCH_OP_COMM)
+                       if (code->op == FETCH_OP_COMM) {
+                               trace_probe_log_err(offs, COMM_CANT_DEREF);
                                return -EINVAL;
-                       if (++code == end)
-                               return -E2BIG;
+                       }
+                       if (++code == end) {
+                               trace_probe_log_err(offs, TOO_MANY_OPS);
+                               return -EINVAL;
+                       }
                        *pcode = code;
 
                        code->op = FETCH_OP_DEREF;
@@ -348,6 +439,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
        }
        if (!ret && code->op == FETCH_OP_NOP) {
                /* Parsed, but do not find fetch method */
+               trace_probe_log_err(offs, BAD_FETCH_ARG);
                ret = -EINVAL;
        }
        return ret;
@@ -379,7 +471,7 @@ static int __parse_bitfield_probe_arg(const char *bf,
                return -EINVAL;
        code++;
        if (code->op != FETCH_OP_NOP)
-               return -E2BIG;
+               return -EINVAL;
        *pcode = code;
 
        code->op = FETCH_OP_MOD_BF;
@@ -392,44 +484,66 @@ static int __parse_bitfield_probe_arg(const char *bf,
 
 /* String length checking wrapper */
 static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
-               struct probe_arg *parg, unsigned int flags)
+               struct probe_arg *parg, unsigned int flags, int offset)
 {
        struct fetch_insn *code, *scode, *tmp = NULL;
-       char *t, *t2;
+       char *t, *t2, *t3;
        int ret, len;
 
-       if (strlen(arg) > MAX_ARGSTR_LEN) {
-               pr_info("Argument is too long.: %s\n",  arg);
-               return -ENOSPC;
+       len = strlen(arg);
+       if (len > MAX_ARGSTR_LEN) {
+               trace_probe_log_err(offset, ARG_TOO_LONG);
+               return -EINVAL;
+       } else if (len == 0) {
+               trace_probe_log_err(offset, NO_ARG_BODY);
+               return -EINVAL;
        }
+
        parg->comm = kstrdup(arg, GFP_KERNEL);
-       if (!parg->comm) {
-               pr_info("Failed to allocate memory for command '%s'.\n", arg);
+       if (!parg->comm)
                return -ENOMEM;
-       }
+
        t = strchr(arg, ':');
        if (t) {
                *t = '\0';
                t2 = strchr(++t, '[');
                if (t2) {
-                       *t2 = '\0';
-                       parg->count = simple_strtoul(t2 + 1, &t2, 0);
-                       if (strcmp(t2, "]") || parg->count == 0)
+                       *t2++ = '\0';
+                       t3 = strchr(t2, ']');
+                       if (!t3) {
+                               offset += t2 + strlen(t2) - arg;
+                               trace_probe_log_err(offset,
+                                                   ARRAY_NO_CLOSE);
+                               return -EINVAL;
+                       } else if (t3[1] != '\0') {
+                               trace_probe_log_err(offset + t3 + 1 - arg,
+                                                   BAD_ARRAY_SUFFIX);
                                return -EINVAL;
-                       if (parg->count > MAX_ARRAY_LEN)
-                               return -E2BIG;
+                       }
+                       *t3 = '\0';
+                       if (kstrtouint(t2, 0, &parg->count) || !parg->count) {
+                               trace_probe_log_err(offset + t2 - arg,
+                                                   BAD_ARRAY_NUM);
+                               return -EINVAL;
+                       }
+                       if (parg->count > MAX_ARRAY_LEN) {
+                               trace_probe_log_err(offset + t2 - arg,
+                                                   ARRAY_TOO_BIG);
+                               return -EINVAL;
+                       }
                }
        }
-       /*
-        * The default type of $comm should be "string", and it can't be
-        * dereferenced.
-        */
-       if (!t && strcmp(arg, "$comm") == 0)
+
+       /* Since $comm can not be dereferred, we can find $comm by strcmp */
+       if (strcmp(arg, "$comm") == 0) {
+               /* The type of $comm must be "string", and not an array. */
+               if (parg->count || (t && strcmp(t, "string")))
+                       return -EINVAL;
                parg->type = find_fetch_type("string");
-       else
+       else
                parg->type = find_fetch_type(t);
        if (!parg->type) {
-               pr_info("Unsupported type: %s\n", t);
+               trace_probe_log_err(offset + (t ? (t - arg) : 0), BAD_TYPE);
                return -EINVAL;
        }
        parg->offset = *size;
@@ -444,13 +558,13 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
                         parg->count);
        }
 
-       code = tmp = kzalloc(sizeof(*code) * FETCH_INSN_MAX, GFP_KERNEL);
+       code = tmp = kcalloc(FETCH_INSN_MAX, sizeof(*code), GFP_KERNEL);
        if (!code)
                return -ENOMEM;
        code[FETCH_INSN_MAX - 1].op = FETCH_OP_END;
 
        ret = parse_probe_arg(arg, parg->type, &code, &code[FETCH_INSN_MAX - 1],
-                             flags);
+                             flags, offset);
        if (ret)
                goto fail;
 
@@ -458,7 +572,8 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
        if (!strcmp(parg->type->name, "string")) {
                if (code->op != FETCH_OP_DEREF && code->op != FETCH_OP_IMM &&
                    code->op != FETCH_OP_COMM) {
-                       pr_info("string only accepts memory or address.\n");
+                       trace_probe_log_err(offset + (t ? (t - arg) : 0),
+                                           BAD_STRING);
                        ret = -EINVAL;
                        goto fail;
                }
@@ -470,7 +585,8 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
                         */
                        code++;
                        if (code->op != FETCH_OP_NOP) {
-                               ret = -E2BIG;
+                               trace_probe_log_err(offset, TOO_MANY_OPS);
+                               ret = -EINVAL;
                                goto fail;
                        }
                }
@@ -483,7 +599,8 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
        } else {
                code++;
                if (code->op != FETCH_OP_NOP) {
-                       ret = -E2BIG;
+                       trace_probe_log_err(offset, TOO_MANY_OPS);
+                       ret = -EINVAL;
                        goto fail;
                }
                code->op = FETCH_OP_ST_RAW;
@@ -493,20 +610,24 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
        /* Modify operation */
        if (t != NULL) {
                ret = __parse_bitfield_probe_arg(t, parg->type, &code);
-               if (ret)
+               if (ret) {
+                       trace_probe_log_err(offset + t - arg, BAD_BITFIELD);
                        goto fail;
+               }
        }
        /* Loop(Array) operation */
        if (parg->count) {
                if (scode->op != FETCH_OP_ST_MEM &&
                    scode->op != FETCH_OP_ST_STRING) {
-                       pr_info("array only accepts memory or address\n");
+                       trace_probe_log_err(offset + (t ? (t - arg) : 0),
+                                           BAD_STRING);
                        ret = -EINVAL;
                        goto fail;
                }
                code++;
                if (code->op != FETCH_OP_NOP) {
-                       ret = -E2BIG;
+                       trace_probe_log_err(offset, TOO_MANY_OPS);
+                       ret = -EINVAL;
                        goto fail;
                }
                code->op = FETCH_OP_LP_ARRAY;
@@ -516,7 +637,7 @@ static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size,
        code->op = FETCH_OP_END;
 
        /* Shrink down the code buffer */
-       parg->code = kzalloc(sizeof(*code) * (code - tmp + 1), GFP_KERNEL);
+       parg->code = kcalloc(code - tmp + 1, sizeof(*code), GFP_KERNEL);
        if (!parg->code)
                ret = -ENOMEM;
        else
@@ -555,15 +676,19 @@ int traceprobe_parse_probe_arg(struct trace_probe *tp, int i, char *arg,
 {
        struct probe_arg *parg = &tp->args[i];
        char *body;
-       int ret;
 
        /* Increment count for freeing args in error case */
        tp->nr_args++;
 
        body = strchr(arg, '=');
        if (body) {
-               if (body - arg > MAX_ARG_NAME_LEN || body == arg)
+               if (body - arg > MAX_ARG_NAME_LEN) {
+                       trace_probe_log_err(0, ARG_NAME_TOO_LONG);
+                       return -EINVAL;
+               } else if (body == arg) {
+                       trace_probe_log_err(0, NO_ARG_NAME);
                        return -EINVAL;
+               }
                parg->name = kmemdup_nul(arg, body - arg, GFP_KERNEL);
                body++;
        } else {
@@ -575,22 +700,16 @@ int traceprobe_parse_probe_arg(struct trace_probe *tp, int i, char *arg,
                return -ENOMEM;
 
        if (!is_good_name(parg->name)) {
-               pr_info("Invalid argument[%d] name: %s\n",
-                       i, parg->name);
+               trace_probe_log_err(0, BAD_ARG_NAME);
                return -EINVAL;
        }
-
        if (traceprobe_conflict_field_name(parg->name, tp->args, i)) {
-               pr_info("Argument[%d]: '%s' conflicts with another field.\n",
-                       i, parg->name);
+               trace_probe_log_err(0, USED_ARG_NAME);
                return -EINVAL;
        }
-
        /* Parse fetch argument */
-       ret = traceprobe_parse_probe_arg_body(body, &tp->size, parg, flags);
-       if (ret)
-               pr_info("Parse error at argument[%d]. (%d)\n", i, ret);
-       return ret;
+       return traceprobe_parse_probe_arg_body(body, &tp->size, parg, flags,
+                                              body - arg);
 }
 
 void traceprobe_free_probe_arg(struct probe_arg *arg)
index 2177c20..f9a8c63 100644 (file)
@@ -124,6 +124,7 @@ struct fetch_insn {
 
 /* fetch + deref*N + store + mod + end <= 16, this allows N=12, enough */
 #define FETCH_INSN_MAX 16
+#define FETCH_TOKEN_COMM       (-ECOMM)
 
 /* Fetch type information table */
 struct fetch_type {
@@ -280,8 +281,8 @@ extern int traceprobe_update_arg(struct probe_arg *arg);
 extern void traceprobe_free_probe_arg(struct probe_arg *arg);
 
 extern int traceprobe_split_symbol_offset(char *symbol, long *offset);
-extern int traceprobe_parse_event_name(const char **pevent,
-                                      const char **pgroup, char *buf);
+int traceprobe_parse_event_name(const char **pevent, const char **pgroup,
+                               char *buf, int offset);
 
 extern int traceprobe_set_print_fmt(struct trace_probe *tp, bool is_return);
 
@@ -298,3 +299,76 @@ extern void destroy_local_trace_uprobe(struct trace_event_call *event_call);
 #endif
 extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
                                        size_t offset, struct trace_probe *tp);
+
+#undef ERRORS
+#define ERRORS \
+       C(FILE_NOT_FOUND,       "Failed to find the given file"),       \
+       C(NO_REGULAR_FILE,      "Not a regular file"),                  \
+       C(BAD_REFCNT,           "Invalid reference counter offset"),    \
+       C(REFCNT_OPEN_BRACE,    "Reference counter brace is not closed"), \
+       C(BAD_REFCNT_SUFFIX,    "Reference counter has wrong suffix"),  \
+       C(BAD_UPROBE_OFFS,      "Invalid uprobe offset"),               \
+       C(MAXACT_NO_KPROBE,     "Maxactive is not for kprobe"),         \
+       C(BAD_MAXACT,           "Invalid maxactive number"),            \
+       C(MAXACT_TOO_BIG,       "Maxactive is too big"),                \
+       C(BAD_PROBE_ADDR,       "Invalid probed address or symbol"),    \
+       C(BAD_RETPROBE,         "Retprobe address must be an function entry"), \
+       C(NO_GROUP_NAME,        "Group name is not specified"),         \
+       C(GROUP_TOO_LONG,       "Group name is too long"),              \
+       C(BAD_GROUP_NAME,       "Group name must follow the same rules as C identifiers"), \
+       C(NO_EVENT_NAME,        "Event name is not specified"),         \
+       C(EVENT_TOO_LONG,       "Event name is too long"),              \
+       C(BAD_EVENT_NAME,       "Event name must follow the same rules as C identifiers"), \
+       C(RETVAL_ON_PROBE,      "$retval is not available on probe"),   \
+       C(BAD_STACK_NUM,        "Invalid stack number"),                \
+       C(BAD_ARG_NUM,          "Invalid argument number"),             \
+       C(BAD_VAR,              "Invalid $-valiable specified"),        \
+       C(BAD_REG_NAME,         "Invalid register name"),               \
+       C(BAD_MEM_ADDR,         "Invalid memory address"),              \
+       C(FILE_ON_KPROBE,       "File offset is not available with kprobe"), \
+       C(BAD_FILE_OFFS,        "Invalid file offset value"),           \
+       C(SYM_ON_UPROBE,        "Symbol is not available with uprobe"), \
+       C(TOO_MANY_OPS,         "Dereference is too much nested"),      \
+       C(DEREF_NEED_BRACE,     "Dereference needs a brace"),           \
+       C(BAD_DEREF_OFFS,       "Invalid dereference offset"),          \
+       C(DEREF_OPEN_BRACE,     "Dereference brace is not closed"),     \
+       C(COMM_CANT_DEREF,      "$comm can not be dereferenced"),       \
+       C(BAD_FETCH_ARG,        "Invalid fetch argument"),              \
+       C(ARRAY_NO_CLOSE,       "Array is not closed"),                 \
+       C(BAD_ARRAY_SUFFIX,     "Array has wrong suffix"),              \
+       C(BAD_ARRAY_NUM,        "Invalid array size"),                  \
+       C(ARRAY_TOO_BIG,        "Array number is too big"),             \
+       C(BAD_TYPE,             "Unknown type is specified"),           \
+       C(BAD_STRING,           "String accepts only memory argument"), \
+       C(BAD_BITFIELD,         "Invalid bitfield"),                    \
+       C(ARG_NAME_TOO_LONG,    "Argument name is too long"),           \
+       C(NO_ARG_NAME,          "Argument name is not specified"),      \
+       C(BAD_ARG_NAME,         "Argument name must follow the same rules as C identifiers"), \
+       C(USED_ARG_NAME,        "This argument name is already used"),  \
+       C(ARG_TOO_LONG,         "Argument expression is too long"),     \
+       C(NO_ARG_BODY,          "No argument expression"),              \
+       C(BAD_INSN_BNDRY,       "Probe point is not an instruction boundary"),\
+       C(FAIL_REG_PROBE,       "Failed to register probe event"),
+
+#undef C
+#define C(a, b)                TP_ERR_##a
+
+/* Define TP_ERR_ */
+enum { ERRORS };
+
+/* Error text is defined in trace_probe.c */
+
+struct trace_probe_log {
+       const char      *subsystem;
+       const char      **argv;
+       int             argc;
+       int             index;
+};
+
+void trace_probe_log_init(const char *subsystem, int argc, const char **argv);
+void trace_probe_log_set_index(int index);
+void trace_probe_log_clear(void);
+void __trace_probe_log_err(int offset, int err);
+
+#define trace_probe_log_err(offs, err) \
+       __trace_probe_log_err(offs, TP_ERR_##err)
index 4737bb8..c30c61f 100644 (file)
@@ -88,7 +88,7 @@ stage3:
        /* 3rd stage: store value to buffer */
        if (unlikely(!dest)) {
                if (code->op == FETCH_OP_ST_STRING) {
-                       ret += fetch_store_strlen(val + code->offset);
+                       ret = fetch_store_strlen(val + code->offset);
                        code++;
                        goto array;
                } else
index 9d402e7..69ee8ef 100644 (file)
@@ -792,7 +792,10 @@ trace_selftest_startup_function_graph(struct tracer *trace,
        /* check the trace buffer */
        ret = trace_test_buffer(&tr->trace_buffer, &count);
 
-       trace->reset(tr);
+       /* Need to also simulate the tr->reset to remove this fgraph_ops */
+       tracing_stop_cmdline_record();
+       unregister_ftrace_graph(&fgraph_ops);
+
        tracing_start();
 
        if (!ret && !count) {
index be78d99..eb7e06b 100644 (file)
@@ -156,7 +156,10 @@ fetch_store_string(unsigned long addr, void *dest, void *base)
        if (unlikely(!maxlen))
                return -ENOMEM;
 
-       ret = strncpy_from_user(dst, src, maxlen);
+       if (addr == FETCH_TOKEN_COMM)
+               ret = strlcpy(dst, current->comm, maxlen);
+       else
+               ret = strncpy_from_user(dst, src, maxlen);
        if (ret >= 0) {
                if (ret == maxlen)
                        dst[ret - 1] = '\0';
@@ -180,7 +183,10 @@ fetch_store_strlen(unsigned long addr)
        int len;
        void __user *vaddr = (void __force __user *) addr;
 
-       len = strnlen_user(vaddr, MAX_STRING_SIZE);
+       if (addr == FETCH_TOKEN_COMM)
+               len = strlen(current->comm) + 1;
+       else
+               len = strnlen_user(vaddr, MAX_STRING_SIZE);
 
        return (len > MAX_STRING_SIZE) ? 0 : len;
 }
@@ -220,6 +226,9 @@ process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, void *dest,
        case FETCH_OP_IMM:
                val = code->immediate;
                break;
+       case FETCH_OP_COMM:
+               val = FETCH_TOKEN_COMM;
+               break;
        case FETCH_OP_FOFFS:
                val = translate_user_vaddr(code->immediate);
                break;
@@ -457,13 +466,19 @@ static int trace_uprobe_create(int argc, const char **argv)
                return -ECANCELED;
        }
 
+       trace_probe_log_init("trace_uprobe", argc, argv);
+       trace_probe_log_set_index(1);   /* filename is the 2nd argument */
+
        *arg++ = '\0';
        ret = kern_path(filename, LOOKUP_FOLLOW, &path);
        if (ret) {
+               trace_probe_log_err(0, FILE_NOT_FOUND);
                kfree(filename);
+               trace_probe_log_clear();
                return ret;
        }
        if (!d_is_reg(path.dentry)) {
+               trace_probe_log_err(0, NO_REGULAR_FILE);
                ret = -EINVAL;
                goto fail_address_parse;
        }
@@ -472,9 +487,16 @@ static int trace_uprobe_create(int argc, const char **argv)
        rctr = strchr(arg, '(');
        if (rctr) {
                rctr_end = strchr(rctr, ')');
-               if (rctr > rctr_end || *(rctr_end + 1) != 0) {
+               if (!rctr_end) {
+                       ret = -EINVAL;
+                       rctr_end = rctr + strlen(rctr);
+                       trace_probe_log_err(rctr_end - filename,
+                                           REFCNT_OPEN_BRACE);
+                       goto fail_address_parse;
+               } else if (rctr_end[1] != '\0') {
                        ret = -EINVAL;
-                       pr_info("Invalid reference counter offset.\n");
+                       trace_probe_log_err(rctr_end + 1 - filename,
+                                           BAD_REFCNT_SUFFIX);
                        goto fail_address_parse;
                }
 
@@ -482,22 +504,23 @@ static int trace_uprobe_create(int argc, const char **argv)
                *rctr_end = '\0';
                ret = kstrtoul(rctr, 0, &ref_ctr_offset);
                if (ret) {
-                       pr_info("Invalid reference counter offset.\n");
+                       trace_probe_log_err(rctr - filename, BAD_REFCNT);
                        goto fail_address_parse;
                }
        }
 
        /* Parse uprobe offset. */
        ret = kstrtoul(arg, 0, &offset);
-       if (ret)
+       if (ret) {
+               trace_probe_log_err(arg - filename, BAD_UPROBE_OFFS);
                goto fail_address_parse;
-
-       argc -= 2;
-       argv += 2;
+       }
 
        /* setup a probe */
+       trace_probe_log_set_index(0);
        if (event) {
-               ret = traceprobe_parse_event_name(&event, &group, buf);
+               ret = traceprobe_parse_event_name(&event, &group, buf,
+                                                 event - argv[0]);
                if (ret)
                        goto fail_address_parse;
        } else {
@@ -519,6 +542,9 @@ static int trace_uprobe_create(int argc, const char **argv)
                kfree(tail);
        }
 
+       argc -= 2;
+       argv += 2;
+
        tu = alloc_trace_uprobe(group, event, argc, is_return);
        if (IS_ERR(tu)) {
                ret = PTR_ERR(tu);
@@ -539,6 +565,7 @@ static int trace_uprobe_create(int argc, const char **argv)
                        goto error;
                }
 
+               trace_probe_log_set_index(i + 2);
                ret = traceprobe_parse_probe_arg(&tu->tp, i, tmp,
                                        is_return ? TPARG_FL_RETURN : 0);
                kfree(tmp);
@@ -547,20 +574,20 @@ static int trace_uprobe_create(int argc, const char **argv)
        }
 
        ret = register_trace_uprobe(tu);
-       if (ret)
-               goto error;
-       return 0;
+       if (!ret)
+               goto out;
 
 error:
        free_trace_uprobe(tu);
+out:
+       trace_probe_log_clear();
        return ret;
 
 fail_address_parse:
+       trace_probe_log_clear();
        path_put(&path);
        kfree(filename);
 
-       pr_info("Failed to parse address or file.\n");
-
        return ret;
 }
 
index 0df9b16..88b834f 100644 (file)
@@ -185,7 +185,7 @@ struct user_struct *alloc_uid(kuid_t uid)
        if (!up) {
                new = kmem_cache_zalloc(uid_cachep, GFP_KERNEL);
                if (!new)
-                       goto out_unlock;
+                       return NULL;
 
                new->uid = uid;
                refcount_set(&new->__count, 1);
@@ -199,8 +199,6 @@ struct user_struct *alloc_uid(kuid_t uid)
                spin_lock_irq(&uidhash_lock);
                up = uid_hash_find(uid, hashent);
                if (up) {
-                       key_put(new->uid_keyring);
-                       key_put(new->session_keyring);
                        kmem_cache_free(uid_cachep, new);
                } else {
                        uid_hash_insert(new, hashent);
@@ -210,9 +208,6 @@ struct user_struct *alloc_uid(kuid_t uid)
        }
 
        return up;
-
-out_unlock:
-       return NULL;
 }
 
 static int __init uid_cache_init(void)
index f323b85..8d9239a 100644 (file)
@@ -46,9 +46,6 @@ config HAVE_ARCH_BITREVERSE
          This option enables the use of hardware bit-reversal instructions on
          architectures which support such operations.
 
-config RATIONAL
-       bool
-
 config GENERIC_STRNCPY_FROM_USER
        bool
 
@@ -61,6 +58,8 @@ config GENERIC_NET_UTILS
 config GENERIC_FIND_FIRST_BIT
        bool
 
+source "lib/math/Kconfig"
+
 config NO_GENERIC_PCI_IOPORT_MAP
        bool
 
@@ -531,12 +530,6 @@ config LRU_CACHE
 config CLZ_TAB
        bool
 
-config CORDIC
-       tristate "CORDIC algorithm"
-       help
-         This option provides an implementation of the CORDIC algorithm;
-         calculations are in fixed point. Module will be called cordic.
-
 config DDR
        bool "JEDEC DDR data"
        help
@@ -608,6 +601,10 @@ config ARCH_NO_SG_CHAIN
 config ARCH_HAS_PMEM_API
        bool
 
+# use memcpy to implement user copies for nommu architectures
+config UACCESS_MEMCPY
+       bool
+
 config ARCH_HAS_UACCESS_FLUSHCACHE
        bool
 
@@ -628,9 +625,6 @@ config SBITMAP
 config PARMAN
        tristate "parman" if COMPILE_TEST
 
-config PRIME_NUMBERS
-       tristate
-
 config STRING_SELFTEST
        tristate "Test string functions"
 
index d695ec1..eae4395 100644 (file)
@@ -318,6 +318,20 @@ config HEADERS_CHECK
          exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in
          your build tree), to make sure they're suitable.
 
+config OPTIMIZE_INLINING
+       bool "Allow compiler to uninline functions marked 'inline'"
+       help
+         This option determines if the kernel forces gcc to inline the functions
+         developers have marked 'inline'. Doing so takes away freedom from gcc to
+         do what it thinks is best, which is desirable for the gcc 3.x series of
+         compilers. The gcc 4.x series have a rewritten inlining algorithm and
+         enabling this option will generate a smaller kernel there. Hopefully
+         this algorithm is so good that allowing gcc 4.x and above to make the
+         decision will become the default in the future. Until then this option
+         is there to test gcc for this.
+
+         If unsure, say N.
+
 config DEBUG_SECTION_MISMATCH
        bool "Enable full Section mismatch analysis"
        help
@@ -446,6 +460,15 @@ config DEBUG_KERNEL
          Say Y here if you are developing drivers or trying to debug and
          identify kernel problems.
 
+config DEBUG_MISC
+       bool "Miscellaneous debug code"
+       default DEBUG_KERNEL
+       depends on DEBUG_KERNEL
+       help
+         Say Y here if you need to enable miscellaneous debug code that should
+         be under a more specific debug option but isn't.
+
+
 menu "Memory Debugging"
 
 source "mm/Kconfig.debug"
@@ -519,10 +542,6 @@ config DEBUG_SLAB
          allocation as well as poisoning memory on free to catch use of freed
          memory. This can make kmalloc/kfree-intensive workloads much slower.
 
-config DEBUG_SLAB_LEAK
-       bool "Memory leak debugging"
-       depends on DEBUG_SLAB
-
 config SLUB_DEBUG_ON
        bool "SLUB debugging on by default"
        depends on SLUB && SLUB_DEBUG
@@ -1358,7 +1377,7 @@ config DEBUG_LIST
 
          If unsure, say N.
 
-config DEBUG_PI_LIST
+config DEBUG_PLIST
        bool "Debug priority linked list manipulation"
        depends on DEBUG_KERNEL
        help
index 83d7df2..fb76970 100644 (file)
@@ -30,7 +30,7 @@ endif
 
 lib-y := ctype.o string.o vsprintf.o cmdline.o \
         rbtree.o radix-tree.o timerqueue.o xarray.o \
-        idr.o int_sqrt.o extable.o \
+        idr.o extable.o \
         sha1.o chacha.o irq_regs.o argv_split.o \
         flex_proportions.o ratelimit.o show_mem.o \
         is_single_threaded.o plist.o decompress.o kobject_uevent.o \
@@ -44,11 +44,11 @@ lib-$(CONFIG_SMP) += cpumask.o
 lib-y  += kobject.o klist.o
 obj-y  += lockref.o
 
-obj-y += bcd.o div64.o sort.o parser.o debug_locks.o random32.o \
+obj-y += bcd.o sort.o parser.o debug_locks.o random32.o \
         bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \
-        gcd.o lcm.o list_sort.o uuid.o iov_iter.o clz_ctz.o \
+        list_sort.o uuid.o iov_iter.o clz_ctz.o \
         bsearch.o find_bit.o llist.o memweight.o kfifo.o \
-        percpu-refcount.o rhashtable.o reciprocal_div.o \
+        percpu-refcount.o rhashtable.o \
         once.o refcount.o usercopy.o errseq.o bucket_locks.o \
         generic-radix-tree.o
 obj-$(CONFIG_STRING_SELFTEST) += test_string.o
@@ -102,6 +102,8 @@ endif
 obj-$(CONFIG_DEBUG_INFO_REDUCED) += debug_info.o
 CFLAGS_debug_info.o += $(call cc-option, -femit-struct-debug-detailed=any)
 
+obj-y += math/
+
 obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
 obj-$(CONFIG_GENERIC_PCI_IOMAP) += pci_iomap.o
 obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
@@ -121,7 +123,6 @@ obj-$(CONFIG_DEBUG_OBJECTS) += debugobjects.o
 
 obj-$(CONFIG_BITREVERSE) += bitrev.o
 obj-$(CONFIG_PACKING)  += packing.o
-obj-$(CONFIG_RATIONAL) += rational.o
 obj-$(CONFIG_CRC_CCITT)        += crc-ccitt.o
 obj-$(CONFIG_CRC16)    += crc16.o
 obj-$(CONFIG_CRC_T10DIF)+= crc-t10dif.o
@@ -195,8 +196,6 @@ obj-$(CONFIG_ATOMIC64_SELFTEST) += atomic64_test.o
 
 obj-$(CONFIG_CPU_RMAP) += cpu_rmap.o
 
-obj-$(CONFIG_CORDIC) += cordic.o
-
 obj-$(CONFIG_DQL) += dynamic_queue_limits.o
 
 obj-$(CONFIG_GLOB) += glob.o
@@ -238,8 +237,6 @@ obj-$(CONFIG_ASN1) += asn1_decoder.o
 
 obj-$(CONFIG_FONT_SUPPORT) += fonts/
 
-obj-$(CONFIG_PRIME_NUMBERS) += prime_numbers.o
-
 hostprogs-y    := gen_crc32table
 hostprogs-y    += gen_crc64table
 clean-files    := crc32table.h
index 98872e9..f235434 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <asm/page.h>
 
+#include "kstrtox.h"
+
 /**
  * DOC: bitmap introduction
  *
@@ -477,12 +479,128 @@ int bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp,
 }
 EXPORT_SYMBOL(bitmap_print_to_pagebuf);
 
+/*
+ * Region 9-38:4/10 describes the following bitmap structure:
+ * 0      9  12    18                  38
+ * .........****......****......****......
+ *         ^  ^     ^                   ^
+ *      start  off   group_len        end
+ */
+struct region {
+       unsigned int start;
+       unsigned int off;
+       unsigned int group_len;
+       unsigned int end;
+};
+
+static int bitmap_set_region(const struct region *r,
+                               unsigned long *bitmap, int nbits)
+{
+       unsigned int start;
+
+       if (r->end >= nbits)
+               return -ERANGE;
+
+       for (start = r->start; start <= r->end; start += r->group_len)
+               bitmap_set(bitmap, start, min(r->end - start + 1, r->off));
+
+       return 0;
+}
+
+static int bitmap_check_region(const struct region *r)
+{
+       if (r->start > r->end || r->group_len == 0 || r->off > r->group_len)
+               return -EINVAL;
+
+       return 0;
+}
+
+static const char *bitmap_getnum(const char *str, unsigned int *num)
+{
+       unsigned long long n;
+       unsigned int len;
+
+       len = _parse_integer(str, 10, &n);
+       if (!len)
+               return ERR_PTR(-EINVAL);
+       if (len & KSTRTOX_OVERFLOW || n != (unsigned int)n)
+               return ERR_PTR(-EOVERFLOW);
+
+       *num = n;
+       return str + len;
+}
+
+static inline bool end_of_str(char c)
+{
+       return c == '\0' || c == '\n';
+}
+
+static inline bool __end_of_region(char c)
+{
+       return isspace(c) || c == ',';
+}
+
+static inline bool end_of_region(char c)
+{
+       return __end_of_region(c) || end_of_str(c);
+}
+
+/*
+ * The format allows commas and whitespases at the beginning
+ * of the region.
+ */
+static const char *bitmap_find_region(const char *str)
+{
+       while (__end_of_region(*str))
+               str++;
+
+       return end_of_str(*str) ? NULL : str;
+}
+
+static const char *bitmap_parse_region(const char *str, struct region *r)
+{
+       str = bitmap_getnum(str, &r->start);
+       if (IS_ERR(str))
+               return str;
+
+       if (end_of_region(*str))
+               goto no_end;
+
+       if (*str != '-')
+               return ERR_PTR(-EINVAL);
+
+       str = bitmap_getnum(str + 1, &r->end);
+       if (IS_ERR(str))
+               return str;
+
+       if (end_of_region(*str))
+               goto no_pattern;
+
+       if (*str != ':')
+               return ERR_PTR(-EINVAL);
+
+       str = bitmap_getnum(str + 1, &r->off);
+       if (IS_ERR(str))
+               return str;
+
+       if (*str != '/')
+               return ERR_PTR(-EINVAL);
+
+       return bitmap_getnum(str + 1, &r->group_len);
+
+no_end:
+       r->end = r->start;
+no_pattern:
+       r->off = r->end + 1;
+       r->group_len = r->end + 1;
+
+       return end_of_str(*str) ? NULL : str;
+}
+
 /**
- * __bitmap_parselist - convert list format ASCII string to bitmap
- * @buf: read nul-terminated user string from this buffer
- * @buflen: buffer size in bytes.  If string is smaller than this
- *    then it must be terminated with a \0.
- * @is_user: location of buffer, 0 indicates kernel space
+ * bitmap_parselist - convert list format ASCII string to bitmap
+ * @buf: read user string from this buffer; must be terminated
+ *    with a \0 or \n.
  * @maskp: write resulting mask here
  * @nmaskbits: number of bits in mask to be written
  *
@@ -498,127 +616,38 @@ EXPORT_SYMBOL(bitmap_print_to_pagebuf);
  *
  * Returns: 0 on success, -errno on invalid input strings. Error values:
  *
- *   - ``-EINVAL``: second number in range smaller than first
+ *   - ``-EINVAL``: wrong region format
  *   - ``-EINVAL``: invalid character in string
  *   - ``-ERANGE``: bit number specified too large for mask
+ *   - ``-EOVERFLOW``: integer overflow in the input parameters
  */
-static int __bitmap_parselist(const char *buf, unsigned int buflen,
-               int is_user, unsigned long *maskp,
-               int nmaskbits)
+int bitmap_parselist(const char *buf, unsigned long *maskp, int nmaskbits)
 {
-       unsigned int a, b, old_a, old_b;
-       unsigned int group_size, used_size, off;
-       int c, old_c, totaldigits, ndigits;
-       const char __user __force *ubuf = (const char __user __force *)buf;
-       int at_start, in_range, in_partial_range;
+       struct region r;
+       long ret;
 
-       totaldigits = c = 0;
-       old_a = old_b = 0;
-       group_size = used_size = 0;
        bitmap_zero(maskp, nmaskbits);
-       do {
-               at_start = 1;
-               in_range = 0;
-               in_partial_range = 0;
-               a = b = 0;
-               ndigits = totaldigits;
-
-               /* Get the next cpu# or a range of cpu#'s */
-               while (buflen) {
-                       old_c = c;
-                       if (is_user) {
-                               if (__get_user(c, ubuf++))
-                                       return -EFAULT;
-                       } else
-                               c = *buf++;
-                       buflen--;
-                       if (isspace(c))
-                               continue;
-
-                       /* A '\0' or a ',' signal the end of a cpu# or range */
-                       if (c == '\0' || c == ',')
-                               break;
-                       /*
-                       * whitespaces between digits are not allowed,
-                       * but it's ok if whitespaces are on head or tail.
-                       * when old_c is whilespace,
-                       * if totaldigits == ndigits, whitespace is on head.
-                       * if whitespace is on tail, it should not run here.
-                       * as c was ',' or '\0',
-                       * the last code line has broken the current loop.
-                       */
-                       if ((totaldigits != ndigits) && isspace(old_c))
-                               return -EINVAL;
 
-                       if (c == '/') {
-                               used_size = a;
-                               at_start = 1;
-                               in_range = 0;
-                               a = b = 0;
-                               continue;
-                       }
+       while (buf) {
+               buf = bitmap_find_region(buf);
+               if (buf == NULL)
+                       return 0;
 
-                       if (c == ':') {
-                               old_a = a;
-                               old_b = b;
-                               at_start = 1;
-                               in_range = 0;
-                               in_partial_range = 1;
-                               a = b = 0;
-                               continue;
-                       }
+               buf = bitmap_parse_region(buf, &r);
+               if (IS_ERR(buf))
+                       return PTR_ERR(buf);
 
-                       if (c == '-') {
-                               if (at_start || in_range)
-                                       return -EINVAL;
-                               b = 0;
-                               in_range = 1;
-                               at_start = 1;
-                               continue;
-                       }
+               ret = bitmap_check_region(&r);
+               if (ret)
+                       return ret;
 
-                       if (!isdigit(c))
-                               return -EINVAL;
+               ret = bitmap_set_region(&r, maskp, nmaskbits);
+               if (ret)
+                       return ret;
+       }
 
-                       b = b * 10 + (c - '0');
-                       if (!in_range)
-                               a = b;
-                       at_start = 0;
-                       totaldigits++;
-               }
-               if (ndigits == totaldigits)
-                       continue;
-               if (in_partial_range) {
-                       group_size = a;
-                       a = old_a;
-                       b = old_b;
-                       old_a = old_b = 0;
-               } else {
-                       used_size = group_size = b - a + 1;
-               }
-               /* if no digit is after '-', it's wrong*/
-               if (at_start && in_range)
-                       return -EINVAL;
-               if (!(a <= b) || group_size == 0 || !(used_size <= group_size))
-                       return -EINVAL;
-               if (b >= nmaskbits)
-                       return -ERANGE;
-               while (a <= b) {
-                       off = min(b - a + 1, used_size);
-                       bitmap_set(maskp, a, off);
-                       a += group_size;
-               }
-       } while (buflen && c == ',');
        return 0;
 }
-
-int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits)
-{
-       char *nl  = strchrnul(bp, '\n');
-       int len = nl - bp;
-
-       return __bitmap_parselist(bp, len, 0, maskp, nmaskbits);
-}
 EXPORT_SYMBOL(bitmap_parselist);
 
 
@@ -632,23 +661,27 @@ EXPORT_SYMBOL(bitmap_parselist);
  * @nmaskbits: size of bitmap, in bits.
  *
  * Wrapper for bitmap_parselist(), providing it with user buffer.
- *
- * We cannot have this as an inline function in bitmap.h because it needs
- * linux/uaccess.h to get the access_ok() declaration and this causes
- * cyclic dependencies.
  */
 int bitmap_parselist_user(const char __user *ubuf,
                        unsigned int ulen, unsigned long *maskp,
                        int nmaskbits)
 {
-       if (!access_ok(ubuf, ulen))
-               return -EFAULT;
-       return __bitmap_parselist((const char __force *)ubuf,
-                                       ulen, 1, maskp, nmaskbits);
+       char *buf;
+       int ret;
+
+       buf = memdup_user_nul(ubuf, ulen);
+       if (IS_ERR(buf))
+               return PTR_ERR(buf);
+
+       ret = bitmap_parselist(buf, maskp, nmaskbits);
+
+       kfree(buf);
+       return ret;
 }
 EXPORT_SYMBOL(bitmap_parselist_user);
 
 
+#ifdef CONFIG_NUMA
 /**
  * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap
  *     @buf: pointer to a bitmap
@@ -757,7 +790,6 @@ void bitmap_remap(unsigned long *dst, const unsigned long *src,
                        set_bit(bitmap_ord_to_pos(new, n % w, nbits), dst);
        }
 }
-EXPORT_SYMBOL(bitmap_remap);
 
 /**
  * bitmap_bitremap - Apply map defined by a pair of bitmaps to a single bit
@@ -795,7 +827,6 @@ int bitmap_bitremap(int oldbit, const unsigned long *old,
        else
                return bitmap_ord_to_pos(new, n % w, bits);
 }
-EXPORT_SYMBOL(bitmap_bitremap);
 
 /**
  * bitmap_onto - translate one bitmap relative to another
@@ -930,7 +961,6 @@ void bitmap_onto(unsigned long *dst, const unsigned long *orig,
                m++;
        }
 }
-EXPORT_SYMBOL(bitmap_onto);
 
 /**
  * bitmap_fold - fold larger bitmap into smaller, modulo specified size
@@ -955,7 +985,7 @@ void bitmap_fold(unsigned long *dst, const unsigned long *orig,
        for_each_set_bit(oldbit, orig, nbits)
                set_bit(oldbit % sz, dst);
 }
-EXPORT_SYMBOL(bitmap_fold);
+#endif /* CONFIG_NUMA */
 
 /*
  * Common code for bitmap_*_region() routines.
diff --git a/lib/cordic.c b/lib/cordic.c
deleted file mode 100644 (file)
index 8ef27c1..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2011 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/module.h>
-#include <linux/cordic.h>
-
-static const s32 arctan_table[] = {
-       2949120,
-       1740967,
-       919879,
-       466945,
-       234379,
-       117304,
-       58666,
-       29335,
-       14668,
-       7334,
-       3667,
-       1833,
-       917,
-       458,
-       229,
-       115,
-       57,
-       29
-};
-
-/*
- * cordic_calc_iq() - calculates the i/q coordinate for given angle
- *
- * theta: angle in degrees for which i/q coordinate is to be calculated
- * coord: function output parameter holding the i/q coordinate
- */
-struct cordic_iq cordic_calc_iq(s32 theta)
-{
-       struct cordic_iq coord;
-       s32 angle, valtmp;
-       unsigned iter;
-       int signx = 1;
-       int signtheta;
-
-       coord.i = CORDIC_ANGLE_GEN;
-       coord.q = 0;
-       angle = 0;
-
-       theta = CORDIC_FIXED(theta);
-       signtheta = (theta < 0) ? -1 : 1;
-       theta = ((theta + CORDIC_FIXED(180) * signtheta) % CORDIC_FIXED(360)) -
-               CORDIC_FIXED(180) * signtheta;
-
-       if (CORDIC_FLOAT(theta) > 90) {
-               theta -= CORDIC_FIXED(180);
-               signx = -1;
-       } else if (CORDIC_FLOAT(theta) < -90) {
-               theta += CORDIC_FIXED(180);
-               signx = -1;
-       }
-
-       for (iter = 0; iter < CORDIC_NUM_ITER; iter++) {
-               if (theta > angle) {
-                       valtmp = coord.i - (coord.q >> iter);
-                       coord.q += (coord.i >> iter);
-                       angle += arctan_table[iter];
-               } else {
-                       valtmp = coord.i + (coord.q >> iter);
-                       coord.q -= (coord.i >> iter);
-                       angle -= arctan_table[iter];
-               }
-               coord.i = valtmp;
-       }
-
-       coord.i *= signx;
-       coord.q *= signx;
-       return coord;
-}
-EXPORT_SYMBOL(cordic_calc_iq);
-
-MODULE_DESCRIPTION("CORDIC algorithm");
-MODULE_AUTHOR("Broadcom Corporation");
-MODULE_LICENSE("Dual BSD/GPL");
diff --git a/lib/div64.c b/lib/div64.c
deleted file mode 100644 (file)
index ee146bb..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
- *
- * Based on former do_div() implementation from asm-parisc/div64.h:
- *     Copyright (C) 1999 Hewlett-Packard Co
- *     Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- *
- * Generic C version of 64bit/32bit division and modulo, with
- * 64bit result and 32bit remainder.
- *
- * The fast case for (n>>32 == 0) is handled inline by do_div(). 
- *
- * Code generated for this function might be very inefficient
- * for some CPUs. __div64_32() can be overridden by linking arch-specific
- * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S
- * or by defining a preprocessor macro in arch/include/asm/div64.h.
- */
-
-#include <linux/export.h>
-#include <linux/kernel.h>
-#include <linux/math64.h>
-
-/* Not needed on 64bit architectures */
-#if BITS_PER_LONG == 32
-
-#ifndef __div64_32
-uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base)
-{
-       uint64_t rem = *n;
-       uint64_t b = base;
-       uint64_t res, d = 1;
-       uint32_t high = rem >> 32;
-
-       /* Reduce the thing a bit first */
-       res = 0;
-       if (high >= base) {
-               high /= base;
-               res = (uint64_t) high << 32;
-               rem -= (uint64_t) (high*base) << 32;
-       }
-
-       while ((int64_t)b > 0 && b < rem) {
-               b = b+b;
-               d = d+d;
-       }
-
-       do {
-               if (rem >= b) {
-                       rem -= b;
-                       res += d;
-               }
-               b >>= 1;
-               d >>= 1;
-       } while (d);
-
-       *n = res;
-       return rem;
-}
-EXPORT_SYMBOL(__div64_32);
-#endif
-
-/**
- * div_s64_rem - signed 64bit divide with 64bit divisor and remainder
- * @dividend:  64bit dividend
- * @divisor:   64bit divisor
- * @remainder:  64bit remainder
- */
-#ifndef div_s64_rem
-s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
-{
-       u64 quotient;
-
-       if (dividend < 0) {
-               quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder);
-               *remainder = -*remainder;
-               if (divisor > 0)
-                       quotient = -quotient;
-       } else {
-               quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder);
-               if (divisor < 0)
-                       quotient = -quotient;
-       }
-       return quotient;
-}
-EXPORT_SYMBOL(div_s64_rem);
-#endif
-
-/**
- * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
- * @dividend:  64bit dividend
- * @divisor:   64bit divisor
- * @remainder:  64bit remainder
- *
- * This implementation is a comparable to algorithm used by div64_u64.
- * But this operation, which includes math for calculating the remainder,
- * is kept distinct to avoid slowing down the div64_u64 operation on 32bit
- * systems.
- */
-#ifndef div64_u64_rem
-u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
-{
-       u32 high = divisor >> 32;
-       u64 quot;
-
-       if (high == 0) {
-               u32 rem32;
-               quot = div_u64_rem(dividend, divisor, &rem32);
-               *remainder = rem32;
-       } else {
-               int n = fls(high);
-               quot = div_u64(dividend >> n, divisor >> n);
-
-               if (quot != 0)
-                       quot--;
-
-               *remainder = dividend - quot * divisor;
-               if (*remainder >= divisor) {
-                       quot++;
-                       *remainder -= divisor;
-               }
-       }
-
-       return quot;
-}
-EXPORT_SYMBOL(div64_u64_rem);
-#endif
-
-/**
- * div64_u64 - unsigned 64bit divide with 64bit divisor
- * @dividend:  64bit dividend
- * @divisor:   64bit divisor
- *
- * This implementation is a modified version of the algorithm proposed
- * by the book 'Hacker's Delight'.  The original source and full proof
- * can be found here and is available for use without restriction.
- *
- * 'http://www.hackersdelight.org/hdcodetxt/divDouble.c.txt'
- */
-#ifndef div64_u64
-u64 div64_u64(u64 dividend, u64 divisor)
-{
-       u32 high = divisor >> 32;
-       u64 quot;
-
-       if (high == 0) {
-               quot = div_u64(dividend, divisor);
-       } else {
-               int n = fls(high);
-               quot = div_u64(dividend >> n, divisor >> n);
-
-               if (quot != 0)
-                       quot--;
-               if ((dividend - quot * divisor) >= divisor)
-                       quot++;
-       }
-
-       return quot;
-}
-EXPORT_SYMBOL(div64_u64);
-#endif
-
-/**
- * div64_s64 - signed 64bit divide with 64bit divisor
- * @dividend:  64bit dividend
- * @divisor:   64bit divisor
- */
-#ifndef div64_s64
-s64 div64_s64(s64 dividend, s64 divisor)
-{
-       s64 quot, t;
-
-       quot = div64_u64(abs(dividend), abs(divisor));
-       t = (dividend ^ divisor) >> 63;
-
-       return (quot ^ t) - t;
-}
-EXPORT_SYMBOL(div64_s64);
-#endif
-
-#endif /* BITS_PER_LONG == 32 */
-
-/*
- * Iterative div/mod for use when dividend is not expected to be much
- * bigger than divisor.
- */
-u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
-{
-       return __iter_div_u64_rem(dividend, divisor, remainder);
-}
-EXPORT_SYMBOL(iter_div_u64_rem);
diff --git a/lib/gcd.c b/lib/gcd.c
deleted file mode 100644 (file)
index 7948ab2..0000000
--- a/lib/gcd.c
+++ /dev/null
@@ -1,84 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/gcd.h>
-#include <linux/export.h>
-
-/*
- * This implements the binary GCD algorithm. (Often attributed to Stein,
- * but as Knuth has noted, appears in a first-century Chinese math text.)
- *
- * This is faster than the division-based algorithm even on x86, which
- * has decent hardware division.
- */
-
-#if !defined(CONFIG_CPU_NO_EFFICIENT_FFS)
-
-/* If __ffs is available, the even/odd algorithm benchmarks slower. */
-
-/**
- * gcd - calculate and return the greatest common divisor of 2 unsigned longs
- * @a: first value
- * @b: second value
- */
-unsigned long gcd(unsigned long a, unsigned long b)
-{
-       unsigned long r = a | b;
-
-       if (!a || !b)
-               return r;
-
-       b >>= __ffs(b);
-       if (b == 1)
-               return r & -r;
-
-       for (;;) {
-               a >>= __ffs(a);
-               if (a == 1)
-                       return r & -r;
-               if (a == b)
-                       return a << __ffs(r);
-
-               if (a < b)
-                       swap(a, b);
-               a -= b;
-       }
-}
-
-#else
-
-/* If normalization is done by loops, the even/odd algorithm is a win. */
-unsigned long gcd(unsigned long a, unsigned long b)
-{
-       unsigned long r = a | b;
-
-       if (!a || !b)
-               return r;
-
-       /* Isolate lsbit of r */
-       r &= -r;
-
-       while (!(b & r))
-               b >>= 1;
-       if (b == r)
-               return r;
-
-       for (;;) {
-               while (!(a & r))
-                       a >>= 1;
-               if (a == r)
-                       return r;
-               if (a == b)
-                       return a;
-
-               if (a < b)
-                       swap(a, b);
-               a -= b;
-               a >>= 1;
-               if (a & r)
-                       a += b;
-               a >>= 1;
-       }
-}
-
-#endif
-
-EXPORT_SYMBOL_GPL(gcd);
index 7660d88..c94586b 100644 (file)
@@ -10,7 +10,6 @@
  * The Hamming Weight of a number is the total number of bits set in it.
  */
 
-#ifndef __HAVE_ARCH_SW_HWEIGHT
 unsigned int __sw_hweight32(unsigned int w)
 {
 #ifdef CONFIG_ARCH_HAS_FAST_MULTIPLIER
@@ -27,7 +26,6 @@ unsigned int __sw_hweight32(unsigned int w)
 #endif
 }
 EXPORT_SYMBOL(__sw_hweight32);
-#endif
 
 unsigned int __sw_hweight16(unsigned int w)
 {
@@ -46,7 +44,6 @@ unsigned int __sw_hweight8(unsigned int w)
 }
 EXPORT_SYMBOL(__sw_hweight8);
 
-#ifndef __HAVE_ARCH_SW_HWEIGHT
 unsigned long __sw_hweight64(__u64 w)
 {
 #if BITS_PER_LONG == 32
@@ -69,4 +66,3 @@ unsigned long __sw_hweight64(__u64 w)
 #endif
 }
 EXPORT_SYMBOL(__sw_hweight64);
-#endif
diff --git a/lib/int_sqrt.c b/lib/int_sqrt.c
deleted file mode 100644 (file)
index 30e0f97..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2013 Davidlohr Bueso <davidlohr.bueso@hp.com>
- *
- *  Based on the shift-and-subtract algorithm for computing integer
- *  square root from Guy L. Steele.
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/bitops.h>
-
-/**
- * int_sqrt - computes the integer square root
- * @x: integer of which to calculate the sqrt
- *
- * Computes: floor(sqrt(x))
- */
-unsigned long int_sqrt(unsigned long x)
-{
-       unsigned long b, m, y = 0;
-
-       if (x <= 1)
-               return x;
-
-       m = 1UL << (__fls(x) & ~1UL);
-       while (m != 0) {
-               b = y + m;
-               y >>= 1;
-
-               if (x >= b) {
-                       x -= b;
-                       y += m;
-               }
-               m >>= 2;
-       }
-
-       return y;
-}
-EXPORT_SYMBOL(int_sqrt);
-
-#if BITS_PER_LONG < 64
-/**
- * int_sqrt64 - strongly typed int_sqrt function when minimum 64 bit input
- * is expected.
- * @x: 64bit integer of which to calculate the sqrt
- */
-u32 int_sqrt64(u64 x)
-{
-       u64 b, m, y = 0;
-
-       if (x <= ULONG_MAX)
-               return int_sqrt((unsigned long) x);
-
-       m = 1ULL << ((fls64(x) - 1) & ~1ULL);
-       while (m != 0) {
-               b = y + m;
-               y >>= 1;
-
-               if (x >= b) {
-                       x -= b;
-                       y += m;
-               }
-               m >>= 2;
-       }
-
-       return y;
-}
-EXPORT_SYMBOL(int_sqrt64);
-#endif
index b396d32..f74fa83 100644 (file)
@@ -1293,7 +1293,9 @@ ssize_t iov_iter_get_pages(struct iov_iter *i,
                        len = maxpages * PAGE_SIZE;
                addr &= ~(PAGE_SIZE - 1);
                n = DIV_ROUND_UP(len, PAGE_SIZE);
-               res = get_user_pages_fast(addr, n, iov_iter_rw(i) != WRITE, pages);
+               res = get_user_pages_fast(addr, n,
+                               iov_iter_rw(i) != WRITE ?  FOLL_WRITE : 0,
+                               pages);
                if (unlikely(res < 0))
                        return res;
                return (res == n ? len : res * PAGE_SIZE) - *start;
@@ -1374,7 +1376,8 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
                p = get_pages_array(n);
                if (!p)
                        return -ENOMEM;
-               res = get_user_pages_fast(addr, n, iov_iter_rw(i) != WRITE, p);
+               res = get_user_pages_fast(addr, n,
+                               iov_iter_rw(i) != WRITE ?  FOLL_WRITE : 0, p);
                if (unlikely(res < 0)) {
                        kvfree(p);
                        return res;
diff --git a/lib/lcm.c b/lib/lcm.c
deleted file mode 100644 (file)
index 03d7fcb..0000000
--- a/lib/lcm.c
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <linux/compiler.h>
-#include <linux/gcd.h>
-#include <linux/export.h>
-#include <linux/lcm.h>
-
-/* Lowest common multiple */
-unsigned long lcm(unsigned long a, unsigned long b)
-{
-       if (a && b)
-               return (a / gcd(a, b)) * b;
-       else
-               return 0;
-}
-EXPORT_SYMBOL_GPL(lcm);
-
-unsigned long lcm_not_zero(unsigned long a, unsigned long b)
-{
-       unsigned long l = lcm(a, b);
-
-       if (l)
-               return l;
-
-       return (b ? : a);
-}
-EXPORT_SYMBOL_GPL(lcm_not_zero);
index 8575992..06e900c 100644 (file)
@@ -7,33 +7,41 @@
 #include <linux/list_sort.h>
 #include <linux/list.h>
 
-#define MAX_LIST_LENGTH_BITS 20
+typedef int __attribute__((nonnull(2,3))) (*cmp_func)(void *,
+               struct list_head const *, struct list_head const *);
 
 /*
  * Returns a list organized in an intermediate format suited
  * to chaining of merge() calls: null-terminated, no reserved or
  * sentinel head node, "prev" links not maintained.
  */
-static struct list_head *merge(void *priv,
-                               int (*cmp)(void *priv, struct list_head *a,
-                                       struct list_head *b),
+__attribute__((nonnull(2,3,4)))
+static struct list_head *merge(void *priv, cmp_func cmp,
                                struct list_head *a, struct list_head *b)
 {
-       struct list_head head, *tail = &head;
+       struct list_head *head, **tail = &head;
 
-       while (a && b) {
+       for (;;) {
                /* if equal, take 'a' -- important for sort stability */
-               if ((*cmp)(priv, a, b) <= 0) {
-                       tail->next = a;
+               if (cmp(priv, a, b) <= 0) {
+                       *tail = a;
+                       tail = &a->next;
                        a = a->next;
+                       if (!a) {
+                               *tail = b;
+                               break;
+                       }
                } else {
-                       tail->next = b;
+                       *tail = b;
+                       tail = &b->next;
                        b = b->next;
+                       if (!b) {
+                               *tail = a;
+                               break;
+                       }
                }
-               tail = tail->next;
        }
-       tail->next = a?:b;
-       return head.next;
+       return head;
 }
 
 /*
@@ -43,44 +51,52 @@ static struct list_head *merge(void *priv,
  * prev-link restoration pass, or maintaining the prev links
  * throughout.
  */
-static void merge_and_restore_back_links(void *priv,
-                               int (*cmp)(void *priv, struct list_head *a,
-                                       struct list_head *b),
-                               struct list_head *head,
-                               struct list_head *a, struct list_head *b)
+__attribute__((nonnull(2,3,4,5)))
+static void merge_final(void *priv, cmp_func cmp, struct list_head *head,
+                       struct list_head *a, struct list_head *b)
 {
        struct list_head *tail = head;
        u8 count = 0;
 
-       while (a && b) {
+       for (;;) {
                /* if equal, take 'a' -- important for sort stability */
-               if ((*cmp)(priv, a, b) <= 0) {
+               if (cmp(priv, a, b) <= 0) {
                        tail->next = a;
                        a->prev = tail;
+                       tail = a;
                        a = a->next;
+                       if (!a)
+                               break;
                } else {
                        tail->next = b;
                        b->prev = tail;
+                       tail = b;
                        b = b->next;
+                       if (!b) {
+                               b = a;
+                               break;
+                       }
                }
-               tail = tail->next;
        }
-       tail->next = a ? : b;
 
+       /* Finish linking remainder of list b on to tail */
+       tail->next = b;
        do {
                /*
-                * In worst cases this loop may run many iterations.
+                * If the merge is highly unbalanced (e.g. the input is
+                * already sorted), this loop may run many iterations.
                 * Continue callbacks to the client even though no
                 * element comparison is needed, so the client's cmp()
                 * routine can invoke cond_resched() periodically.
                 */
-               if (unlikely(!(++count)))
-                       (*cmp)(priv, tail->next, tail->next);
-
-               tail->next->prev = tail;
-               tail = tail->next;
-       } while (tail->next);
-
+               if (unlikely(!++count))
+                       cmp(priv, b, b);
+               b->prev = tail;
+               tail = b;
+               b = b->next;
+       } while (b);
+
+       /* And the final links to make a circular doubly-linked list */
        tail->next = head;
        head->prev = tail;
 }
@@ -91,55 +107,149 @@ static void merge_and_restore_back_links(void *priv,
  * @head: the list to sort
  * @cmp: the elements comparison function
  *
- * This function implements "merge sort", which has O(nlog(n))
- * complexity.
+ * The comparison funtion @cmp must return > 0 if @a should sort after
+ * @b ("@a > @b" if you want an ascending sort), and <= 0 if @a should
+ * sort before @b *or* their original order should be preserved.  It is
+ * always called with the element that came first in the input in @a,
+ * and list_sort is a stable sort, so it is not necessary to distinguish
+ * the @a < @b and @a == @b cases.
+ *
+ * This is compatible with two styles of @cmp function:
+ * - The traditional style which returns <0 / =0 / >0, or
+ * - Returning a boolean 0/1.
+ * The latter offers a chance to save a few cycles in the comparison
+ * (which is used by e.g. plug_ctx_cmp() in block/blk-mq.c).
+ *
+ * A good way to write a multi-word comparison is
+ *     if (a->high != b->high)
+ *             return a->high > b->high;
+ *     if (a->middle != b->middle)
+ *             return a->middle > b->middle;
+ *     return a->low > b->low;
+ *
+ *
+ * This mergesort is as eager as possible while always performing at least
+ * 2:1 balanced merges.  Given two pending sublists of size 2^k, they are
+ * merged to a size-2^(k+1) list as soon as we have 2^k following elements.
+ *
+ * Thus, it will avoid cache thrashing as long as 3*2^k elements can
+ * fit into the cache.  Not quite as good as a fully-eager bottom-up
+ * mergesort, but it does use 0.2*n fewer comparisons, so is faster in
+ * the common case that everything fits into L1.
+ *
+ *
+ * The merging is controlled by "count", the number of elements in the
+ * pending lists.  This is beautiully simple code, but rather subtle.
  *
- * The comparison function @cmp must return a negative value if @a
- * should sort before @b, and a positive value if @a should sort after
- * @b. If @a and @b are equivalent, and their original relative
- * ordering is to be preserved, @cmp must return 0.
+ * Each time we increment "count", we set one bit (bit k) and clear
+ * bits k-1 .. 0.  Each time this happens (except the very first time
+ * for each bit, when count increments to 2^k), we merge two lists of
+ * size 2^k into one list of size 2^(k+1).
+ *
+ * This merge happens exactly when the count reaches an odd multiple of
+ * 2^k, which is when we have 2^k elements pending in smaller lists,
+ * so it's safe to merge away two lists of size 2^k.
+ *
+ * After this happens twice, we have created two lists of size 2^(k+1),
+ * which will be merged into a list of size 2^(k+2) before we create
+ * a third list of size 2^(k+1), so there are never more than two pending.
+ *
+ * The number of pending lists of size 2^k is determined by the
+ * state of bit k of "count" plus two extra pieces of information:
+ * - The state of bit k-1 (when k == 0, consider bit -1 always set), and
+ * - Whether the higher-order bits are zero or non-zero (i.e.
+ *   is count >= 2^(k+1)).
+ * There are six states we distinguish.  "x" represents some arbitrary
+ * bits, and "y" represents some arbitrary non-zero bits:
+ * 0:  00x: 0 pending of size 2^k;           x pending of sizes < 2^k
+ * 1:  01x: 0 pending of size 2^k; 2^(k-1) + x pending of sizes < 2^k
+ * 2: x10x: 0 pending of size 2^k; 2^k     + x pending of sizes < 2^k
+ * 3: x11x: 1 pending of size 2^k; 2^(k-1) + x pending of sizes < 2^k
+ * 4: y00x: 1 pending of size 2^k; 2^k     + x pending of sizes < 2^k
+ * 5: y01x: 2 pending of size 2^k; 2^(k-1) + x pending of sizes < 2^k
+ * (merge and loop back to state 2)
+ *
+ * We gain lists of size 2^k in the 2->3 and 4->5 transitions (because
+ * bit k-1 is set while the more significant bits are non-zero) and
+ * merge them away in the 5->2 transition.  Note in particular that just
+ * before the 5->2 transition, all lower-order bits are 11 (state 3),
+ * so there is one list of each smaller size.
+ *
+ * When we reach the end of the input, we merge all the pending
+ * lists, from smallest to largest.  If you work through cases 2 to
+ * 5 above, you can see that the number of elements we merge with a list
+ * of size 2^k varies from 2^(k-1) (cases 3 and 5 when x == 0) to
+ * 2^(k+1) - 1 (second merge of case 5 when x == 2^(k-1) - 1).
  */
+__attribute__((nonnull(2,3)))
 void list_sort(void *priv, struct list_head *head,
                int (*cmp)(void *priv, struct list_head *a,
                        struct list_head *b))
 {
-       struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists
-                                               -- last slot is a sentinel */
-       int lev;  /* index into part[] */
-       int max_lev = 0;
-       struct list_head *list;
+       struct list_head *list = head->next, *pending = NULL;
+       size_t count = 0;       /* Count of pending */
 
-       if (list_empty(head))
+       if (list == head->prev) /* Zero or one elements */
                return;
 
-       memset(part, 0, sizeof(part));
-
+       /* Convert to a null-terminated singly-linked list. */
        head->prev->next = NULL;
-       list = head->next;
-
-       while (list) {
-               struct list_head *cur = list;
-               list = list->next;
-               cur->next = NULL;
 
-               for (lev = 0; part[lev]; lev++) {
-                       cur = merge(priv, cmp, part[lev], cur);
-                       part[lev] = NULL;
-               }
-               if (lev > max_lev) {
-                       if (unlikely(lev >= ARRAY_SIZE(part)-1)) {
-                               printk_once(KERN_DEBUG "list too long for efficiency\n");
-                               lev--;
-                       }
-                       max_lev = lev;
+       /*
+        * Data structure invariants:
+        * - All lists are singly linked and null-terminated; prev
+        *   pointers are not maintained.
+        * - pending is a prev-linked "list of lists" of sorted
+        *   sublists awaiting further merging.
+        * - Each of the sorted sublists is power-of-two in size.
+        * - Sublists are sorted by size and age, smallest & newest at front.
+        * - There are zero to two sublists of each size.
+        * - A pair of pending sublists are merged as soon as the number
+        *   of following pending elements equals their size (i.e.
+        *   each time count reaches an odd multiple of that size).
+        *   That ensures each later final merge will be at worst 2:1.
+        * - Each round consists of:
+        *   - Merging the two sublists selected by the highest bit
+        *     which flips when count is incremented, and
+        *   - Adding an element from the input as a size-1 sublist.
+        */
+       do {
+               size_t bits;
+               struct list_head **tail = &pending;
+
+               /* Find the least-significant clear bit in count */
+               for (bits = count; bits & 1; bits >>= 1)
+                       tail = &(*tail)->prev;
+               /* Do the indicated merge */
+               if (likely(bits)) {
+                       struct list_head *a = *tail, *b = a->prev;
+
+                       a = merge(priv, (cmp_func)cmp, b, a);
+                       /* Install the merged result in place of the inputs */
+                       a->prev = b->prev;
+                       *tail = a;
                }
-               part[lev] = cur;
-       }
 
-       for (lev = 0; lev < max_lev; lev++)
-               if (part[lev])
-                       list = merge(priv, cmp, part[lev], list);
-
-       merge_and_restore_back_links(priv, cmp, head, part[max_lev], list);
+               /* Move one element from input list to pending */
+               list->prev = pending;
+               pending = list;
+               list = list->next;
+               pending->next = NULL;
+               count++;
+       } while (list);
+
+       /* End of input; merge together all the pending lists. */
+       list = pending;
+       pending = pending->prev;
+       for (;;) {
+               struct list_head *next = pending->prev;
+
+               if (!next)
+                       break;
+               list = merge(priv, (cmp_func)cmp, pending, list);
+               pending = next;
+       }
+       /* The final merge, rebuilding prev links */
+       merge_final(priv, (cmp_func)cmp, head, pending, list);
 }
 EXPORT_SYMBOL(list_sort);
diff --git a/lib/math/Kconfig b/lib/math/Kconfig
new file mode 100644 (file)
index 0000000..73bdf37
--- /dev/null
@@ -0,0 +1,11 @@
+config CORDIC
+       tristate "CORDIC algorithm"
+       help
+         This option provides an implementation of the CORDIC algorithm;
+         calculations are in fixed point. Module will be called cordic.
+
+config PRIME_NUMBERS
+       tristate
+
+config RATIONAL
+       bool
diff --git a/lib/math/Makefile b/lib/math/Makefile
new file mode 100644 (file)
index 0000000..583bbfe
--- /dev/null
@@ -0,0 +1,5 @@
+obj-y += div64.o gcd.o lcm.o int_pow.o int_sqrt.o reciprocal_div.o
+
+obj-$(CONFIG_CORDIC)           += cordic.o
+obj-$(CONFIG_PRIME_NUMBERS)    += prime_numbers.o
+obj-$(CONFIG_RATIONAL)         += rational.o
diff --git a/lib/math/cordic.c b/lib/math/cordic.c
new file mode 100644 (file)
index 0000000..8ef27c1
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/module.h>
+#include <linux/cordic.h>
+
+static const s32 arctan_table[] = {
+       2949120,
+       1740967,
+       919879,
+       466945,
+       234379,
+       117304,
+       58666,
+       29335,
+       14668,
+       7334,
+       3667,
+       1833,
+       917,
+       458,
+       229,
+       115,
+       57,
+       29
+};
+
+/*
+ * cordic_calc_iq() - calculates the i/q coordinate for given angle
+ *
+ * theta: angle in degrees for which i/q coordinate is to be calculated
+ * coord: function output parameter holding the i/q coordinate
+ */
+struct cordic_iq cordic_calc_iq(s32 theta)
+{
+       struct cordic_iq coord;
+       s32 angle, valtmp;
+       unsigned iter;
+       int signx = 1;
+       int signtheta;
+
+       coord.i = CORDIC_ANGLE_GEN;
+       coord.q = 0;
+       angle = 0;
+
+       theta = CORDIC_FIXED(theta);
+       signtheta = (theta < 0) ? -1 : 1;
+       theta = ((theta + CORDIC_FIXED(180) * signtheta) % CORDIC_FIXED(360)) -
+               CORDIC_FIXED(180) * signtheta;
+
+       if (CORDIC_FLOAT(theta) > 90) {
+               theta -= CORDIC_FIXED(180);
+               signx = -1;
+       } else if (CORDIC_FLOAT(theta) < -90) {
+               theta += CORDIC_FIXED(180);
+               signx = -1;
+       }
+
+       for (iter = 0; iter < CORDIC_NUM_ITER; iter++) {
+               if (theta > angle) {
+                       valtmp = coord.i - (coord.q >> iter);
+                       coord.q += (coord.i >> iter);
+                       angle += arctan_table[iter];
+               } else {
+                       valtmp = coord.i + (coord.q >> iter);
+                       coord.q -= (coord.i >> iter);
+                       angle -= arctan_table[iter];
+               }
+               coord.i = valtmp;
+       }
+
+       coord.i *= signx;
+       coord.q *= signx;
+       return coord;
+}
+EXPORT_SYMBOL(cordic_calc_iq);
+
+MODULE_DESCRIPTION("CORDIC algorithm");
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/lib/math/div64.c b/lib/math/div64.c
new file mode 100644 (file)
index 0000000..368ca7f
--- /dev/null
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
+ *
+ * Based on former do_div() implementation from asm-parisc/div64.h:
+ *     Copyright (C) 1999 Hewlett-Packard Co
+ *     Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ *
+ * Generic C version of 64bit/32bit division and modulo, with
+ * 64bit result and 32bit remainder.
+ *
+ * The fast case for (n>>32 == 0) is handled inline by do_div().
+ *
+ * Code generated for this function might be very inefficient
+ * for some CPUs. __div64_32() can be overridden by linking arch-specific
+ * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S
+ * or by defining a preprocessor macro in arch/include/asm/div64.h.
+ */
+
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+
+/* Not needed on 64bit architectures */
+#if BITS_PER_LONG == 32
+
+#ifndef __div64_32
+uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base)
+{
+       uint64_t rem = *n;
+       uint64_t b = base;
+       uint64_t res, d = 1;
+       uint32_t high = rem >> 32;
+
+       /* Reduce the thing a bit first */
+       res = 0;
+       if (high >= base) {
+               high /= base;
+               res = (uint64_t) high << 32;
+               rem -= (uint64_t) (high*base) << 32;
+       }
+
+       while ((int64_t)b > 0 && b < rem) {
+               b = b+b;
+               d = d+d;
+       }
+
+       do {
+               if (rem >= b) {
+                       rem -= b;
+                       res += d;
+               }
+               b >>= 1;
+               d >>= 1;
+       } while (d);
+
+       *n = res;
+       return rem;
+}
+EXPORT_SYMBOL(__div64_32);
+#endif
+
+/**
+ * div_s64_rem - signed 64bit divide with 64bit divisor and remainder
+ * @dividend:  64bit dividend
+ * @divisor:   64bit divisor
+ * @remainder:  64bit remainder
+ */
+#ifndef div_s64_rem
+s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
+{
+       u64 quotient;
+
+       if (dividend < 0) {
+               quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder);
+               *remainder = -*remainder;
+               if (divisor > 0)
+                       quotient = -quotient;
+       } else {
+               quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder);
+               if (divisor < 0)
+                       quotient = -quotient;
+       }
+       return quotient;
+}
+EXPORT_SYMBOL(div_s64_rem);
+#endif
+
+/**
+ * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
+ * @dividend:  64bit dividend
+ * @divisor:   64bit divisor
+ * @remainder:  64bit remainder
+ *
+ * This implementation is a comparable to algorithm used by div64_u64.
+ * But this operation, which includes math for calculating the remainder,
+ * is kept distinct to avoid slowing down the div64_u64 operation on 32bit
+ * systems.
+ */
+#ifndef div64_u64_rem
+u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
+{
+       u32 high = divisor >> 32;
+       u64 quot;
+
+       if (high == 0) {
+               u32 rem32;
+               quot = div_u64_rem(dividend, divisor, &rem32);
+               *remainder = rem32;
+       } else {
+               int n = fls(high);
+               quot = div_u64(dividend >> n, divisor >> n);
+
+               if (quot != 0)
+                       quot--;
+
+               *remainder = dividend - quot * divisor;
+               if (*remainder >= divisor) {
+                       quot++;
+                       *remainder -= divisor;
+               }
+       }
+
+       return quot;
+}
+EXPORT_SYMBOL(div64_u64_rem);
+#endif
+
+/**
+ * div64_u64 - unsigned 64bit divide with 64bit divisor
+ * @dividend:  64bit dividend
+ * @divisor:   64bit divisor
+ *
+ * This implementation is a modified version of the algorithm proposed
+ * by the book 'Hacker's Delight'.  The original source and full proof
+ * can be found here and is available for use without restriction.
+ *
+ * 'http://www.hackersdelight.org/hdcodetxt/divDouble.c.txt'
+ */
+#ifndef div64_u64
+u64 div64_u64(u64 dividend, u64 divisor)
+{
+       u32 high = divisor >> 32;
+       u64 quot;
+
+       if (high == 0) {
+               quot = div_u64(dividend, divisor);
+       } else {
+               int n = fls(high);
+               quot = div_u64(dividend >> n, divisor >> n);
+
+               if (quot != 0)
+                       quot--;
+               if ((dividend - quot * divisor) >= divisor)
+                       quot++;
+       }
+
+       return quot;
+}
+EXPORT_SYMBOL(div64_u64);
+#endif
+
+/**
+ * div64_s64 - signed 64bit divide with 64bit divisor
+ * @dividend:  64bit dividend
+ * @divisor:   64bit divisor
+ */
+#ifndef div64_s64
+s64 div64_s64(s64 dividend, s64 divisor)
+{
+       s64 quot, t;
+
+       quot = div64_u64(abs(dividend), abs(divisor));
+       t = (dividend ^ divisor) >> 63;
+
+       return (quot ^ t) - t;
+}
+EXPORT_SYMBOL(div64_s64);
+#endif
+
+#endif /* BITS_PER_LONG == 32 */
+
+/*
+ * Iterative div/mod for use when dividend is not expected to be much
+ * bigger than divisor.
+ */
+u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
+{
+       return __iter_div_u64_rem(dividend, divisor, remainder);
+}
+EXPORT_SYMBOL(iter_div_u64_rem);
diff --git a/lib/math/gcd.c b/lib/math/gcd.c
new file mode 100644 (file)
index 0000000..7948ab2
--- /dev/null
@@ -0,0 +1,84 @@
+#include <linux/kernel.h>
+#include <linux/gcd.h>
+#include <linux/export.h>
+
+/*
+ * This implements the binary GCD algorithm. (Often attributed to Stein,
+ * but as Knuth has noted, appears in a first-century Chinese math text.)
+ *
+ * This is faster than the division-based algorithm even on x86, which
+ * has decent hardware division.
+ */
+
+#if !defined(CONFIG_CPU_NO_EFFICIENT_FFS)
+
+/* If __ffs is available, the even/odd algorithm benchmarks slower. */
+
+/**
+ * gcd - calculate and return the greatest common divisor of 2 unsigned longs
+ * @a: first value
+ * @b: second value
+ */
+unsigned long gcd(unsigned long a, unsigned long b)
+{
+       unsigned long r = a | b;
+
+       if (!a || !b)
+               return r;
+
+       b >>= __ffs(b);
+       if (b == 1)
+               return r & -r;
+
+       for (;;) {
+               a >>= __ffs(a);
+               if (a == 1)
+                       return r & -r;
+               if (a == b)
+                       return a << __ffs(r);
+
+               if (a < b)
+                       swap(a, b);
+               a -= b;
+       }
+}
+
+#else
+
+/* If normalization is done by loops, the even/odd algorithm is a win. */
+unsigned long gcd(unsigned long a, unsigned long b)
+{
+       unsigned long r = a | b;
+
+       if (!a || !b)
+               return r;
+
+       /* Isolate lsbit of r */
+       r &= -r;
+
+       while (!(b & r))
+               b >>= 1;
+       if (b == r)
+               return r;
+
+       for (;;) {
+               while (!(a & r))
+                       a >>= 1;
+               if (a == r)
+                       return r;
+               if (a == b)
+                       return a;
+
+               if (a < b)
+                       swap(a, b);
+               a -= b;
+               a >>= 1;
+               if (a & r)
+                       a += b;
+               a >>= 1;
+       }
+}
+
+#endif
+
+EXPORT_SYMBOL_GPL(gcd);
diff --git a/lib/math/int_pow.c b/lib/math/int_pow.c
new file mode 100644 (file)
index 0000000..622fc1a
--- /dev/null
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * An integer based power function
+ *
+ * Derived from drivers/video/backlight/pwm_bl.c
+ */
+
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+/**
+ * int_pow - computes the exponentiation of the given base and exponent
+ * @base: base which will be raised to the given power
+ * @exp: power to be raised to
+ *
+ * Computes: pow(base, exp), i.e. @base raised to the @exp power
+ */
+u64 int_pow(u64 base, unsigned int exp)
+{
+       u64 result = 1;
+
+       while (exp) {
+               if (exp & 1)
+                       result *= base;
+               exp >>= 1;
+               base *= base;
+       }
+
+       return result;
+}
+EXPORT_SYMBOL_GPL(int_pow);
diff --git a/lib/math/int_sqrt.c b/lib/math/int_sqrt.c
new file mode 100644 (file)
index 0000000..30e0f97
--- /dev/null
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2013 Davidlohr Bueso <davidlohr.bueso@hp.com>
+ *
+ *  Based on the shift-and-subtract algorithm for computing integer
+ *  square root from Guy L. Steele.
+ */
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/bitops.h>
+
+/**
+ * int_sqrt - computes the integer square root
+ * @x: integer of which to calculate the sqrt
+ *
+ * Computes: floor(sqrt(x))
+ */
+unsigned long int_sqrt(unsigned long x)
+{
+       unsigned long b, m, y = 0;
+
+       if (x <= 1)
+               return x;
+
+       m = 1UL << (__fls(x) & ~1UL);
+       while (m != 0) {
+               b = y + m;
+               y >>= 1;
+
+               if (x >= b) {
+                       x -= b;
+                       y += m;
+               }
+               m >>= 2;
+       }
+
+       return y;
+}
+EXPORT_SYMBOL(int_sqrt);
+
+#if BITS_PER_LONG < 64
+/**
+ * int_sqrt64 - strongly typed int_sqrt function when minimum 64 bit input
+ * is expected.
+ * @x: 64bit integer of which to calculate the sqrt
+ */
+u32 int_sqrt64(u64 x)
+{
+       u64 b, m, y = 0;
+
+       if (x <= ULONG_MAX)
+               return int_sqrt((unsigned long) x);
+
+       m = 1ULL << ((fls64(x) - 1) & ~1ULL);
+       while (m != 0) {
+               b = y + m;
+               y >>= 1;
+
+               if (x >= b) {
+                       x -= b;
+                       y += m;
+               }
+               m >>= 2;
+       }
+
+       return y;
+}
+EXPORT_SYMBOL(int_sqrt64);
+#endif
diff --git a/lib/math/lcm.c b/lib/math/lcm.c
new file mode 100644 (file)
index 0000000..03d7fcb
--- /dev/null
@@ -0,0 +1,25 @@
+#include <linux/compiler.h>
+#include <linux/gcd.h>
+#include <linux/export.h>
+#include <linux/lcm.h>
+
+/* Lowest common multiple */
+unsigned long lcm(unsigned long a, unsigned long b)
+{
+       if (a && b)
+               return (a / gcd(a, b)) * b;
+       else
+               return 0;
+}
+EXPORT_SYMBOL_GPL(lcm);
+
+unsigned long lcm_not_zero(unsigned long a, unsigned long b)
+{
+       unsigned long l = lcm(a, b);
+
+       if (l)
+               return l;
+
+       return (b ? : a);
+}
+EXPORT_SYMBOL_GPL(lcm_not_zero);
diff --git a/lib/math/prime_numbers.c b/lib/math/prime_numbers.c
new file mode 100644 (file)
index 0000000..550eec4
--- /dev/null
@@ -0,0 +1,315 @@
+#define pr_fmt(fmt) "prime numbers: " fmt "\n"
+
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/prime_numbers.h>
+#include <linux/slab.h>
+
+#define bitmap_size(nbits) (BITS_TO_LONGS(nbits) * sizeof(unsigned long))
+
+struct primes {
+       struct rcu_head rcu;
+       unsigned long last, sz;
+       unsigned long primes[];
+};
+
+#if BITS_PER_LONG == 64
+static const struct primes small_primes = {
+       .last = 61,
+       .sz = 64,
+       .primes = {
+               BIT(2) |
+               BIT(3) |
+               BIT(5) |
+               BIT(7) |
+               BIT(11) |
+               BIT(13) |
+               BIT(17) |
+               BIT(19) |
+               BIT(23) |
+               BIT(29) |
+               BIT(31) |
+               BIT(37) |
+               BIT(41) |
+               BIT(43) |
+               BIT(47) |
+               BIT(53) |
+               BIT(59) |
+               BIT(61)
+       }
+};
+#elif BITS_PER_LONG == 32
+static const struct primes small_primes = {
+       .last = 31,
+       .sz = 32,
+       .primes = {
+               BIT(2) |
+               BIT(3) |
+               BIT(5) |
+               BIT(7) |
+               BIT(11) |
+               BIT(13) |
+               BIT(17) |
+               BIT(19) |
+               BIT(23) |
+               BIT(29) |
+               BIT(31)
+       }
+};
+#else
+#error "unhandled BITS_PER_LONG"
+#endif
+
+static DEFINE_MUTEX(lock);
+static const struct primes __rcu *primes = RCU_INITIALIZER(&small_primes);
+
+static unsigned long selftest_max;
+
+static bool slow_is_prime_number(unsigned long x)
+{
+       unsigned long y = int_sqrt(x);
+
+       while (y > 1) {
+               if ((x % y) == 0)
+                       break;
+               y--;
+       }
+
+       return y == 1;
+}
+
+static unsigned long slow_next_prime_number(unsigned long x)
+{
+       while (x < ULONG_MAX && !slow_is_prime_number(++x))
+               ;
+
+       return x;
+}
+
+static unsigned long clear_multiples(unsigned long x,
+                                    unsigned long *p,
+                                    unsigned long start,
+                                    unsigned long end)
+{
+       unsigned long m;
+
+       m = 2 * x;
+       if (m < start)
+               m = roundup(start, x);
+
+       while (m < end) {
+               __clear_bit(m, p);
+               m += x;
+       }
+
+       return x;
+}
+
+static bool expand_to_next_prime(unsigned long x)
+{
+       const struct primes *p;
+       struct primes *new;
+       unsigned long sz, y;
+
+       /* Betrand's Postulate (or Chebyshev's theorem) states that if n > 3,
+        * there is always at least one prime p between n and 2n - 2.
+        * Equivalently, if n > 1, then there is always at least one prime p
+        * such that n < p < 2n.
+        *
+        * http://mathworld.wolfram.com/BertrandsPostulate.html
+        * https://en.wikipedia.org/wiki/Bertrand's_postulate
+        */
+       sz = 2 * x;
+       if (sz < x)
+               return false;
+
+       sz = round_up(sz, BITS_PER_LONG);
+       new = kmalloc(sizeof(*new) + bitmap_size(sz),
+                     GFP_KERNEL | __GFP_NOWARN);
+       if (!new)
+               return false;
+
+       mutex_lock(&lock);
+       p = rcu_dereference_protected(primes, lockdep_is_held(&lock));
+       if (x < p->last) {
+               kfree(new);
+               goto unlock;
+       }
+
+       /* Where memory permits, track the primes using the
+        * Sieve of Eratosthenes. The sieve is to remove all multiples of known
+        * primes from the set, what remains in the set is therefore prime.
+        */
+       bitmap_fill(new->primes, sz);
+       bitmap_copy(new->primes, p->primes, p->sz);
+       for (y = 2UL; y < sz; y = find_next_bit(new->primes, sz, y + 1))
+               new->last = clear_multiples(y, new->primes, p->sz, sz);
+       new->sz = sz;
+
+       BUG_ON(new->last <= x);
+
+       rcu_assign_pointer(primes, new);
+       if (p != &small_primes)
+               kfree_rcu((struct primes *)p, rcu);
+
+unlock:
+       mutex_unlock(&lock);
+       return true;
+}
+
+static void free_primes(void)
+{
+       const struct primes *p;
+
+       mutex_lock(&lock);
+       p = rcu_dereference_protected(primes, lockdep_is_held(&lock));
+       if (p != &small_primes) {
+               rcu_assign_pointer(primes, &small_primes);
+               kfree_rcu((struct primes *)p, rcu);
+       }
+       mutex_unlock(&lock);
+}
+
+/**
+ * next_prime_number - return the next prime number
+ * @x: the starting point for searching to test
+ *
+ * A prime number is an integer greater than 1 that is only divisible by
+ * itself and 1.  The set of prime numbers is computed using the Sieve of
+ * Eratoshenes (on finding a prime, all multiples of that prime are removed
+ * from the set) enabling a fast lookup of the next prime number larger than
+ * @x. If the sieve fails (memory limitation), the search falls back to using
+ * slow trial-divison, up to the value of ULONG_MAX (which is reported as the
+ * final prime as a sentinel).
+ *
+ * Returns: the next prime number larger than @x
+ */
+unsigned long next_prime_number(unsigned long x)
+{
+       const struct primes *p;
+
+       rcu_read_lock();
+       p = rcu_dereference(primes);
+       while (x >= p->last) {
+               rcu_read_unlock();
+
+               if (!expand_to_next_prime(x))
+                       return slow_next_prime_number(x);
+
+               rcu_read_lock();
+               p = rcu_dereference(primes);
+       }
+       x = find_next_bit(p->primes, p->last, x + 1);
+       rcu_read_unlock();
+
+       return x;
+}
+EXPORT_SYMBOL(next_prime_number);
+
+/**
+ * is_prime_number - test whether the given number is prime
+ * @x: the number to test
+ *
+ * A prime number is an integer greater than 1 that is only divisible by
+ * itself and 1. Internally a cache of prime numbers is kept (to speed up
+ * searching for sequential primes, see next_prime_number()), but if the number
+ * falls outside of that cache, its primality is tested using trial-divison.
+ *
+ * Returns: true if @x is prime, false for composite numbers.
+ */
+bool is_prime_number(unsigned long x)
+{
+       const struct primes *p;
+       bool result;
+
+       rcu_read_lock();
+       p = rcu_dereference(primes);
+       while (x >= p->sz) {
+               rcu_read_unlock();
+
+               if (!expand_to_next_prime(x))
+                       return slow_is_prime_number(x);
+
+               rcu_read_lock();
+               p = rcu_dereference(primes);
+       }
+       result = test_bit(x, p->primes);
+       rcu_read_unlock();
+
+       return result;
+}
+EXPORT_SYMBOL(is_prime_number);
+
+static void dump_primes(void)
+{
+       const struct primes *p;
+       char *buf;
+
+       buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+
+       rcu_read_lock();
+       p = rcu_dereference(primes);
+
+       if (buf)
+               bitmap_print_to_pagebuf(true, buf, p->primes, p->sz);
+       pr_info("primes.{last=%lu, .sz=%lu, .primes[]=...x%lx} = %s",
+               p->last, p->sz, p->primes[BITS_TO_LONGS(p->sz) - 1], buf);
+
+       rcu_read_unlock();
+
+       kfree(buf);
+}
+
+static int selftest(unsigned long max)
+{
+       unsigned long x, last;
+
+       if (!max)
+               return 0;
+
+       for (last = 0, x = 2; x < max; x++) {
+               bool slow = slow_is_prime_number(x);
+               bool fast = is_prime_number(x);
+
+               if (slow != fast) {
+                       pr_err("inconsistent result for is-prime(%lu): slow=%s, fast=%s!",
+                              x, slow ? "yes" : "no", fast ? "yes" : "no");
+                       goto err;
+               }
+
+               if (!slow)
+                       continue;
+
+               if (next_prime_number(last) != x) {
+                       pr_err("incorrect result for next-prime(%lu): expected %lu, got %lu",
+                              last, x, next_prime_number(last));
+                       goto err;
+               }
+               last = x;
+       }
+
+       pr_info("selftest(%lu) passed, last prime was %lu", x, last);
+       return 0;
+
+err:
+       dump_primes();
+       return -EINVAL;
+}
+
+static int __init primes_init(void)
+{
+       return selftest(selftest_max);
+}
+
+static void __exit primes_exit(void)
+{
+       free_primes();
+}
+
+module_init(primes_init);
+module_exit(primes_exit);
+
+module_param_named(selftest, selftest_max, ulong, 0400);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL");
diff --git a/lib/math/rational.c b/lib/math/rational.c
new file mode 100644 (file)
index 0000000..ba74436
--- /dev/null
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rational fractions
+ *
+ * Copyright (C) 2009 emlix GmbH, Oskar Schirmer <oskar@scara.com>
+ *
+ * helper functions when coping with rational numbers
+ */
+
+#include <linux/rational.h>
+#include <linux/compiler.h>
+#include <linux/export.h>
+
+/*
+ * calculate best rational approximation for a given fraction
+ * taking into account restricted register size, e.g. to find
+ * appropriate values for a pll with 5 bit denominator and
+ * 8 bit numerator register fields, trying to set up with a
+ * frequency ratio of 3.1415, one would say:
+ *
+ * rational_best_approximation(31415, 10000,
+ *             (1 << 8) - 1, (1 << 5) - 1, &n, &d);
+ *
+ * you may look at given_numerator as a fixed point number,
+ * with the fractional part size described in given_denominator.
+ *
+ * for theoretical background, see:
+ * http://en.wikipedia.org/wiki/Continued_fraction
+ */
+
+void rational_best_approximation(
+       unsigned long given_numerator, unsigned long given_denominator,
+       unsigned long max_numerator, unsigned long max_denominator,
+       unsigned long *best_numerator, unsigned long *best_denominator)
+{
+       unsigned long n, d, n0, d0, n1, d1;
+       n = given_numerator;
+       d = given_denominator;
+       n0 = d1 = 0;
+       n1 = d0 = 1;
+       for (;;) {
+               unsigned long t, a;
+               if ((n1 > max_numerator) || (d1 > max_denominator)) {
+                       n1 = n0;
+                       d1 = d0;
+                       break;
+               }
+               if (d == 0)
+                       break;
+               t = d;
+               a = n / d;
+               d = n % d;
+               n = t;
+               t = n0 + a * n1;
+               n0 = n1;
+               n1 = t;
+               t = d0 + a * d1;
+               d0 = d1;
+               d1 = t;
+       }
+       *best_numerator = n1;
+       *best_denominator = d1;
+}
+
+EXPORT_SYMBOL(rational_best_approximation);
diff --git a/lib/math/reciprocal_div.c b/lib/math/reciprocal_div.c
new file mode 100644 (file)
index 0000000..bf04325
--- /dev/null
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <asm/div64.h>
+#include <linux/reciprocal_div.h>
+#include <linux/export.h>
+
+/*
+ * For a description of the algorithm please have a look at
+ * include/linux/reciprocal_div.h
+ */
+
+struct reciprocal_value reciprocal_value(u32 d)
+{
+       struct reciprocal_value R;
+       u64 m;
+       int l;
+
+       l = fls(d - 1);
+       m = ((1ULL << 32) * ((1ULL << l) - d));
+       do_div(m, d);
+       ++m;
+       R.m = (u32)m;
+       R.sh1 = min(l, 1);
+       R.sh2 = max(l - 1, 0);
+
+       return R;
+}
+EXPORT_SYMBOL(reciprocal_value);
+
+struct reciprocal_value_adv reciprocal_value_adv(u32 d, u8 prec)
+{
+       struct reciprocal_value_adv R;
+       u32 l, post_shift;
+       u64 mhigh, mlow;
+
+       /* ceil(log2(d)) */
+       l = fls(d - 1);
+       /* NOTE: mlow/mhigh could overflow u64 when l == 32. This case needs to
+        * be handled before calling "reciprocal_value_adv", please see the
+        * comment at include/linux/reciprocal_div.h.
+        */
+       WARN(l == 32,
+            "ceil(log2(0x%08x)) == 32, %s doesn't support such divisor",
+            d, __func__);
+       post_shift = l;
+       mlow = 1ULL << (32 + l);
+       do_div(mlow, d);
+       mhigh = (1ULL << (32 + l)) + (1ULL << (32 + l - prec));
+       do_div(mhigh, d);
+
+       for (; post_shift > 0; post_shift--) {
+               u64 lo = mlow >> 1, hi = mhigh >> 1;
+
+               if (lo >= hi)
+                       break;
+
+               mlow = lo;
+               mhigh = hi;
+       }
+
+       R.m = (u32)mhigh;
+       R.sh = post_shift;
+       R.exp = l;
+       R.is_wide_m = mhigh > U32_MAX;
+
+       return R;
+}
+EXPORT_SYMBOL(reciprocal_value_adv);
index 199408f..d3bd882 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/bug.h>
 #include <linux/plist.h>
 
-#ifdef CONFIG_DEBUG_PI_LIST
+#ifdef CONFIG_DEBUG_PLIST
 
 static struct plist_head test_head;
 
@@ -173,7 +173,7 @@ void plist_requeue(struct plist_node *node, struct plist_head *head)
        plist_check_head(head);
 }
 
-#ifdef CONFIG_DEBUG_PI_LIST
+#ifdef CONFIG_DEBUG_PLIST
 #include <linux/sched.h>
 #include <linux/sched/clock.h>
 #include <linux/module.h>
diff --git a/lib/prime_numbers.c b/lib/prime_numbers.c
deleted file mode 100644 (file)
index 550eec4..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-#define pr_fmt(fmt) "prime numbers: " fmt "\n"
-
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/prime_numbers.h>
-#include <linux/slab.h>
-
-#define bitmap_size(nbits) (BITS_TO_LONGS(nbits) * sizeof(unsigned long))
-
-struct primes {
-       struct rcu_head rcu;
-       unsigned long last, sz;
-       unsigned long primes[];
-};
-
-#if BITS_PER_LONG == 64
-static const struct primes small_primes = {
-       .last = 61,
-       .sz = 64,
-       .primes = {
-               BIT(2) |
-               BIT(3) |
-               BIT(5) |
-               BIT(7) |
-               BIT(11) |
-               BIT(13) |
-               BIT(17) |
-               BIT(19) |
-               BIT(23) |
-               BIT(29) |
-               BIT(31) |
-               BIT(37) |
-               BIT(41) |
-               BIT(43) |
-               BIT(47) |
-               BIT(53) |
-               BIT(59) |
-               BIT(61)
-       }
-};
-#elif BITS_PER_LONG == 32
-static const struct primes small_primes = {
-       .last = 31,
-       .sz = 32,
-       .primes = {
-               BIT(2) |
-               BIT(3) |
-               BIT(5) |
-               BIT(7) |
-               BIT(11) |
-               BIT(13) |
-               BIT(17) |
-               BIT(19) |
-               BIT(23) |
-               BIT(29) |
-               BIT(31)
-       }
-};
-#else
-#error "unhandled BITS_PER_LONG"
-#endif
-
-static DEFINE_MUTEX(lock);
-static const struct primes __rcu *primes = RCU_INITIALIZER(&small_primes);
-
-static unsigned long selftest_max;
-
-static bool slow_is_prime_number(unsigned long x)
-{
-       unsigned long y = int_sqrt(x);
-
-       while (y > 1) {
-               if ((x % y) == 0)
-                       break;
-               y--;
-       }
-
-       return y == 1;
-}
-
-static unsigned long slow_next_prime_number(unsigned long x)
-{
-       while (x < ULONG_MAX && !slow_is_prime_number(++x))
-               ;
-
-       return x;
-}
-
-static unsigned long clear_multiples(unsigned long x,
-                                    unsigned long *p,
-                                    unsigned long start,
-                                    unsigned long end)
-{
-       unsigned long m;
-
-       m = 2 * x;
-       if (m < start)
-               m = roundup(start, x);
-
-       while (m < end) {
-               __clear_bit(m, p);
-               m += x;
-       }
-
-       return x;
-}
-
-static bool expand_to_next_prime(unsigned long x)
-{
-       const struct primes *p;
-       struct primes *new;
-       unsigned long sz, y;
-
-       /* Betrand's Postulate (or Chebyshev's theorem) states that if n > 3,
-        * there is always at least one prime p between n and 2n - 2.
-        * Equivalently, if n > 1, then there is always at least one prime p
-        * such that n < p < 2n.
-        *
-        * http://mathworld.wolfram.com/BertrandsPostulate.html
-        * https://en.wikipedia.org/wiki/Bertrand's_postulate
-        */
-       sz = 2 * x;
-       if (sz < x)
-               return false;
-
-       sz = round_up(sz, BITS_PER_LONG);
-       new = kmalloc(sizeof(*new) + bitmap_size(sz),
-                     GFP_KERNEL | __GFP_NOWARN);
-       if (!new)
-               return false;
-
-       mutex_lock(&lock);
-       p = rcu_dereference_protected(primes, lockdep_is_held(&lock));
-       if (x < p->last) {
-               kfree(new);
-               goto unlock;
-       }
-
-       /* Where memory permits, track the primes using the
-        * Sieve of Eratosthenes. The sieve is to remove all multiples of known
-        * primes from the set, what remains in the set is therefore prime.
-        */
-       bitmap_fill(new->primes, sz);
-       bitmap_copy(new->primes, p->primes, p->sz);
-       for (y = 2UL; y < sz; y = find_next_bit(new->primes, sz, y + 1))
-               new->last = clear_multiples(y, new->primes, p->sz, sz);
-       new->sz = sz;
-
-       BUG_ON(new->last <= x);
-
-       rcu_assign_pointer(primes, new);
-       if (p != &small_primes)
-               kfree_rcu((struct primes *)p, rcu);
-
-unlock:
-       mutex_unlock(&lock);
-       return true;
-}
-
-static void free_primes(void)
-{
-       const struct primes *p;
-
-       mutex_lock(&lock);
-       p = rcu_dereference_protected(primes, lockdep_is_held(&lock));
-       if (p != &small_primes) {
-               rcu_assign_pointer(primes, &small_primes);
-               kfree_rcu((struct primes *)p, rcu);
-       }
-       mutex_unlock(&lock);
-}
-
-/**
- * next_prime_number - return the next prime number
- * @x: the starting point for searching to test
- *
- * A prime number is an integer greater than 1 that is only divisible by
- * itself and 1.  The set of prime numbers is computed using the Sieve of
- * Eratoshenes (on finding a prime, all multiples of that prime are removed
- * from the set) enabling a fast lookup of the next prime number larger than
- * @x. If the sieve fails (memory limitation), the search falls back to using
- * slow trial-divison, up to the value of ULONG_MAX (which is reported as the
- * final prime as a sentinel).
- *
- * Returns: the next prime number larger than @x
- */
-unsigned long next_prime_number(unsigned long x)
-{
-       const struct primes *p;
-
-       rcu_read_lock();
-       p = rcu_dereference(primes);
-       while (x >= p->last) {
-               rcu_read_unlock();
-
-               if (!expand_to_next_prime(x))
-                       return slow_next_prime_number(x);
-
-               rcu_read_lock();
-               p = rcu_dereference(primes);
-       }
-       x = find_next_bit(p->primes, p->last, x + 1);
-       rcu_read_unlock();
-
-       return x;
-}
-EXPORT_SYMBOL(next_prime_number);
-
-/**
- * is_prime_number - test whether the given number is prime
- * @x: the number to test
- *
- * A prime number is an integer greater than 1 that is only divisible by
- * itself and 1. Internally a cache of prime numbers is kept (to speed up
- * searching for sequential primes, see next_prime_number()), but if the number
- * falls outside of that cache, its primality is tested using trial-divison.
- *
- * Returns: true if @x is prime, false for composite numbers.
- */
-bool is_prime_number(unsigned long x)
-{
-       const struct primes *p;
-       bool result;
-
-       rcu_read_lock();
-       p = rcu_dereference(primes);
-       while (x >= p->sz) {
-               rcu_read_unlock();
-
-               if (!expand_to_next_prime(x))
-                       return slow_is_prime_number(x);
-
-               rcu_read_lock();
-               p = rcu_dereference(primes);
-       }
-       result = test_bit(x, p->primes);
-       rcu_read_unlock();
-
-       return result;
-}
-EXPORT_SYMBOL(is_prime_number);
-
-static void dump_primes(void)
-{
-       const struct primes *p;
-       char *buf;
-
-       buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-
-       rcu_read_lock();
-       p = rcu_dereference(primes);
-
-       if (buf)
-               bitmap_print_to_pagebuf(true, buf, p->primes, p->sz);
-       pr_info("primes.{last=%lu, .sz=%lu, .primes[]=...x%lx} = %s",
-               p->last, p->sz, p->primes[BITS_TO_LONGS(p->sz) - 1], buf);
-
-       rcu_read_unlock();
-
-       kfree(buf);
-}
-
-static int selftest(unsigned long max)
-{
-       unsigned long x, last;
-
-       if (!max)
-               return 0;
-
-       for (last = 0, x = 2; x < max; x++) {
-               bool slow = slow_is_prime_number(x);
-               bool fast = is_prime_number(x);
-
-               if (slow != fast) {
-                       pr_err("inconsistent result for is-prime(%lu): slow=%s, fast=%s!",
-                              x, slow ? "yes" : "no", fast ? "yes" : "no");
-                       goto err;
-               }
-
-               if (!slow)
-                       continue;
-
-               if (next_prime_number(last) != x) {
-                       pr_err("incorrect result for next-prime(%lu): expected %lu, got %lu",
-                              last, x, next_prime_number(last));
-                       goto err;
-               }
-               last = x;
-       }
-
-       pr_info("selftest(%lu) passed, last prime was %lu", x, last);
-       return 0;
-
-err:
-       dump_primes();
-       return -EINVAL;
-}
-
-static int __init primes_init(void)
-{
-       return selftest(selftest_max);
-}
-
-static void __exit primes_exit(void)
-{
-       free_primes();
-}
-
-module_init(primes_init);
-module_exit(primes_exit);
-
-module_param_named(selftest, selftest_max, ulong, 0400);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_LICENSE("GPL");
diff --git a/lib/rational.c b/lib/rational.c
deleted file mode 100644 (file)
index ba74436..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * rational fractions
- *
- * Copyright (C) 2009 emlix GmbH, Oskar Schirmer <oskar@scara.com>
- *
- * helper functions when coping with rational numbers
- */
-
-#include <linux/rational.h>
-#include <linux/compiler.h>
-#include <linux/export.h>
-
-/*
- * calculate best rational approximation for a given fraction
- * taking into account restricted register size, e.g. to find
- * appropriate values for a pll with 5 bit denominator and
- * 8 bit numerator register fields, trying to set up with a
- * frequency ratio of 3.1415, one would say:
- *
- * rational_best_approximation(31415, 10000,
- *             (1 << 8) - 1, (1 << 5) - 1, &n, &d);
- *
- * you may look at given_numerator as a fixed point number,
- * with the fractional part size described in given_denominator.
- *
- * for theoretical background, see:
- * http://en.wikipedia.org/wiki/Continued_fraction
- */
-
-void rational_best_approximation(
-       unsigned long given_numerator, unsigned long given_denominator,
-       unsigned long max_numerator, unsigned long max_denominator,
-       unsigned long *best_numerator, unsigned long *best_denominator)
-{
-       unsigned long n, d, n0, d0, n1, d1;
-       n = given_numerator;
-       d = given_denominator;
-       n0 = d1 = 0;
-       n1 = d0 = 1;
-       for (;;) {
-               unsigned long t, a;
-               if ((n1 > max_numerator) || (d1 > max_denominator)) {
-                       n1 = n0;
-                       d1 = d0;
-                       break;
-               }
-               if (d == 0)
-                       break;
-               t = d;
-               a = n / d;
-               d = n % d;
-               n = t;
-               t = n0 + a * n1;
-               n0 = n1;
-               n1 = t;
-               t = d0 + a * d1;
-               d0 = d1;
-               d1 = t;
-       }
-       *best_numerator = n1;
-       *best_denominator = d1;
-}
-
-EXPORT_SYMBOL(rational_best_approximation);
diff --git a/lib/reciprocal_div.c b/lib/reciprocal_div.c
deleted file mode 100644 (file)
index bf04325..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/bug.h>
-#include <linux/kernel.h>
-#include <asm/div64.h>
-#include <linux/reciprocal_div.h>
-#include <linux/export.h>
-
-/*
- * For a description of the algorithm please have a look at
- * include/linux/reciprocal_div.h
- */
-
-struct reciprocal_value reciprocal_value(u32 d)
-{
-       struct reciprocal_value R;
-       u64 m;
-       int l;
-
-       l = fls(d - 1);
-       m = ((1ULL << 32) * ((1ULL << l) - d));
-       do_div(m, d);
-       ++m;
-       R.m = (u32)m;
-       R.sh1 = min(l, 1);
-       R.sh2 = max(l - 1, 0);
-
-       return R;
-}
-EXPORT_SYMBOL(reciprocal_value);
-
-struct reciprocal_value_adv reciprocal_value_adv(u32 d, u8 prec)
-{
-       struct reciprocal_value_adv R;
-       u32 l, post_shift;
-       u64 mhigh, mlow;
-
-       /* ceil(log2(d)) */
-       l = fls(d - 1);
-       /* NOTE: mlow/mhigh could overflow u64 when l == 32. This case needs to
-        * be handled before calling "reciprocal_value_adv", please see the
-        * comment at include/linux/reciprocal_div.h.
-        */
-       WARN(l == 32,
-            "ceil(log2(0x%08x)) == 32, %s doesn't support such divisor",
-            d, __func__);
-       post_shift = l;
-       mlow = 1ULL << (32 + l);
-       do_div(mlow, d);
-       mhigh = (1ULL << (32 + l)) + (1ULL << (32 + l - prec));
-       do_div(mhigh, d);
-
-       for (; post_shift > 0; post_shift--) {
-               u64 lo = mlow >> 1, hi = mhigh >> 1;
-
-               if (lo >= hi)
-                       break;
-
-               mlow = lo;
-               mhigh = hi;
-       }
-
-       R.m = (u32)mhigh;
-       R.sh = post_shift;
-       R.exp = l;
-       R.is_wide_m = mhigh > U32_MAX;
-
-       return R;
-}
-EXPORT_SYMBOL(reciprocal_value_adv);
index d6b7a20..50855ea 100644 (file)
@@ -1,8 +1,13 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * A fast, small, non-recursive O(nlog n) sort for the Linux kernel
+ * A fast, small, non-recursive O(n log n) sort for the Linux kernel
  *
- * Jan 23 2005  Matt Mackall <mpm@selenic.com>
+ * This performs n*log2(n) + 0.37*n + o(n) comparisons on average,
+ * and 1.5*n*log2(n) + O(n) in the (very contrived) worst case.
+ *
+ * Glibc qsort() manages n*log2(n) - 1.26*n for random inputs (1.63*n
+ * better) at the expense of stack usage and much larger code to avoid
+ * quicksort's O(n^2) worst case.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/export.h>
 #include <linux/sort.h>
 
-static int alignment_ok(const void *base, int align)
+/**
+ * is_aligned - is this pointer & size okay for word-wide copying?
+ * @base: pointer to data
+ * @size: size of each element
+ * @align: required alignment (typically 4 or 8)
+ *
+ * Returns true if elements can be copied using word loads and stores.
+ * The size must be a multiple of the alignment, and the base address must
+ * be if we do not have CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS.
+ *
+ * For some reason, gcc doesn't know to optimize "if (a & mask || b & mask)"
+ * to "if ((a | b) & mask)", so we do that by hand.
+ */
+__attribute_const__ __always_inline
+static bool is_aligned(const void *base, size_t size, unsigned char align)
 {
-       return IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ||
-               ((unsigned long)base & (align - 1)) == 0;
+       unsigned char lsbits = (unsigned char)size;
+
+       (void)base;
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+       lsbits |= (unsigned char)(uintptr_t)base;
+#endif
+       return (lsbits & (align - 1)) == 0;
 }
 
-static void u32_swap(void *a, void *b, int size)
+/**
+ * swap_words_32 - swap two elements in 32-bit chunks
+ * @a, @b: pointers to the elements
+ * @size: element size (must be a multiple of 4)
+ *
+ * Exchange the two objects in memory.  This exploits base+index addressing,
+ * which basically all CPUs have, to minimize loop overhead computations.
+ *
+ * For some reason, on x86 gcc 7.3.0 adds a redundant test of n at the
+ * bottom of the loop, even though the zero flag is stil valid from the
+ * subtract (since the intervening mov instructions don't alter the flags).
+ * Gcc 8.1.0 doesn't have that problem.
+ */
+static void swap_words_32(void *a, void *b, size_t n)
 {
-       u32 t = *(u32 *)a;
-       *(u32 *)a = *(u32 *)b;
-       *(u32 *)b = t;
+       do {
+               u32 t = *(u32 *)(a + (n -= 4));
+               *(u32 *)(a + n) = *(u32 *)(b + n);
+               *(u32 *)(b + n) = t;
+       } while (n);
 }
 
-static void u64_swap(void *a, void *b, int size)
+/**
+ * swap_words_64 - swap two elements in 64-bit chunks
+ * @a, @b: pointers to the elements
+ * @size: element size (must be a multiple of 8)
+ *
+ * Exchange the two objects in memory.  This exploits base+index
+ * addressing, which basically all CPUs have, to minimize loop overhead
+ * computations.
+ *
+ * We'd like to use 64-bit loads if possible.  If they're not, emulating
+ * one requires base+index+4 addressing which x86 has but most other
+ * processors do not.  If CONFIG_64BIT, we definitely have 64-bit loads,
+ * but it's possible to have 64-bit loads without 64-bit pointers (e.g.
+ * x32 ABI).  Are there any cases the kernel needs to worry about?
+ */
+static void swap_words_64(void *a, void *b, size_t n)
 {
-       u64 t = *(u64 *)a;
-       *(u64 *)a = *(u64 *)b;
-       *(u64 *)b = t;
+       do {
+#ifdef CONFIG_64BIT
+               u64 t = *(u64 *)(a + (n -= 8));
+               *(u64 *)(a + n) = *(u64 *)(b + n);
+               *(u64 *)(b + n) = t;
+#else
+               /* Use two 32-bit transfers to avoid base+index+4 addressing */
+               u32 t = *(u32 *)(a + (n -= 4));
+               *(u32 *)(a + n) = *(u32 *)(b + n);
+               *(u32 *)(b + n) = t;
+
+               t = *(u32 *)(a + (n -= 4));
+               *(u32 *)(a + n) = *(u32 *)(b + n);
+               *(u32 *)(b + n) = t;
+#endif
+       } while (n);
 }
 
-static void generic_swap(void *a, void *b, int size)
+/**
+ * swap_bytes - swap two elements a byte at a time
+ * @a, @b: pointers to the elements
+ * @size: element size
+ *
+ * This is the fallback if alignment doesn't allow using larger chunks.
+ */
+static void swap_bytes(void *a, void *b, size_t n)
 {
-       char t;
-
        do {
-               t = *(char *)a;
-               *(char *)a++ = *(char *)b;
-               *(char *)b++ = t;
-       } while (--size > 0);
+               char t = ((char *)a)[--n];
+               ((char *)a)[n] = ((char *)b)[n];
+               ((char *)b)[n] = t;
+       } while (n);
+}
+
+typedef void (*swap_func_t)(void *a, void *b, int size);
+
+/*
+ * The values are arbitrary as long as they can't be confused with
+ * a pointer, but small integers make for the smallest compare
+ * instructions.
+ */
+#define SWAP_WORDS_64 (swap_func_t)0
+#define SWAP_WORDS_32 (swap_func_t)1
+#define SWAP_BYTES    (swap_func_t)2
+
+/*
+ * The function pointer is last to make tail calls most efficient if the
+ * compiler decides not to inline this function.
+ */
+static void do_swap(void *a, void *b, size_t size, swap_func_t swap_func)
+{
+       if (swap_func == SWAP_WORDS_64)
+               swap_words_64(a, b, size);
+       else if (swap_func == SWAP_WORDS_32)
+               swap_words_32(a, b, size);
+       else if (swap_func == SWAP_BYTES)
+               swap_bytes(a, b, size);
+       else
+               swap_func(a, b, (int)size);
+}
+
+/**
+ * parent - given the offset of the child, find the offset of the parent.
+ * @i: the offset of the heap element whose parent is sought.  Non-zero.
+ * @lsbit: a precomputed 1-bit mask, equal to "size & -size"
+ * @size: size of each element
+ *
+ * In terms of array indexes, the parent of element j = @i/@size is simply
+ * (j-1)/2.  But when working in byte offsets, we can't use implicit
+ * truncation of integer divides.
+ *
+ * Fortunately, we only need one bit of the quotient, not the full divide.
+ * @size has a least significant bit.  That bit will be clear if @i is
+ * an even multiple of @size, and set if it's an odd multiple.
+ *
+ * Logically, we're doing "if (i & lsbit) i -= size;", but since the
+ * branch is unpredictable, it's done with a bit of clever branch-free
+ * code instead.
+ */
+__attribute_const__ __always_inline
+static size_t parent(size_t i, unsigned int lsbit, size_t size)
+{
+       i -= size;
+       i -= size & -(i & lsbit);
+       return i / 2;
 }
 
 /**
@@ -50,57 +175,78 @@ static void generic_swap(void *a, void *b, int size)
  * @cmp_func: pointer to comparison function
  * @swap_func: pointer to swap function or NULL
  *
- * This function does a heapsort on the given array. You may provide a
- * swap_func function optimized to your element type.
+ * This function does a heapsort on the given array.  You may provide
+ * a swap_func function if you need to do something more than a memory
+ * copy (e.g. fix up pointers or auxiliary data), but the built-in swap
+ * avoids a slow retpoline and so is significantly faster.
  *
  * Sorting time is O(n log n) both on average and worst-case. While
- * qsort is about 20% faster on average, it suffers from exploitable
+ * quicksort is slightly faster on average, it suffers from exploitable
  * O(n*n) worst-case behavior and extra memory requirements that make
  * it less suitable for kernel use.
  */
-
 void sort(void *base, size_t num, size_t size,
          int (*cmp_func)(const void *, const void *),
          void (*swap_func)(void *, void *, int size))
 {
        /* pre-scale counters for performance */
-       int i = (num/2 - 1) * size, n = num * size, c, r;
+       size_t n = num * size, a = (num/2) * size;
+       const unsigned int lsbit = size & -size;  /* Used to find parent */
+
+       if (!a)         /* num < 2 || size == 0 */
+               return;
 
        if (!swap_func) {
-               if (size == 4 && alignment_ok(base, 4))
-                       swap_func = u32_swap;
-               else if (size == 8 && alignment_ok(base, 8))
-                       swap_func = u64_swap;
+               if (is_aligned(base, size, 8))
+                       swap_func = SWAP_WORDS_64;
+               else if (is_aligned(base, size, 4))
+                       swap_func = SWAP_WORDS_32;
                else
-                       swap_func = generic_swap;
+                       swap_func = SWAP_BYTES;
        }
 
-       /* heapify */
-       for ( ; i >= 0; i -= size) {
-               for (r = i; r * 2 + size < n; r  = c) {
-                       c = r * 2 + size;
-                       if (c < n - size &&
-                                       cmp_func(base + c, base + c + size) < 0)
-                               c += size;
-                       if (cmp_func(base + r, base + c) >= 0)
-                               break;
-                       swap_func(base + r, base + c, size);
-               }
-       }
+       /*
+        * Loop invariants:
+        * 1. elements [a,n) satisfy the heap property (compare greater than
+        *    all of their children),
+        * 2. elements [n,num*size) are sorted, and
+        * 3. a <= b <= c <= d <= n (whenever they are valid).
+        */
+       for (;;) {
+               size_t b, c, d;
+
+               if (a)                  /* Building heap: sift down --a */
+                       a -= size;
+               else if (n -= size)     /* Sorting: Extract root to --n */
+                       do_swap(base, base + n, size, swap_func);
+               else                    /* Sort complete */
+                       break;
 
-       /* sort */
-       for (i = n - size; i > 0; i -= size) {
-               swap_func(base, base + i, size);
-               for (r = 0; r * 2 + size < i; r = c) {
-                       c = r * 2 + size;
-                       if (c < i - size &&
-                                       cmp_func(base + c, base + c + size) < 0)
-                               c += size;
-                       if (cmp_func(base + r, base + c) >= 0)
-                               break;
-                       swap_func(base + r, base + c, size);
+               /*
+                * Sift element at "a" down into heap.  This is the
+                * "bottom-up" variant, which significantly reduces
+                * calls to cmp_func(): we find the sift-down path all
+                * the way to the leaves (one compare per level), then
+                * backtrack to find where to insert the target element.
+                *
+                * Because elements tend to sift down close to the leaves,
+                * this uses fewer compares than doing two per level
+                * on the way down.  (A bit more than half as many on
+                * average, 3/4 worst-case.)
+                */
+               for (b = a; c = 2*b + size, (d = c + size) < n;)
+                       b = cmp_func(base + c, base + d) >= 0 ? c : d;
+               if (d == n)     /* Special case last leaf with no sibling */
+                       b = c;
+
+               /* Now backtrack from "b" to the correct location for "a" */
+               while (b != a && cmp_func(base + a, base + b) >= 0)
+                       b = parent(b, lsbit, size);
+               c = b;                  /* Where "a" belongs */
+               while (b != a) {        /* Shift it into place */
+                       b = parent(b, lsbit, size);
+                       do_swap(base + b, base + c, size, swap_func);
                }
        }
 }
-
 EXPORT_SYMBOL(sort);
index 792d906..d3a501f 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/printk.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/uaccess.h>
 
 #include "../tools/testing/selftests/kselftest_module.h"
 
@@ -226,7 +227,8 @@ static const unsigned long exp[] __initconst = {
        BITMAP_FROM_U64(0xffffffff),
        BITMAP_FROM_U64(0xfffffffe),
        BITMAP_FROM_U64(0x3333333311111111ULL),
-       BITMAP_FROM_U64(0xffffffff77777777ULL)
+       BITMAP_FROM_U64(0xffffffff77777777ULL),
+       BITMAP_FROM_U64(0),
 };
 
 static const unsigned long exp2[] __initconst = {
@@ -249,55 +251,93 @@ static const struct test_bitmap_parselist parselist_tests[] __initconst = {
        {0, "1-31:4/4",                 &exp[9 * step], 32, 0},
        {0, "0-31:1/4,32-63:2/4",       &exp[10 * step], 64, 0},
        {0, "0-31:3/4,32-63:4/4",       &exp[11 * step], 64, 0},
+       {0, "  ,,  0-31:3/4  ,, 32-63:4/4  ,,  ",       &exp[11 * step], 64, 0},
 
        {0, "0-31:1/4,32-63:2/4,64-95:3/4,96-127:4/4",  exp2, 128, 0},
 
        {0, "0-2047:128/256", NULL, 2048, PARSE_TIME},
 
+       {0, "",                         &exp[12 * step], 8, 0},
+       {0, "\n",                       &exp[12 * step], 8, 0},
+       {0, ",,  ,,  , ,  ,",           &exp[12 * step], 8, 0},
+       {0, " ,  ,,  , ,   ",           &exp[12 * step], 8, 0},
+       {0, " ,  ,,  , ,   \n",         &exp[12 * step], 8, 0},
+
        {-EINVAL, "-1", NULL, 8, 0},
        {-EINVAL, "-0", NULL, 8, 0},
        {-EINVAL, "10-1", NULL, 8, 0},
        {-EINVAL, "0-31:", NULL, 8, 0},
        {-EINVAL, "0-31:0", NULL, 8, 0},
+       {-EINVAL, "0-31:0/", NULL, 8, 0},
        {-EINVAL, "0-31:0/0", NULL, 8, 0},
        {-EINVAL, "0-31:1/0", NULL, 8, 0},
        {-EINVAL, "0-31:10/1", NULL, 8, 0},
+       {-EOVERFLOW, "0-98765432123456789:10/1", NULL, 8, 0},
+
+       {-EINVAL, "a-31", NULL, 8, 0},
+       {-EINVAL, "0-a1", NULL, 8, 0},
+       {-EINVAL, "a-31:10/1", NULL, 8, 0},
+       {-EINVAL, "0-31:a/1", NULL, 8, 0},
+       {-EINVAL, "0-\n", NULL, 8, 0},
 };
 
-static void __init test_bitmap_parselist(void)
+static void __init __test_bitmap_parselist(int is_user)
 {
        int i;
        int err;
-       cycles_t cycles;
+       ktime_t time;
        DECLARE_BITMAP(bmap, 2048);
+       char *mode = is_user ? "_user"  : "";
 
        for (i = 0; i < ARRAY_SIZE(parselist_tests); i++) {
 #define ptest parselist_tests[i]
 
-               cycles = get_cycles();
-               err = bitmap_parselist(ptest.in, bmap, ptest.nbits);
-               cycles = get_cycles() - cycles;
+               if (is_user) {
+                       mm_segment_t orig_fs = get_fs();
+                       size_t len = strlen(ptest.in);
+
+                       set_fs(KERNEL_DS);
+                       time = ktime_get();
+                       err = bitmap_parselist_user(ptest.in, len,
+                                                   bmap, ptest.nbits);
+                       time = ktime_get() - time;
+                       set_fs(orig_fs);
+               } else {
+                       time = ktime_get();
+                       err = bitmap_parselist(ptest.in, bmap, ptest.nbits);
+                       time = ktime_get() - time;
+               }
 
                if (err != ptest.errno) {
-                       pr_err("test %d: input is %s, errno is %d, expected %d\n",
-                                       i, ptest.in, err, ptest.errno);
+                       pr_err("parselist%s: %d: input is %s, errno is %d, expected %d\n",
+                                       mode, i, ptest.in, err, ptest.errno);
                        continue;
                }
 
                if (!err && ptest.expected
                         && !__bitmap_equal(bmap, ptest.expected, ptest.nbits)) {
-                       pr_err("test %d: input is %s, result is 0x%lx, expected 0x%lx\n",
-                                       i, ptest.in, bmap[0], *ptest.expected);
+                       pr_err("parselist%s: %d: input is %s, result is 0x%lx, expected 0x%lx\n",
+                                       mode, i, ptest.in, bmap[0],
+                                       *ptest.expected);
                        continue;
                }
 
                if (ptest.flags & PARSE_TIME)
-                       pr_err("test %d: input is '%s' OK, Time: %llu\n",
-                                       i, ptest.in,
-                                       (unsigned long long)cycles);
+                       pr_err("parselist%s: %d: input is '%s' OK, Time: %llu\n",
+                                       mode, i, ptest.in, time);
        }
 }
 
+static void __init test_bitmap_parselist(void)
+{
+       __test_bitmap_parselist(0);
+}
+
+static void __init test_bitmap_parselist_user(void)
+{
+       __test_bitmap_parselist(1);
+}
+
 #define EXP_BYTES      (sizeof(exp) * 8)
 
 static void __init test_bitmap_arr32(void)
@@ -370,6 +410,7 @@ static void __init selftest(void)
        test_copy();
        test_bitmap_arr32();
        test_bitmap_parselist();
+       test_bitmap_parselist_user();
        test_mem_optimisations();
 }
 
index 3dd801c..566dad3 100644 (file)
@@ -47,6 +47,9 @@ struct test_sysctl_data {
        unsigned int uint_0001;
 
        char string_0001[65];
+
+#define SYSCTL_TEST_BITMAP_SIZE        65536
+       unsigned long *bitmap_0001;
 };
 
 static struct test_sysctl_data test_data = {
@@ -102,6 +105,13 @@ static struct ctl_table test_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dostring,
        },
+       {
+               .procname       = "bitmap_0001",
+               .data           = &test_data.bitmap_0001,
+               .maxlen         = SYSCTL_TEST_BITMAP_SIZE,
+               .mode           = 0644,
+               .proc_handler   = proc_do_large_bitmap,
+       },
        { }
 };
 
@@ -129,15 +139,21 @@ static struct ctl_table_header *test_sysctl_header;
 
 static int __init test_sysctl_init(void)
 {
+       test_data.bitmap_0001 = kzalloc(SYSCTL_TEST_BITMAP_SIZE/8, GFP_KERNEL);
+       if (!test_data.bitmap_0001)
+               return -ENOMEM;
        test_sysctl_header = register_sysctl_table(test_sysctl_root_table);
-       if (!test_sysctl_header)
+       if (!test_sysctl_header) {
+               kfree(test_data.bitmap_0001);
                return -ENOMEM;
+       }
        return 0;
 }
 late_initcall(test_sysctl_init);
 
 static void __exit test_sysctl_exit(void)
 {
+       kfree(test_data.bitmap_0001);
        if (test_sysctl_header)
                unregister_sysctl_table(test_sysctl_header);
 }
index f832b09..8bbefca 100644 (file)
@@ -384,12 +384,11 @@ static int test_func(void *private)
 {
        struct test_driver *t = private;
        int random_array[ARRAY_SIZE(test_case_array)];
-       int index, i, j, ret;
+       int index, i, j;
        ktime_t kt;
        u64 delta;
 
-       ret = set_cpus_allowed_ptr(current, cpumask_of(t->cpu));
-       if (ret < 0)
+       if (set_cpus_allowed_ptr(current, cpumask_of(t->cpu)) < 0)
                pr_err("Failed to set affinity to %d CPU\n", t->cpu);
 
        for (i = 0; i < ARRAY_SIZE(test_case_array); i++)
@@ -415,8 +414,7 @@ static int test_func(void *private)
 
                kt = ktime_get();
                for (j = 0; j < test_repeat_count; j++) {
-                       ret = test_case_array[index].test_func();
-                       if (!ret)
+                       if (!test_case_array[index].test_func())
                                per_cpu_test_data[t->cpu][index].test_passed++;
                        else
                                per_cpu_test_data[t->cpu][index].test_failed++;
index 25c71eb..ee8d1f3 100644 (file)
@@ -11,23 +11,24 @@ choice
        default DISCONTIGMEM_MANUAL if ARCH_DISCONTIGMEM_DEFAULT
        default SPARSEMEM_MANUAL if ARCH_SPARSEMEM_DEFAULT
        default FLATMEM_MANUAL
+       help
+         This option allows you to change some of the ways that
+         Linux manages its memory internally. Most users will
+         only have one option here selected by the architecture
+         configuration. This is normal.
 
 config FLATMEM_MANUAL
        bool "Flat Memory"
        depends on !(ARCH_DISCONTIGMEM_ENABLE || ARCH_SPARSEMEM_ENABLE) || ARCH_FLATMEM_ENABLE
        help
-         This option allows you to change some of the ways that
-         Linux manages its memory internally.  Most users will
-         only have one option here: FLATMEM.  This is normal
-         and a correct option.
-
-         Some users of more advanced features like NUMA and
-         memory hotplug may have different options here.
-         DISCONTIGMEM is a more mature, better tested system,
-         but is incompatible with memory hotplug and may suffer
-         decreased performance over SPARSEMEM.  If unsure between
-         "Sparse Memory" and "Discontiguous Memory", choose
-         "Discontiguous Memory".
+         This option is best suited for non-NUMA systems with
+         flat address space. The FLATMEM is the most efficient
+         system in terms of performance and resource consumption
+         and it is the best option for smaller systems.
+
+         For systems that have holes in their physical address
+         spaces and for features like NUMA and memory hotplug,
+         choose "Sparse Memory"
 
          If unsure, choose this option (Flat Memory) over any other.
 
@@ -38,29 +39,26 @@ config DISCONTIGMEM_MANUAL
          This option provides enhanced support for discontiguous
          memory systems, over FLATMEM.  These systems have holes
          in their physical address spaces, and this option provides
-         more efficient handling of these holes.  However, the vast
-         majority of hardware has quite flat address spaces, and
-         can have degraded performance from the extra overhead that
-         this option imposes.
+         more efficient handling of these holes.
 
-         Many NUMA configurations will have this as the only option.
+         Although "Discontiguous Memory" is still used by several
+         architectures, it is considered deprecated in favor of
+         "Sparse Memory".
 
-         If unsure, choose "Flat Memory" over this option.
+         If unsure, choose "Sparse Memory" over this option.
 
 config SPARSEMEM_MANUAL
        bool "Sparse Memory"
        depends on ARCH_SPARSEMEM_ENABLE
        help
          This will be the only option for some systems, including
-         memory hotplug systems.  This is normal.
+         memory hot-plug systems.  This is normal.
 
-         For many other systems, this will be an alternative to
-         "Discontiguous Memory".  This option provides some potential
-         performance benefits, along with decreased code complexity,
-         but it is newer, and more experimental.
+         This option provides efficient support for systems with
+         holes is their physical address space and allows memory
+         hot-plug and hot-remove.
 
-         If unsure, choose "Discontiguous Memory" or "Flat Memory"
-         over this option.
+         If unsure, choose "Flat Memory" over this option.
 
 endchoice
 
@@ -136,7 +134,7 @@ config HAVE_MEMBLOCK_PHYS_MAP
 config HAVE_GENERIC_GUP
        bool
 
-config ARCH_DISCARD_MEMBLOCK
+config ARCH_KEEP_MEMBLOCK
        bool
 
 config MEMORY_ISOLATION
@@ -161,7 +159,6 @@ config MEMORY_HOTPLUG_SPARSE
 
 config MEMORY_HOTPLUG_DEFAULT_ONLINE
         bool "Online the newly added memory blocks by default"
-        default n
         depends on MEMORY_HOTPLUG
         help
          This option sets the default policy setting for memory hotplug
@@ -258,6 +255,9 @@ config ARCH_ENABLE_HUGEPAGE_MIGRATION
 config ARCH_ENABLE_THP_MIGRATION
        bool
 
+config CONTIG_ALLOC
+       def_bool (MEMORY_ISOLATION && COMPACTION) || CMA
+
 config PHYS_ADDR_T_64BIT
        def_bool 64BIT
 
@@ -436,7 +436,6 @@ config NEED_PER_CPU_KM
 
 config CLEANCACHE
        bool "Enable cleancache driver to cache clean pages if tmem is present"
-       default n
        help
          Cleancache can be thought of as a page-granularity victim cache
          for clean pages that the kernel's pageframe replacement algorithm
@@ -460,7 +459,6 @@ config CLEANCACHE
 config FRONTSWAP
        bool "Enable frontswap to cache swap pages if tmem is present"
        depends on SWAP
-       default n
        help
          Frontswap is so named because it can be thought of as the opposite
          of a "backing" store for a swap device.  The data is stored into
@@ -532,7 +530,6 @@ config ZSWAP
        depends on FRONTSWAP && CRYPTO=y
        select CRYPTO_LZO
        select ZPOOL
-       default n
        help
          A lightweight compressed cache for swap pages.  It takes
          pages that are in the process of being swapped out and attempts to
@@ -549,14 +546,12 @@ config ZSWAP
 
 config ZPOOL
        tristate "Common API for compressed memory storage"
-       default n
        help
          Compressed memory storage API.  This allows using either zbud or
          zsmalloc.
 
 config ZBUD
        tristate "Low (Up to 2x) density storage for compressed pages"
-       default n
        help
          A special purpose allocator for storing compressed pages.
          It is designed to store up to two compressed pages per physical
@@ -567,7 +562,6 @@ config ZBUD
 config Z3FOLD
        tristate "Up to 3x density storage for compressed pages"
        depends on ZPOOL
-       default n
        help
          A special purpose allocator for storing compressed pages.
          It is designed to store up to three compressed pages per physical
@@ -577,7 +571,6 @@ config Z3FOLD
 config ZSMALLOC
        tristate "Memory allocator for compressed pages"
        depends on MMU
-       default n
        help
          zsmalloc is a slab-based memory allocator designed to store
          compressed RAM pages.  zsmalloc uses virtual memory mapping
@@ -628,7 +621,6 @@ config MAX_STACK_SIZE_MB
 
 config DEFERRED_STRUCT_PAGE_INIT
        bool "Defer initialisation of struct pages to kthreads"
-       default n
        depends on SPARSEMEM
        depends on !NEED_PER_CPU_KM
        depends on 64BIT
@@ -676,6 +668,22 @@ config ZONE_DEVICE
 
          If FS_DAX is enabled, then say Y.
 
+config ARCH_HAS_HMM_MIRROR
+       bool
+       default y
+       depends on (X86_64 || PPC64)
+       depends on MMU && 64BIT
+
+config ARCH_HAS_HMM_DEVICE
+       bool
+       default y
+       depends on (X86_64 || PPC64)
+       depends on MEMORY_HOTPLUG
+       depends on MEMORY_HOTREMOVE
+       depends on SPARSEMEM_VMEMMAP
+       depends on ARCH_HAS_ZONE_DEVICE
+       select XARRAY_MULTI
+
 config ARCH_HAS_HMM
        bool
        default y
@@ -694,12 +702,12 @@ config DEV_PAGEMAP_OPS
 
 config HMM
        bool
+       select MMU_NOTIFIER
        select MIGRATE_VMA_HELPER
 
 config HMM_MIRROR
        bool "HMM mirror CPU page table into a device page table"
        depends on ARCH_HAS_HMM
-       select MMU_NOTIFIER
        select HMM
        help
          Select HMM_MIRROR if you want to mirror range of the CPU page table of a
@@ -740,7 +748,6 @@ config ARCH_HAS_PKEYS
 
 config PERCPU_STATS
        bool "Collect percpu memory statistics"
-       default n
        help
          This feature collects and exposes statistics via debugfs. The
          information includes global and per chunk statistics, which can
@@ -748,7 +755,6 @@ config PERCPU_STATS
 
 config GUP_BENCHMARK
        bool "Enable infrastructure for get_user_pages_fast() benchmarking"
-       default n
        help
          Provides /sys/kernel/debug/gup_benchmark that helps with testing
          performance of get_user_pages_fast().
index e3df921..e980ceb 100644 (file)
@@ -33,7 +33,6 @@ config DEBUG_PAGEALLOC
 
 config DEBUG_PAGEALLOC_ENABLE_DEFAULT
        bool "Enable debug page memory allocations by default?"
-       default n
        depends on DEBUG_PAGEALLOC
        ---help---
          Enable debug page memory allocations by default? This value
index d210cc9..ac5e5ba 100644 (file)
@@ -33,7 +33,7 @@ mmu-$(CONFIG_MMU)     += process_vm_access.o
 endif
 
 obj-y                  := filemap.o mempool.o oom_kill.o fadvise.o \
-                          maccess.o page_alloc.o page-writeback.o \
+                          maccess.o page-writeback.o \
                           readahead.o swap.o truncate.o vmscan.o shmem.o \
                           util.o mmzone.o vmstat.o backing-dev.o \
                           mm_init.o mmu_context.o percpu.o slab_common.o \
@@ -41,6 +41,11 @@ obj-y                        := filemap.o mempool.o oom_kill.o fadvise.o \
                           interval_tree.o list_lru.o workingset.o \
                           debug.o $(mmu-y)
 
+# Give 'page_alloc' its own module-parameter namespace
+page-alloc-y := page_alloc.o
+page-alloc-$(CONFIG_SHUFFLE_PAGE_ALLOCATOR) += shuffle.o
+
+obj-y += page-alloc.o
 obj-y += init-mm.o
 obj-y += memblock.o
 
index bb2d333..5e36d74 100644 (file)
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -106,8 +106,10 @@ static int __init cma_activate_area(struct cma *cma)
 
        cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
 
-       if (!cma->bitmap)
+       if (!cma->bitmap) {
+               cma->count = 0;
                return -ENOMEM;
+       }
 
        WARN_ON_ONCE(!pfn_valid(pfn));
        zone = page_zone(pfn_to_page(pfn));
@@ -367,23 +369,26 @@ err:
 #ifdef CONFIG_CMA_DEBUG
 static void cma_debug_show_areas(struct cma *cma)
 {
-       unsigned long next_zero_bit, next_set_bit;
+       unsigned long next_zero_bit, next_set_bit, nr_zero;
        unsigned long start = 0;
-       unsigned int nr_zero, nr_total = 0;
+       unsigned long nr_part, nr_total = 0;
+       unsigned long nbits = cma_bitmap_maxno(cma);
 
        mutex_lock(&cma->lock);
        pr_info("number of available pages: ");
        for (;;) {
-               next_zero_bit = find_next_zero_bit(cma->bitmap, cma->count, start);
-               if (next_zero_bit >= cma->count)
+               next_zero_bit = find_next_zero_bit(cma->bitmap, nbits, start);
+               if (next_zero_bit >= nbits)
                        break;
-               next_set_bit = find_next_bit(cma->bitmap, cma->count, next_zero_bit);
+               next_set_bit = find_next_bit(cma->bitmap, nbits, next_zero_bit);
                nr_zero = next_set_bit - next_zero_bit;
-               pr_cont("%s%u@%lu", nr_total ? "+" : "", nr_zero, next_zero_bit);
-               nr_total += nr_zero;
+               nr_part = nr_zero << cma->order_per_bit;
+               pr_cont("%s%lu@%lu", nr_total ? "+" : "", nr_part,
+                       next_zero_bit);
+               nr_total += nr_part;
                start = next_zero_bit + nr_zero;
        }
-       pr_cont("=> %u free of %lu total pages\n", nr_total, cma->count);
+       pr_cont("=> %lu free of %lu total pages\n", nr_total, cma->count);
        mutex_unlock(&cma->lock);
 }
 #else
index 8d7b2fd..a7dd9e8 100644 (file)
@@ -56,7 +56,7 @@ static int cma_maxchunk_get(void *data, u64 *val)
        mutex_lock(&cma->lock);
        for (;;) {
                start = find_next_zero_bit(cma->bitmap, bitmap_maxno, end);
-               if (start >= cma->count)
+               if (start >= bitmap_maxno)
                        break;
                end = find_next_bit(cma->bitmap, bitmap_maxno, start);
                maxchunk = max(end - start, maxchunk);
index 3319e08..cbac727 100644 (file)
@@ -1164,7 +1164,9 @@ static bool suitable_migration_target(struct compact_control *cc,
 static inline unsigned int
 freelist_scan_limit(struct compact_control *cc)
 {
-       return (COMPACT_CLUSTER_MAX >> cc->fast_search_fail) + 1;
+       unsigned short shift = BITS_PER_LONG - 1;
+
+       return (COMPACT_CLUSTER_MAX >> min(shift, cc->fast_search_fail)) + 1;
 }
 
 /*
@@ -1886,13 +1888,13 @@ static enum compact_result __compact_finished(struct compact_control *cc)
                bool can_steal;
 
                /* Job done if page is free of the right migratetype */
-               if (!list_empty(&area->free_list[migratetype]))
+               if (!free_area_empty(area, migratetype))
                        return COMPACT_SUCCESS;
 
 #ifdef CONFIG_CMA
                /* MIGRATE_MOVABLE can fallback on MIGRATE_CMA */
                if (migratetype == MIGRATE_MOVABLE &&
-                       !list_empty(&area->free_list[MIGRATE_CMA]))
+                       !free_area_empty(area, MIGRATE_CMA))
                        return COMPACT_SUCCESS;
 #endif
                /*
index eee9c22..8345bb6 100644 (file)
@@ -67,7 +67,7 @@ void __dump_page(struct page *page, const char *reason)
         */
        mapcount = PageSlab(page) ? 0 : page_mapcount(page);
 
-       pr_warn("page:%px count:%d mapcount:%d mapping:%px index:%#lx",
+       pr_warn("page:%px refcount:%d mapcount:%d mapping:%px index:%#lx",
                  page, page_ref_count(page), mapcount,
                  page->mapping, page_to_pgoff(page));
        if (PageCompound(page))
index d78f577..c5af80c 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/pagemap.h>
 #include <linux/file.h>
 #include <linux/uio.h>
+#include <linux/error-injection.h>
 #include <linux/hash.h>
 #include <linux/writeback.h>
 #include <linux/backing-dev.h>
@@ -279,11 +280,11 @@ EXPORT_SYMBOL(delete_from_page_cache);
  * @pvec: pagevec with pages to delete
  *
  * The function walks over mapping->i_pages and removes pages passed in @pvec
- * from the mapping. The function expects @pvec to be sorted by page index.
+ * from the mapping. The function expects @pvec to be sorted by page index
+ * and is optimised for it to be dense.
  * It tolerates holes in @pvec (mapping entries at those indices are not
  * modified). The function expects only THP head pages to be present in the
- * @pvec and takes care to delete all corresponding tail pages from the
- * mapping as well.
+ * @pvec.
  *
  * The function expects the i_pages lock to be held.
  */
@@ -292,40 +293,44 @@ static void page_cache_delete_batch(struct address_space *mapping,
 {
        XA_STATE(xas, &mapping->i_pages, pvec->pages[0]->index);
        int total_pages = 0;
-       int i = 0, tail_pages = 0;
+       int i = 0;
        struct page *page;
 
        mapping_set_update(&xas, mapping);
        xas_for_each(&xas, page, ULONG_MAX) {
-               if (i >= pagevec_count(pvec) && !tail_pages)
+               if (i >= pagevec_count(pvec))
                        break;
+
+               /* A swap/dax/shadow entry got inserted? Skip it. */
                if (xa_is_value(page))
                        continue;
-               if (!tail_pages) {
-                       /*
-                        * Some page got inserted in our range? Skip it. We
-                        * have our pages locked so they are protected from
-                        * being removed.
-                        */
-                       if (page != pvec->pages[i]) {
-                               VM_BUG_ON_PAGE(page->index >
-                                               pvec->pages[i]->index, page);
-                               continue;
-                       }
-                       WARN_ON_ONCE(!PageLocked(page));
-                       if (PageTransHuge(page) && !PageHuge(page))
-                               tail_pages = HPAGE_PMD_NR - 1;
+               /*
+                * A page got inserted in our range? Skip it. We have our
+                * pages locked so they are protected from being removed.
+                * If we see a page whose index is higher than ours, it
+                * means our page has been removed, which shouldn't be
+                * possible because we're holding the PageLock.
+                */
+               if (page != pvec->pages[i]) {
+                       VM_BUG_ON_PAGE(page->index > pvec->pages[i]->index,
+                                       page);
+                       continue;
+               }
+
+               WARN_ON_ONCE(!PageLocked(page));
+
+               if (page->index == xas.xa_index)
                        page->mapping = NULL;
-                       /*
-                        * Leave page->index set: truncation lookup relies
-                        * upon it
-                        */
+               /* Leave page->index set: truncation lookup relies on it */
+
+               /*
+                * Move to the next page in the vector if this is a regular
+                * page or the index is of the last sub-page of this compound
+                * page.
+                */
+               if (page->index + (1UL << compound_order(page)) - 1 ==
+                               xas.xa_index)
                        i++;
-               } else {
-                       VM_BUG_ON_PAGE(page->index + HPAGE_PMD_NR - tail_pages
-                                       != pvec->pages[i]->index, page);
-                       tail_pages--;
-               }
                xas_store(&xas, NULL);
                total_pages++;
        }
@@ -878,6 +883,7 @@ error:
        put_page(page);
        return xas_error(&xas);
 }
+ALLOW_ERROR_INJECTION(__add_to_page_cache_locked, ERRNO);
 
 /**
  * add_to_page_cache_locked - add a locked page to the pagecache
@@ -1440,7 +1446,7 @@ pgoff_t page_cache_next_miss(struct address_space *mapping,
 EXPORT_SYMBOL(page_cache_next_miss);
 
 /**
- * page_cache_prev_miss() - Find the next gap in the page cache.
+ * page_cache_prev_miss() - Find the previous gap in the page cache.
  * @mapping: Mapping.
  * @index: Index.
  * @max_scan: Maximum range to search.
@@ -1491,7 +1497,7 @@ EXPORT_SYMBOL(page_cache_prev_miss);
 struct page *find_get_entry(struct address_space *mapping, pgoff_t offset)
 {
        XA_STATE(xas, &mapping->i_pages, offset);
-       struct page *head, *page;
+       struct page *page;
 
        rcu_read_lock();
 repeat:
@@ -1506,25 +1512,19 @@ repeat:
        if (!page || xa_is_value(page))
                goto out;
 
-       head = compound_head(page);
-       if (!page_cache_get_speculative(head))
+       if (!page_cache_get_speculative(page))
                goto repeat;
 
-       /* The page was split under us? */
-       if (compound_head(page) != head) {
-               put_page(head);
-               goto repeat;
-       }
-
        /*
-        * Has the page moved?
+        * Has the page moved or been split?
         * This is part of the lockless pagecache protocol. See
         * include/linux/pagemap.h for details.
         */
        if (unlikely(page != xas_reload(&xas))) {
-               put_page(head);
+               put_page(page);
                goto repeat;
        }
+       page = find_subpage(page, offset);
 out:
        rcu_read_unlock();
 
@@ -1706,7 +1706,6 @@ unsigned find_get_entries(struct address_space *mapping,
 
        rcu_read_lock();
        xas_for_each(&xas, page, ULONG_MAX) {
-               struct page *head;
                if (xas_retry(&xas, page))
                        continue;
                /*
@@ -1717,17 +1716,13 @@ unsigned find_get_entries(struct address_space *mapping,
                if (xa_is_value(page))
                        goto export;
 
-               head = compound_head(page);
-               if (!page_cache_get_speculative(head))
+               if (!page_cache_get_speculative(page))
                        goto retry;
 
-               /* The page was split under us? */
-               if (compound_head(page) != head)
-                       goto put_page;
-
-               /* Has the page moved? */
+               /* Has the page moved or been split? */
                if (unlikely(page != xas_reload(&xas)))
                        goto put_page;
+               page = find_subpage(page, xas.xa_index);
 
 export:
                indices[ret] = xas.xa_index;
@@ -1736,7 +1731,7 @@ export:
                        break;
                continue;
 put_page:
-               put_page(head);
+               put_page(page);
 retry:
                xas_reset(&xas);
        }
@@ -1778,33 +1773,27 @@ unsigned find_get_pages_range(struct address_space *mapping, pgoff_t *start,
 
        rcu_read_lock();
        xas_for_each(&xas, page, end) {
-               struct page *head;
                if (xas_retry(&xas, page))
                        continue;
                /* Skip over shadow, swap and DAX entries */
                if (xa_is_value(page))
                        continue;
 
-               head = compound_head(page);
-               if (!page_cache_get_speculative(head))
+               if (!page_cache_get_speculative(page))
                        goto retry;
 
-               /* The page was split under us? */
-               if (compound_head(page) != head)
-                       goto put_page;
-
-               /* Has the page moved? */
+               /* Has the page moved or been split? */
                if (unlikely(page != xas_reload(&xas)))
                        goto put_page;
 
-               pages[ret] = page;
+               pages[ret] = find_subpage(page, xas.xa_index);
                if (++ret == nr_pages) {
                        *start = xas.xa_index + 1;
                        goto out;
                }
                continue;
 put_page:
-               put_page(head);
+               put_page(page);
 retry:
                xas_reset(&xas);
        }
@@ -1849,7 +1838,6 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index,
 
        rcu_read_lock();
        for (page = xas_load(&xas); page; page = xas_next(&xas)) {
-               struct page *head;
                if (xas_retry(&xas, page))
                        continue;
                /*
@@ -1859,24 +1847,19 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index,
                if (xa_is_value(page))
                        break;
 
-               head = compound_head(page);
-               if (!page_cache_get_speculative(head))
+               if (!page_cache_get_speculative(page))
                        goto retry;
 
-               /* The page was split under us? */
-               if (compound_head(page) != head)
-                       goto put_page;
-
-               /* Has the page moved? */
+               /* Has the page moved or been split? */
                if (unlikely(page != xas_reload(&xas)))
                        goto put_page;
 
-               pages[ret] = page;
+               pages[ret] = find_subpage(page, xas.xa_index);
                if (++ret == nr_pages)
                        break;
                continue;
 put_page:
-               put_page(head);
+               put_page(page);
 retry:
                xas_reset(&xas);
        }
@@ -1912,7 +1895,6 @@ unsigned find_get_pages_range_tag(struct address_space *mapping, pgoff_t *index,
 
        rcu_read_lock();
        xas_for_each_marked(&xas, page, end, tag) {
-               struct page *head;
                if (xas_retry(&xas, page))
                        continue;
                /*
@@ -1923,26 +1905,21 @@ unsigned find_get_pages_range_tag(struct address_space *mapping, pgoff_t *index,
                if (xa_is_value(page))
                        continue;
 
-               head = compound_head(page);
-               if (!page_cache_get_speculative(head))
+               if (!page_cache_get_speculative(page))
                        goto retry;
 
-               /* The page was split under us? */
-               if (compound_head(page) != head)
-                       goto put_page;
-
-               /* Has the page moved? */
+               /* Has the page moved or been split? */
                if (unlikely(page != xas_reload(&xas)))
                        goto put_page;
 
-               pages[ret] = page;
+               pages[ret] = find_subpage(page, xas.xa_index);
                if (++ret == nr_pages) {
                        *index = xas.xa_index + 1;
                        goto out;
                }
                continue;
 put_page:
-               put_page(head);
+               put_page(page);
 retry:
                xas_reset(&xas);
        }
@@ -1964,72 +1941,6 @@ out:
 }
 EXPORT_SYMBOL(find_get_pages_range_tag);
 
-/**
- * find_get_entries_tag - find and return entries that match @tag
- * @mapping:   the address_space to search
- * @start:     the starting page cache index
- * @tag:       the tag index
- * @nr_entries:        the maximum number of entries
- * @entries:   where the resulting entries are placed
- * @indices:   the cache indices corresponding to the entries in @entries
- *
- * Like find_get_entries, except we only return entries which are tagged with
- * @tag.
- *
- * Return: the number of entries which were found.
- */
-unsigned find_get_entries_tag(struct address_space *mapping, pgoff_t start,
-                       xa_mark_t tag, unsigned int nr_entries,
-                       struct page **entries, pgoff_t *indices)
-{
-       XA_STATE(xas, &mapping->i_pages, start);
-       struct page *page;
-       unsigned int ret = 0;
-
-       if (!nr_entries)
-               return 0;
-
-       rcu_read_lock();
-       xas_for_each_marked(&xas, page, ULONG_MAX, tag) {
-               struct page *head;
-               if (xas_retry(&xas, page))
-                       continue;
-               /*
-                * A shadow entry of a recently evicted page, a swap
-                * entry from shmem/tmpfs or a DAX entry.  Return it
-                * without attempting to raise page count.
-                */
-               if (xa_is_value(page))
-                       goto export;
-
-               head = compound_head(page);
-               if (!page_cache_get_speculative(head))
-                       goto retry;
-
-               /* The page was split under us? */
-               if (compound_head(page) != head)
-                       goto put_page;
-
-               /* Has the page moved? */
-               if (unlikely(page != xas_reload(&xas)))
-                       goto put_page;
-
-export:
-               indices[ret] = xas.xa_index;
-               entries[ret] = page;
-               if (++ret == nr_entries)
-                       break;
-               continue;
-put_page:
-               put_page(head);
-retry:
-               xas_reset(&xas);
-       }
-       rcu_read_unlock();
-       return ret;
-}
-EXPORT_SYMBOL(find_get_entries_tag);
-
 /*
  * CD/DVDs are error prone. When a medium error occurs, the driver may fail
  * a _large_ part of the i/o request. Imagine the worst scenario:
@@ -2691,7 +2602,7 @@ void filemap_map_pages(struct vm_fault *vmf,
        pgoff_t last_pgoff = start_pgoff;
        unsigned long max_idx;
        XA_STATE(xas, &mapping->i_pages, start_pgoff);
-       struct page *head, *page;
+       struct page *page;
 
        rcu_read_lock();
        xas_for_each(&xas, page, end_pgoff) {
@@ -2700,24 +2611,19 @@ void filemap_map_pages(struct vm_fault *vmf,
                if (xa_is_value(page))
                        goto next;
 
-               head = compound_head(page);
-
                /*
                 * Check for a locked page first, as a speculative
                 * reference may adversely influence page migration.
                 */
-               if (PageLocked(head))
+               if (PageLocked(page))
                        goto next;
-               if (!page_cache_get_speculative(head))
+               if (!page_cache_get_speculative(page))
                        goto next;
 
-               /* The page was split under us? */
-               if (compound_head(page) != head)
-                       goto skip;
-
-               /* Has the page moved? */
+               /* Has the page moved or been split? */
                if (unlikely(page != xas_reload(&xas)))
                        goto skip;
+               page = find_subpage(page, xas.xa_index);
 
                if (!PageUptodate(page) ||
                                PageReadahead(page) ||
index 91819b8..2c08248 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -28,6 +28,111 @@ struct follow_page_context {
        unsigned int page_mask;
 };
 
+typedef int (*set_dirty_func_t)(struct page *page);
+
+static void __put_user_pages_dirty(struct page **pages,
+                                  unsigned long npages,
+                                  set_dirty_func_t sdf)
+{
+       unsigned long index;
+
+       for (index = 0; index < npages; index++) {
+               struct page *page = compound_head(pages[index]);
+
+               /*
+                * Checking PageDirty at this point may race with
+                * clear_page_dirty_for_io(), but that's OK. Two key cases:
+                *
+                * 1) This code sees the page as already dirty, so it skips
+                * the call to sdf(). That could happen because
+                * clear_page_dirty_for_io() called page_mkclean(),
+                * followed by set_page_dirty(). However, now the page is
+                * going to get written back, which meets the original
+                * intention of setting it dirty, so all is well:
+                * clear_page_dirty_for_io() goes on to call
+                * TestClearPageDirty(), and write the page back.
+                *
+                * 2) This code sees the page as clean, so it calls sdf().
+                * The page stays dirty, despite being written back, so it
+                * gets written back again in the next writeback cycle.
+                * This is harmless.
+                */
+               if (!PageDirty(page))
+                       sdf(page);
+
+               put_user_page(page);
+       }
+}
+
+/**
+ * put_user_pages_dirty() - release and dirty an array of gup-pinned pages
+ * @pages:  array of pages to be marked dirty and released.
+ * @npages: number of pages in the @pages array.
+ *
+ * "gup-pinned page" refers to a page that has had one of the get_user_pages()
+ * variants called on that page.
+ *
+ * For each page in the @pages array, make that page (or its head page, if a
+ * compound page) dirty, if it was previously listed as clean. Then, release
+ * the page using put_user_page().
+ *
+ * Please see the put_user_page() documentation for details.
+ *
+ * set_page_dirty(), which does not lock the page, is used here.
+ * Therefore, it is the caller's responsibility to ensure that this is
+ * safe. If not, then put_user_pages_dirty_lock() should be called instead.
+ *
+ */
+void put_user_pages_dirty(struct page **pages, unsigned long npages)
+{
+       __put_user_pages_dirty(pages, npages, set_page_dirty);
+}
+EXPORT_SYMBOL(put_user_pages_dirty);
+
+/**
+ * put_user_pages_dirty_lock() - release and dirty an array of gup-pinned pages
+ * @pages:  array of pages to be marked dirty and released.
+ * @npages: number of pages in the @pages array.
+ *
+ * For each page in the @pages array, make that page (or its head page, if a
+ * compound page) dirty, if it was previously listed as clean. Then, release
+ * the page using put_user_page().
+ *
+ * Please see the put_user_page() documentation for details.
+ *
+ * This is just like put_user_pages_dirty(), except that it invokes
+ * set_page_dirty_lock(), instead of set_page_dirty().
+ *
+ */
+void put_user_pages_dirty_lock(struct page **pages, unsigned long npages)
+{
+       __put_user_pages_dirty(pages, npages, set_page_dirty_lock);
+}
+EXPORT_SYMBOL(put_user_pages_dirty_lock);
+
+/**
+ * put_user_pages() - release an array of gup-pinned pages.
+ * @pages:  array of pages to be marked dirty and released.
+ * @npages: number of pages in the @pages array.
+ *
+ * For each page in the @pages array, release the page using put_user_page().
+ *
+ * Please see the put_user_page() documentation for details.
+ */
+void put_user_pages(struct page **pages, unsigned long npages)
+{
+       unsigned long index;
+
+       /*
+        * TODO: this can be optimized for huge pages: if a series of pages is
+        * physically contiguous and part of the same compound page, then a
+        * single operation to the head page should suffice.
+        */
+       for (index = 0; index < npages; index++)
+               put_user_page(pages[index]);
+}
+EXPORT_SYMBOL(put_user_pages);
+
 static struct page *no_page_table(struct vm_area_struct *vma,
                unsigned int flags)
 {
@@ -1018,6 +1123,15 @@ long get_user_pages_locked(unsigned long start, unsigned long nr_pages,
                           unsigned int gup_flags, struct page **pages,
                           int *locked)
 {
+       /*
+        * FIXME: Current FOLL_LONGTERM behavior is incompatible with
+        * FAULT_FLAG_ALLOW_RETRY because of the FS DAX check requirement on
+        * vmas.  As there are no users of this flag in this call we simply
+        * disallow this option for now.
+        */
+       if (WARN_ON_ONCE(gup_flags & FOLL_LONGTERM))
+               return -EINVAL;
+
        return __get_user_pages_locked(current, current->mm, start, nr_pages,
                                       pages, NULL, locked,
                                       gup_flags | FOLL_TOUCH);
@@ -1046,6 +1160,15 @@ long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
        int locked = 1;
        long ret;
 
+       /*
+        * FIXME: Current FOLL_LONGTERM behavior is incompatible with
+        * FAULT_FLAG_ALLOW_RETRY because of the FS DAX check requirement on
+        * vmas.  As there are no users of this flag in this call we simply
+        * disallow this option for now.
+        */
+       if (WARN_ON_ONCE(gup_flags & FOLL_LONGTERM))
+               return -EINVAL;
+
        down_read(&mm->mmap_sem);
        ret = __get_user_pages_locked(current, mm, start, nr_pages, pages, NULL,
                                      &locked, gup_flags | FOLL_TOUCH);
@@ -1116,32 +1239,22 @@ long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm,
                unsigned int gup_flags, struct page **pages,
                struct vm_area_struct **vmas, int *locked)
 {
+       /*
+        * FIXME: Current FOLL_LONGTERM behavior is incompatible with
+        * FAULT_FLAG_ALLOW_RETRY because of the FS DAX check requirement on
+        * vmas.  As there are no users of this flag in this call we simply
+        * disallow this option for now.
+        */
+       if (WARN_ON_ONCE(gup_flags & FOLL_LONGTERM))
+               return -EINVAL;
+
        return __get_user_pages_locked(tsk, mm, start, nr_pages, pages, vmas,
                                       locked,
                                       gup_flags | FOLL_TOUCH | FOLL_REMOTE);
 }
 EXPORT_SYMBOL(get_user_pages_remote);
 
-/*
- * This is the same as get_user_pages_remote(), just with a
- * less-flexible calling convention where we assume that the task
- * and mm being operated on are the current task's and don't allow
- * passing of a locked parameter.  We also obviously don't pass
- * FOLL_REMOTE in here.
- */
-long get_user_pages(unsigned long start, unsigned long nr_pages,
-               unsigned int gup_flags, struct page **pages,
-               struct vm_area_struct **vmas)
-{
-       return __get_user_pages_locked(current, current->mm, start, nr_pages,
-                                      pages, vmas, NULL,
-                                      gup_flags | FOLL_TOUCH);
-}
-EXPORT_SYMBOL(get_user_pages);
-
 #if defined(CONFIG_FS_DAX) || defined (CONFIG_CMA)
-
-#ifdef CONFIG_FS_DAX
 static bool check_dax_vmas(struct vm_area_struct **vmas, long nr_pages)
 {
        long i;
@@ -1160,12 +1273,6 @@ static bool check_dax_vmas(struct vm_area_struct **vmas, long nr_pages)
        }
        return false;
 }
-#else
-static inline bool check_dax_vmas(struct vm_area_struct **vmas, long nr_pages)
-{
-       return false;
-}
-#endif
 
 #ifdef CONFIG_CMA
 static struct page *new_non_cma_page(struct page *page, unsigned long private)
@@ -1219,10 +1326,13 @@ static struct page *new_non_cma_page(struct page *page, unsigned long private)
        return __alloc_pages_node(nid, gfp_mask, 0);
 }
 
-static long check_and_migrate_cma_pages(unsigned long start, long nr_pages,
-                                       unsigned int gup_flags,
+static long check_and_migrate_cma_pages(struct task_struct *tsk,
+                                       struct mm_struct *mm,
+                                       unsigned long start,
+                                       unsigned long nr_pages,
                                        struct page **pages,
-                                       struct vm_area_struct **vmas)
+                                       struct vm_area_struct **vmas,
+                                       unsigned int gup_flags)
 {
        long i;
        bool drain_allow = true;
@@ -1278,10 +1388,14 @@ check_again:
                                putback_movable_pages(&cma_page_list);
                }
                /*
-                * We did migrate all the pages, Try to get the page references again
-                * migrating any new CMA pages which we failed to isolate earlier.
+                * We did migrate all the pages, Try to get the page references
+                * again migrating any new CMA pages which we failed to isolate
+                * earlier.
                 */
-               nr_pages = get_user_pages(start, nr_pages, gup_flags, pages, vmas);
+               nr_pages = __get_user_pages_locked(tsk, mm, start, nr_pages,
+                                                  pages, vmas, NULL,
+                                                  gup_flags);
+
                if ((nr_pages > 0) && migrate_allow) {
                        drain_allow = true;
                        goto check_again;
@@ -1291,66 +1405,101 @@ check_again:
        return nr_pages;
 }
 #else
-static inline long check_and_migrate_cma_pages(unsigned long start, long nr_pages,
-                                              unsigned int gup_flags,
-                                              struct page **pages,
-                                              struct vm_area_struct **vmas)
+static long check_and_migrate_cma_pages(struct task_struct *tsk,
+                                       struct mm_struct *mm,
+                                       unsigned long start,
+                                       unsigned long nr_pages,
+                                       struct page **pages,
+                                       struct vm_area_struct **vmas,
+                                       unsigned int gup_flags)
 {
        return nr_pages;
 }
 #endif
 
 /*
- * This is the same as get_user_pages() in that it assumes we are
- * operating on the current task's mm, but it goes further to validate
- * that the vmas associated with the address range are suitable for
- * longterm elevated page reference counts. For example, filesystem-dax
- * mappings are subject to the lifetime enforced by the filesystem and
- * we need guarantees that longterm users like RDMA and V4L2 only
- * establish mappings that have a kernel enforced revocation mechanism.
- *
- * "longterm" == userspace controlled elevated page count lifetime.
- * Contrast this to iov_iter_get_pages() usages which are transient.
+ * __gup_longterm_locked() is a wrapper for __get_user_pages_locked which
+ * allows us to process the FOLL_LONGTERM flag.
  */
-long get_user_pages_longterm(unsigned long start, unsigned long nr_pages,
-                            unsigned int gup_flags, struct page **pages,
-                            struct vm_area_struct **vmas_arg)
+static long __gup_longterm_locked(struct task_struct *tsk,
+                                 struct mm_struct *mm,
+                                 unsigned long start,
+                                 unsigned long nr_pages,
+                                 struct page **pages,
+                                 struct vm_area_struct **vmas,
+                                 unsigned int gup_flags)
 {
-       struct vm_area_struct **vmas = vmas_arg;
-       unsigned long flags;
+       struct vm_area_struct **vmas_tmp = vmas;
+       unsigned long flags = 0;
        long rc, i;
 
-       if (!pages)
-               return -EINVAL;
-
-       if (!vmas) {
-               vmas = kcalloc(nr_pages, sizeof(struct vm_area_struct *),
-                              GFP_KERNEL);
-               if (!vmas)
-                       return -ENOMEM;
+       if (gup_flags & FOLL_LONGTERM) {
+               if (!pages)
+                       return -EINVAL;
+
+               if (!vmas_tmp) {
+                       vmas_tmp = kcalloc(nr_pages,
+                                          sizeof(struct vm_area_struct *),
+                                          GFP_KERNEL);
+                       if (!vmas_tmp)
+                               return -ENOMEM;
+               }
+               flags = memalloc_nocma_save();
        }
 
-       flags = memalloc_nocma_save();
-       rc = get_user_pages(start, nr_pages, gup_flags, pages, vmas);
-       memalloc_nocma_restore(flags);
-       if (rc < 0)
-               goto out;
+       rc = __get_user_pages_locked(tsk, mm, start, nr_pages, pages,
+                                    vmas_tmp, NULL, gup_flags);
 
-       if (check_dax_vmas(vmas, rc)) {
-               for (i = 0; i < rc; i++)
-                       put_page(pages[i]);
-               rc = -EOPNOTSUPP;
-               goto out;
+       if (gup_flags & FOLL_LONGTERM) {
+               memalloc_nocma_restore(flags);
+               if (rc < 0)
+                       goto out;
+
+               if (check_dax_vmas(vmas_tmp, rc)) {
+                       for (i = 0; i < rc; i++)
+                               put_page(pages[i]);
+                       rc = -EOPNOTSUPP;
+                       goto out;
+               }
+
+               rc = check_and_migrate_cma_pages(tsk, mm, start, rc, pages,
+                                                vmas_tmp, gup_flags);
        }
 
-       rc = check_and_migrate_cma_pages(start, rc, gup_flags, pages, vmas);
 out:
-       if (vmas != vmas_arg)
-               kfree(vmas);
+       if (vmas_tmp != vmas)
+               kfree(vmas_tmp);
        return rc;
 }
-EXPORT_SYMBOL(get_user_pages_longterm);
-#endif /* CONFIG_FS_DAX */
+#else /* !CONFIG_FS_DAX && !CONFIG_CMA */
+static __always_inline long __gup_longterm_locked(struct task_struct *tsk,
+                                                 struct mm_struct *mm,
+                                                 unsigned long start,
+                                                 unsigned long nr_pages,
+                                                 struct page **pages,
+                                                 struct vm_area_struct **vmas,
+                                                 unsigned int flags)
+{
+       return __get_user_pages_locked(tsk, mm, start, nr_pages, pages, vmas,
+                                      NULL, flags);
+}
+#endif /* CONFIG_FS_DAX || CONFIG_CMA */
+
+/*
+ * This is the same as get_user_pages_remote(), just with a
+ * less-flexible calling convention where we assume that the task
+ * and mm being operated on are the current task's and don't allow
+ * passing of a locked parameter.  We also obviously don't pass
+ * FOLL_REMOTE in here.
+ */
+long get_user_pages(unsigned long start, unsigned long nr_pages,
+               unsigned int gup_flags, struct page **pages,
+               struct vm_area_struct **vmas)
+{
+       return __gup_longterm_locked(current, current->mm, start, nr_pages,
+                                    pages, vmas, gup_flags | FOLL_TOUCH);
+}
+EXPORT_SYMBOL(get_user_pages);
 
 /**
  * populate_vma_page_range() -  populate a range of pages in the vma.
@@ -1571,7 +1720,7 @@ static inline struct page *try_get_compound_head(struct page *page, int refs)
 
 #ifdef CONFIG_ARCH_HAS_PTE_SPECIAL
 static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end,
-                        int write, struct page **pages, int *nr)
+                        unsigned int flags, struct page **pages, int *nr)
 {
        struct dev_pagemap *pgmap = NULL;
        int nr_start = *nr, ret = 0;
@@ -1589,10 +1738,13 @@ static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end,
                if (pte_protnone(pte))
                        goto pte_unmap;
 
-               if (!pte_access_permitted(pte, write))
+               if (!pte_access_permitted(pte, flags & FOLL_WRITE))
                        goto pte_unmap;
 
                if (pte_devmap(pte)) {
+                       if (unlikely(flags & FOLL_LONGTERM))
+                               goto pte_unmap;
+
                        pgmap = get_dev_pagemap(pte_pfn(pte), pgmap);
                        if (unlikely(!pgmap)) {
                                undo_dev_pagemap(nr, nr_start, pages);
@@ -1641,7 +1793,7 @@ pte_unmap:
  * useful to have gup_huge_pmd even if we can't operate on ptes.
  */
 static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end,
-                        int write, struct page **pages, int *nr)
+                        unsigned int flags, struct page **pages, int *nr)
 {
        return 0;
 }
@@ -1724,16 +1876,19 @@ static int __gup_device_huge_pud(pud_t pud, pud_t *pudp, unsigned long addr,
 #endif
 
 static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr,
-               unsigned long end, int write, struct page **pages, int *nr)
+               unsigned long end, unsigned int flags, struct page **pages, int *nr)
 {
        struct page *head, *page;
        int refs;
 
-       if (!pmd_access_permitted(orig, write))
+       if (!pmd_access_permitted(orig, flags & FOLL_WRITE))
                return 0;
 
-       if (pmd_devmap(orig))
+       if (pmd_devmap(orig)) {
+               if (unlikely(flags & FOLL_LONGTERM))
+                       return 0;
                return __gup_device_huge_pmd(orig, pmdp, addr, end, pages, nr);
+       }
 
        refs = 0;
        page = pmd_page(orig) + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
@@ -1762,16 +1917,19 @@ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr,
 }
 
 static int gup_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr,
-               unsigned long end, int write, struct page **pages, int *nr)
+               unsigned long end, unsigned int flags, struct page **pages, int *nr)
 {
        struct page *head, *page;
        int refs;
 
-       if (!pud_access_permitted(orig, write))
+       if (!pud_access_permitted(orig, flags & FOLL_WRITE))
                return 0;
 
-       if (pud_devmap(orig))
+       if (pud_devmap(orig)) {
+               if (unlikely(flags & FOLL_LONGTERM))
+                       return 0;
                return __gup_device_huge_pud(orig, pudp, addr, end, pages, nr);
+       }
 
        refs = 0;
        page = pud_page(orig) + ((addr & ~PUD_MASK) >> PAGE_SHIFT);
@@ -1800,13 +1958,13 @@ static int gup_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr,
 }
 
 static int gup_huge_pgd(pgd_t orig, pgd_t *pgdp, unsigned long addr,
-                       unsigned long end, int write,
+                       unsigned long end, unsigned int flags,
                        struct page **pages, int *nr)
 {
        int refs;
        struct page *head, *page;
 
-       if (!pgd_access_permitted(orig, write))
+       if (!pgd_access_permitted(orig, flags & FOLL_WRITE))
                return 0;
 
        BUILD_BUG_ON(pgd_devmap(orig));
@@ -1837,7 +1995,7 @@ static int gup_huge_pgd(pgd_t orig, pgd_t *pgdp, unsigned long addr,
 }
 
 static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
-               int write, struct page **pages, int *nr)
+               unsigned int flags, struct page **pages, int *nr)
 {
        unsigned long next;
        pmd_t *pmdp;
@@ -1860,7 +2018,7 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
                        if (pmd_protnone(pmd))
                                return 0;
 
-                       if (!gup_huge_pmd(pmd, pmdp, addr, next, write,
+                       if (!gup_huge_pmd(pmd, pmdp, addr, next, flags,
                                pages, nr))
                                return 0;
 
@@ -1870,9 +2028,9 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
                         * pmd format and THP pmd format
                         */
                        if (!gup_huge_pd(__hugepd(pmd_val(pmd)), addr,
-                                        PMD_SHIFT, next, write, pages, nr))
+                                        PMD_SHIFT, next, flags, pages, nr))
                                return 0;
-               } else if (!gup_pte_range(pmd, addr, next, write, pages, nr))
+               } else if (!gup_pte_range(pmd, addr, next, flags, pages, nr))
                        return 0;
        } while (pmdp++, addr = next, addr != end);
 
@@ -1880,7 +2038,7 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
 }
 
 static int gup_pud_range(p4d_t p4d, unsigned long addr, unsigned long end,
-                        int write, struct page **pages, int *nr)
+                        unsigned int flags, struct page **pages, int *nr)
 {
        unsigned long next;
        pud_t *pudp;
@@ -1893,14 +2051,14 @@ static int gup_pud_range(p4d_t p4d, unsigned long addr, unsigned long end,
                if (pud_none(pud))
                        return 0;
                if (unlikely(pud_huge(pud))) {
-                       if (!gup_huge_pud(pud, pudp, addr, next, write,
+                       if (!gup_huge_pud(pud, pudp, addr, next, flags,
                                          pages, nr))
                                return 0;
                } else if (unlikely(is_hugepd(__hugepd(pud_val(pud))))) {
                        if (!gup_huge_pd(__hugepd(pud_val(pud)), addr,
-                                        PUD_SHIFT, next, write, pages, nr))
+                                        PUD_SHIFT, next, flags, pages, nr))
                                return 0;
-               } else if (!gup_pmd_range(pud, addr, next, write, pages, nr))
+               } else if (!gup_pmd_range(pud, addr, next, flags, pages, nr))
                        return 0;
        } while (pudp++, addr = next, addr != end);
 
@@ -1908,7 +2066,7 @@ static int gup_pud_range(p4d_t p4d, unsigned long addr, unsigned long end,
 }
 
 static int gup_p4d_range(pgd_t pgd, unsigned long addr, unsigned long end,
-                        int write, struct page **pages, int *nr)
+                        unsigned int flags, struct page **pages, int *nr)
 {
        unsigned long next;
        p4d_t *p4dp;
@@ -1923,9 +2081,9 @@ static int gup_p4d_range(pgd_t pgd, unsigned long addr, unsigned long end,
                BUILD_BUG_ON(p4d_huge(p4d));
                if (unlikely(is_hugepd(__hugepd(p4d_val(p4d))))) {
                        if (!gup_huge_pd(__hugepd(p4d_val(p4d)), addr,
-                                        P4D_SHIFT, next, write, pages, nr))
+                                        P4D_SHIFT, next, flags, pages, nr))
                                return 0;
-               } else if (!gup_pud_range(p4d, addr, next, write, pages, nr))
+               } else if (!gup_pud_range(p4d, addr, next, flags, pages, nr))
                        return 0;
        } while (p4dp++, addr = next, addr != end);
 
@@ -1933,7 +2091,7 @@ static int gup_p4d_range(pgd_t pgd, unsigned long addr, unsigned long end,
 }
 
 static void gup_pgd_range(unsigned long addr, unsigned long end,
-               int write, struct page **pages, int *nr)
+               unsigned int flags, struct page **pages, int *nr)
 {
        unsigned long next;
        pgd_t *pgdp;
@@ -1946,14 +2104,14 @@ static void gup_pgd_range(unsigned long addr, unsigned long end,
                if (pgd_none(pgd))
                        return;
                if (unlikely(pgd_huge(pgd))) {
-                       if (!gup_huge_pgd(pgd, pgdp, addr, next, write,
+                       if (!gup_huge_pgd(pgd, pgdp, addr, next, flags,
                                          pages, nr))
                                return;
                } else if (unlikely(is_hugepd(__hugepd(pgd_val(pgd))))) {
                        if (!gup_huge_pd(__hugepd(pgd_val(pgd)), addr,
-                                        PGDIR_SHIFT, next, write, pages, nr))
+                                        PGDIR_SHIFT, next, flags, pages, nr))
                                return;
-               } else if (!gup_p4d_range(pgd, addr, next, write, pages, nr))
+               } else if (!gup_p4d_range(pgd, addr, next, flags, pages, nr))
                        return;
        } while (pgdp++, addr = next, addr != end);
 }
@@ -2007,18 +2165,41 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
 
        if (gup_fast_permitted(start, nr_pages)) {
                local_irq_save(flags);
-               gup_pgd_range(start, end, write, pages, &nr);
+               gup_pgd_range(start, end, write ? FOLL_WRITE : 0, pages, &nr);
                local_irq_restore(flags);
        }
 
        return nr;
 }
 
+static int __gup_longterm_unlocked(unsigned long start, int nr_pages,
+                                  unsigned int gup_flags, struct page **pages)
+{
+       int ret;
+
+       /*
+        * FIXME: FOLL_LONGTERM does not work with
+        * get_user_pages_unlocked() (see comments in that function)
+        */
+       if (gup_flags & FOLL_LONGTERM) {
+               down_read(&current->mm->mmap_sem);
+               ret = __gup_longterm_locked(current, current->mm,
+                                           start, nr_pages,
+                                           pages, NULL, gup_flags);
+               up_read(&current->mm->mmap_sem);
+       } else {
+               ret = get_user_pages_unlocked(start, nr_pages,
+                                             pages, gup_flags);
+       }
+
+       return ret;
+}
+
 /**
  * get_user_pages_fast() - pin user pages in memory
  * @start:     starting user address
  * @nr_pages:  number of pages from start to pin
- * @write:     whether pages will be written to
+ * @gup_flags: flags modifying pin behaviour
  * @pages:     array that receives pointers to the pages pinned.
  *             Should be at least nr_pages long.
  *
@@ -2030,8 +2211,8 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
  * requested. If nr_pages is 0 or negative, returns 0. If no pages
  * were pinned, returns -errno.
  */
-int get_user_pages_fast(unsigned long start, int nr_pages, int write,
-                       struct page **pages)
+int get_user_pages_fast(unsigned long start, int nr_pages,
+                       unsigned int gup_flags, struct page **pages)
 {
        unsigned long addr, len, end;
        int nr = 0, ret = 0;
@@ -2049,7 +2230,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
 
        if (gup_fast_permitted(start, nr_pages)) {
                local_irq_disable();
-               gup_pgd_range(addr, end, write, pages, &nr);
+               gup_pgd_range(addr, end, gup_flags, pages, &nr);
                local_irq_enable();
                ret = nr;
        }
@@ -2059,8 +2240,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
                start += nr << PAGE_SHIFT;
                pages += nr;
 
-               ret = get_user_pages_unlocked(start, nr_pages - nr, pages,
-                               write ? FOLL_WRITE : 0);
+               ret = __gup_longterm_unlocked(start, nr_pages - nr,
+                                             gup_flags, pages);
 
                /* Have to be a bit careful with return values */
                if (nr > 0) {
index 6c0279e..7dd602d 100644 (file)
@@ -54,8 +54,9 @@ static int __gup_benchmark_ioctl(unsigned int cmd,
                                                 pages + i);
                        break;
                case GUP_LONGTERM_BENCHMARK:
-                       nr = get_user_pages_longterm(addr, nr, gup->flags & 1,
-                                                    pages + i, NULL);
+                       nr = get_user_pages(addr, nr,
+                                           (gup->flags & 1) | FOLL_LONGTERM,
+                                           pages + i, NULL);
                        break;
                case GUP_BENCHMARK:
                        nr = get_user_pages(addr, nr, gup->flags & 1, pages + i,
index fe1cd87..0db8491 100644 (file)
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -30,6 +30,7 @@
 #include <linux/hugetlb.h>
 #include <linux/memremap.h>
 #include <linux/jump_label.h>
+#include <linux/dma-mapping.h>
 #include <linux/mmu_notifier.h>
 #include <linux/memory_hotplug.h>
 
 #if IS_ENABLED(CONFIG_HMM_MIRROR)
 static const struct mmu_notifier_ops hmm_mmu_notifier_ops;
 
-/*
- * struct hmm - HMM per mm struct
- *
- * @mm: mm struct this HMM struct is bound to
- * @lock: lock protecting ranges list
- * @ranges: list of range being snapshotted
- * @mirrors: list of mirrors for this mm
- * @mmu_notifier: mmu notifier to track updates to CPU page table
- * @mirrors_sem: read/write semaphore protecting the mirrors list
- */
-struct hmm {
-       struct mm_struct        *mm;
-       spinlock_t              lock;
-       struct list_head        ranges;
-       struct list_head        mirrors;
-       struct mmu_notifier     mmu_notifier;
-       struct rw_semaphore     mirrors_sem;
-};
+static inline struct hmm *mm_get_hmm(struct mm_struct *mm)
+{
+       struct hmm *hmm = READ_ONCE(mm->hmm);
 
-/*
- * hmm_register - register HMM against an mm (HMM internal)
+       if (hmm && kref_get_unless_zero(&hmm->kref))
+               return hmm;
+
+       return NULL;
+}
+
+/**
+ * hmm_get_or_create - register HMM against an mm (HMM internal)
  *
  * @mm: mm struct to attach to
+ * Returns: returns an HMM object, either by referencing the existing
+ *          (per-process) object, or by creating a new one.
  *
- * This is not intended to be used directly by device drivers. It allocates an
- * HMM struct if mm does not have one, and initializes it.
+ * This is not intended to be used directly by device drivers. If mm already
+ * has an HMM struct then it get a reference on it and returns it. Otherwise
+ * it allocates an HMM struct, initializes it, associate it with the mm and
+ * returns it.
  */
-static struct hmm *hmm_register(struct mm_struct *mm)
+static struct hmm *hmm_get_or_create(struct mm_struct *mm)
 {
-       struct hmm *hmm = READ_ONCE(mm->hmm);
+       struct hmm *hmm = mm_get_hmm(mm);
        bool cleanup = false;
 
-       /*
-        * The hmm struct can only be freed once the mm_struct goes away,
-        * hence we should always have pre-allocated an new hmm struct
-        * above.
-        */
        if (hmm)
                return hmm;
 
        hmm = kmalloc(sizeof(*hmm), GFP_KERNEL);
        if (!hmm)
                return NULL;
+       init_waitqueue_head(&hmm->wq);
        INIT_LIST_HEAD(&hmm->mirrors);
        init_rwsem(&hmm->mirrors_sem);
        hmm->mmu_notifier.ops = NULL;
        INIT_LIST_HEAD(&hmm->ranges);
-       spin_lock_init(&hmm->lock);
+       mutex_init(&hmm->lock);
+       kref_init(&hmm->kref);
+       hmm->notifiers = 0;
+       hmm->dead = false;
        hmm->mm = mm;
 
        spin_lock(&mm->page_table_lock);
@@ -106,7 +101,7 @@ static struct hmm *hmm_register(struct mm_struct *mm)
        if (__mmu_notifier_register(&hmm->mmu_notifier, mm))
                goto error_mm;
 
-       return mm->hmm;
+       return hmm;
 
 error_mm:
        spin_lock(&mm->page_table_lock);
@@ -118,54 +113,60 @@ error:
        return NULL;
 }
 
-void hmm_mm_destroy(struct mm_struct *mm)
+static void hmm_free(struct kref *kref)
 {
-       kfree(mm->hmm);
-}
+       struct hmm *hmm = container_of(kref, struct hmm, kref);
+       struct mm_struct *mm = hmm->mm;
 
-static int hmm_invalidate_range(struct hmm *hmm, bool device,
-                               const struct hmm_update *update)
-{
-       struct hmm_mirror *mirror;
-       struct hmm_range *range;
-
-       spin_lock(&hmm->lock);
-       list_for_each_entry(range, &hmm->ranges, list) {
-               unsigned long addr, idx, npages;
+       mmu_notifier_unregister_no_release(&hmm->mmu_notifier, mm);
 
-               if (update->end < range->start || update->start >= range->end)
-                       continue;
+       spin_lock(&mm->page_table_lock);
+       if (mm->hmm == hmm)
+               mm->hmm = NULL;
+       spin_unlock(&mm->page_table_lock);
 
-               range->valid = false;
-               addr = max(update->start, range->start);
-               idx = (addr - range->start) >> PAGE_SHIFT;
-               npages = (min(range->end, update->end) - addr) >> PAGE_SHIFT;
-               memset(&range->pfns[idx], 0, sizeof(*range->pfns) * npages);
-       }
-       spin_unlock(&hmm->lock);
+       kfree(hmm);
+}
 
-       if (!device)
-               return 0;
+static inline void hmm_put(struct hmm *hmm)
+{
+       kref_put(&hmm->kref, hmm_free);
+}
 
-       down_read(&hmm->mirrors_sem);
-       list_for_each_entry(mirror, &hmm->mirrors, list) {
-               int ret;
+void hmm_mm_destroy(struct mm_struct *mm)
+{
+       struct hmm *hmm;
 
-               ret = mirror->ops->sync_cpu_device_pagetables(mirror, update);
-               if (!update->blockable && ret == -EAGAIN) {
-                       up_read(&hmm->mirrors_sem);
-                       return -EAGAIN;
-               }
+       spin_lock(&mm->page_table_lock);
+       hmm = mm_get_hmm(mm);
+       mm->hmm = NULL;
+       if (hmm) {
+               hmm->mm = NULL;
+               hmm->dead = true;
+               spin_unlock(&mm->page_table_lock);
+               hmm_put(hmm);
+               return;
        }
-       up_read(&hmm->mirrors_sem);
 
-       return 0;
+       spin_unlock(&mm->page_table_lock);
 }
 
 static void hmm_release(struct mmu_notifier *mn, struct mm_struct *mm)
 {
+       struct hmm *hmm = mm_get_hmm(mm);
        struct hmm_mirror *mirror;
-       struct hmm *hmm = mm->hmm;
+       struct hmm_range *range;
+
+       /* Report this HMM as dying. */
+       hmm->dead = true;
+
+       /* Wake-up everyone waiting on any range. */
+       mutex_lock(&hmm->lock);
+       list_for_each_entry(range, &hmm->ranges, list) {
+               range->valid = false;
+       }
+       wake_up_all(&hmm->wq);
+       mutex_unlock(&hmm->lock);
 
        down_write(&hmm->mirrors_sem);
        mirror = list_first_entry_or_null(&hmm->mirrors, struct hmm_mirror,
@@ -186,36 +187,86 @@ static void hmm_release(struct mmu_notifier *mn, struct mm_struct *mm)
                                                  struct hmm_mirror, list);
        }
        up_write(&hmm->mirrors_sem);
+
+       hmm_put(hmm);
 }
 
 static int hmm_invalidate_range_start(struct mmu_notifier *mn,
-                       const struct mmu_notifier_range *range)
+                       const struct mmu_notifier_range *nrange)
 {
+       struct hmm *hmm = mm_get_hmm(nrange->mm);
+       struct hmm_mirror *mirror;
        struct hmm_update update;
-       struct hmm *hmm = range->mm->hmm;
+       struct hmm_range *range;
+       int ret = 0;
 
        VM_BUG_ON(!hmm);
 
-       update.start = range->start;
-       update.end = range->end;
+       update.start = nrange->start;
+       update.end = nrange->end;
        update.event = HMM_UPDATE_INVALIDATE;
-       update.blockable = range->blockable;
-       return hmm_invalidate_range(hmm, true, &update);
+       update.blockable = mmu_notifier_range_blockable(nrange);
+
+       if (mmu_notifier_range_blockable(nrange))
+               mutex_lock(&hmm->lock);
+       else if (!mutex_trylock(&hmm->lock)) {
+               ret = -EAGAIN;
+               goto out;
+       }
+       hmm->notifiers++;
+       list_for_each_entry(range, &hmm->ranges, list) {
+               if (update.end < range->start || update.start >= range->end)
+                       continue;
+
+               range->valid = false;
+       }
+       mutex_unlock(&hmm->lock);
+
+       if (mmu_notifier_range_blockable(nrange))
+               down_read(&hmm->mirrors_sem);
+       else if (!down_read_trylock(&hmm->mirrors_sem)) {
+               ret = -EAGAIN;
+               goto out;
+       }
+       list_for_each_entry(mirror, &hmm->mirrors, list) {
+               int ret;
+
+               ret = mirror->ops->sync_cpu_device_pagetables(mirror, &update);
+               if (!update.blockable && ret == -EAGAIN) {
+                       up_read(&hmm->mirrors_sem);
+                       ret = -EAGAIN;
+                       goto out;
+               }
+       }
+       up_read(&hmm->mirrors_sem);
+
+out:
+       hmm_put(hmm);
+       return ret;
 }
 
 static void hmm_invalidate_range_end(struct mmu_notifier *mn,
-                       const struct mmu_notifier_range *range)
+                       const struct mmu_notifier_range *nrange)
 {
-       struct hmm_update update;
-       struct hmm *hmm = range->mm->hmm;
+       struct hmm *hmm = mm_get_hmm(nrange->mm);
 
        VM_BUG_ON(!hmm);
 
-       update.start = range->start;
-       update.end = range->end;
-       update.event = HMM_UPDATE_INVALIDATE;
-       update.blockable = true;
-       hmm_invalidate_range(hmm, false, &update);
+       mutex_lock(&hmm->lock);
+       hmm->notifiers--;
+       if (!hmm->notifiers) {
+               struct hmm_range *range;
+
+               list_for_each_entry(range, &hmm->ranges, list) {
+                       if (range->valid)
+                               continue;
+                       range->valid = true;
+               }
+               wake_up_all(&hmm->wq);
+       }
+       mutex_unlock(&hmm->lock);
+
+       hmm_put(hmm);
 }
 
 static const struct mmu_notifier_ops hmm_mmu_notifier_ops = {
@@ -241,24 +292,13 @@ int hmm_mirror_register(struct hmm_mirror *mirror, struct mm_struct *mm)
        if (!mm || !mirror || !mirror->ops)
                return -EINVAL;
 
-again:
-       mirror->hmm = hmm_register(mm);
+       mirror->hmm = hmm_get_or_create(mm);
        if (!mirror->hmm)
                return -ENOMEM;
 
        down_write(&mirror->hmm->mirrors_sem);
-       if (mirror->hmm->mm == NULL) {
-               /*
-                * A racing hmm_mirror_unregister() is about to destroy the hmm
-                * struct. Try again to allocate a new one.
-                */
-               up_write(&mirror->hmm->mirrors_sem);
-               mirror->hmm = NULL;
-               goto again;
-       } else {
-               list_add(&mirror->list, &mirror->hmm->mirrors);
-               up_write(&mirror->hmm->mirrors_sem);
-       }
+       list_add(&mirror->list, &mirror->hmm->mirrors);
+       up_write(&mirror->hmm->mirrors_sem);
 
        return 0;
 }
@@ -273,38 +313,24 @@ EXPORT_SYMBOL(hmm_mirror_register);
  */
 void hmm_mirror_unregister(struct hmm_mirror *mirror)
 {
-       bool should_unregister = false;
-       struct mm_struct *mm;
-       struct hmm *hmm;
+       struct hmm *hmm = READ_ONCE(mirror->hmm);
 
-       if (mirror->hmm == NULL)
+       if (hmm == NULL)
                return;
 
-       hmm = mirror->hmm;
        down_write(&hmm->mirrors_sem);
        list_del_init(&mirror->list);
-       should_unregister = list_empty(&hmm->mirrors);
+       /* To protect us against double unregister ... */
        mirror->hmm = NULL;
-       mm = hmm->mm;
-       hmm->mm = NULL;
        up_write(&hmm->mirrors_sem);
 
-       if (!should_unregister || mm == NULL)
-               return;
-
-       mmu_notifier_unregister_no_release(&hmm->mmu_notifier, mm);
-
-       spin_lock(&mm->page_table_lock);
-       if (mm->hmm == hmm)
-               mm->hmm = NULL;
-       spin_unlock(&mm->page_table_lock);
-
-       kfree(hmm);
+       hmm_put(hmm);
 }
 EXPORT_SYMBOL(hmm_mirror_unregister);
 
 struct hmm_vma_walk {
        struct hmm_range        *range;
+       struct dev_pagemap      *pgmap;
        unsigned long           last;
        bool                    fault;
        bool                    block;
@@ -323,13 +349,13 @@ static int hmm_vma_do_fault(struct mm_walk *walk, unsigned long addr,
        flags |= write_fault ? FAULT_FLAG_WRITE : 0;
        ret = handle_mm_fault(vma, addr, flags);
        if (ret & VM_FAULT_RETRY)
-               return -EBUSY;
+               return -EAGAIN;
        if (ret & VM_FAULT_ERROR) {
                *pfn = range->values[HMM_PFN_ERROR];
                return -EFAULT;
        }
 
-       return -EAGAIN;
+       return -EBUSY;
 }
 
 static int hmm_pfns_bad(unsigned long addr,
@@ -355,7 +381,7 @@ static int hmm_pfns_bad(unsigned long addr,
  * @fault: should we fault or not ?
  * @write_fault: write fault ?
  * @walk: mm_walk structure
- * Returns: 0 on success, -EAGAIN after page fault, or page fault error
+ * Returns: 0 on success, -EBUSY after page fault, or page fault error
  *
  * This function will be called whenever pmd_none() or pte_none() returns true,
  * or whenever there is no page directory covering the virtual address range.
@@ -367,23 +393,25 @@ static int hmm_vma_walk_hole_(unsigned long addr, unsigned long end,
        struct hmm_vma_walk *hmm_vma_walk = walk->private;
        struct hmm_range *range = hmm_vma_walk->range;
        uint64_t *pfns = range->pfns;
-       unsigned long i;
+       unsigned long i, page_size;
 
        hmm_vma_walk->last = addr;
-       i = (addr - range->start) >> PAGE_SHIFT;
-       for (; addr < end; addr += PAGE_SIZE, i++) {
+       page_size = hmm_range_page_size(range);
+       i = (addr - range->start) >> range->page_shift;
+
+       for (; addr < end; addr += page_size, i++) {
                pfns[i] = range->values[HMM_PFN_NONE];
                if (fault || write_fault) {
                        int ret;
 
                        ret = hmm_vma_do_fault(walk, addr, write_fault,
                                               &pfns[i]);
-                       if (ret != -EAGAIN)
+                       if (ret != -EBUSY)
                                return ret;
                }
        }
 
-       return (fault || write_fault) ? -EAGAIN : 0;
+       return (fault || write_fault) ? -EBUSY : 0;
 }
 
 static inline void hmm_pte_need_fault(const struct hmm_vma_walk *hmm_vma_walk,
@@ -392,10 +420,21 @@ static inline void hmm_pte_need_fault(const struct hmm_vma_walk *hmm_vma_walk,
 {
        struct hmm_range *range = hmm_vma_walk->range;
 
-       *fault = *write_fault = false;
        if (!hmm_vma_walk->fault)
                return;
 
+       /*
+        * So we not only consider the individual per page request we also
+        * consider the default flags requested for the range. The API can
+        * be use in 2 fashions. The first one where the HMM user coalesce
+        * multiple page fault into one request and set flags per pfns for
+        * of those faults. The second one where the HMM user want to pre-
+        * fault a range with specific flags. For the latter one it is a
+        * waste to have the user pre-fill the pfn arrays with a default
+        * flags value.
+        */
+       pfns = (pfns & range->pfn_flags_mask) | range->default_flags;
+
        /* We aren't ask to do anything ... */
        if (!(pfns & range->flags[HMM_PFN_VALID]))
                return;
@@ -431,10 +470,11 @@ static void hmm_range_need_fault(const struct hmm_vma_walk *hmm_vma_walk,
                return;
        }
 
+       *fault = *write_fault = false;
        for (i = 0; i < npages; ++i) {
                hmm_pte_need_fault(hmm_vma_walk, pfns[i], cpu_flags,
                                   fault, write_fault);
-               if ((*fault) || (*write_fault))
+               if ((*write_fault))
                        return;
        }
 }
@@ -465,12 +505,22 @@ static inline uint64_t pmd_to_hmm_pfn_flags(struct hmm_range *range, pmd_t pmd)
                                range->flags[HMM_PFN_VALID];
 }
 
+static inline uint64_t pud_to_hmm_pfn_flags(struct hmm_range *range, pud_t pud)
+{
+       if (!pud_present(pud))
+               return 0;
+       return pud_write(pud) ? range->flags[HMM_PFN_VALID] |
+                               range->flags[HMM_PFN_WRITE] :
+                               range->flags[HMM_PFN_VALID];
+}
+
 static int hmm_vma_handle_pmd(struct mm_walk *walk,
                              unsigned long addr,
                              unsigned long end,
                              uint64_t *pfns,
                              pmd_t pmd)
 {
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
        struct hmm_vma_walk *hmm_vma_walk = walk->private;
        struct hmm_range *range = hmm_vma_walk->range;
        unsigned long pfn, npages, i;
@@ -486,10 +536,25 @@ static int hmm_vma_handle_pmd(struct mm_walk *walk,
                return hmm_vma_walk_hole_(addr, end, fault, write_fault, walk);
 
        pfn = pmd_pfn(pmd) + pte_index(addr);
-       for (i = 0; addr < end; addr += PAGE_SIZE, i++, pfn++)
-               pfns[i] = hmm_pfn_from_pfn(range, pfn) | cpu_flags;
+       for (i = 0; addr < end; addr += PAGE_SIZE, i++, pfn++) {
+               if (pmd_devmap(pmd)) {
+                       hmm_vma_walk->pgmap = get_dev_pagemap(pfn,
+                                             hmm_vma_walk->pgmap);
+                       if (unlikely(!hmm_vma_walk->pgmap))
+                               return -EBUSY;
+               }
+               pfns[i] = hmm_device_entry_from_pfn(range, pfn) | cpu_flags;
+       }
+       if (hmm_vma_walk->pgmap) {
+               put_dev_pagemap(hmm_vma_walk->pgmap);
+               hmm_vma_walk->pgmap = NULL;
+       }
        hmm_vma_walk->last = end;
        return 0;
+#else
+       /* If THP is not enabled then we should never reach that code ! */
+       return -EINVAL;
+#endif
 }
 
 static inline uint64_t pte_to_hmm_pfn_flags(struct hmm_range *range, pte_t pte)
@@ -514,11 +579,11 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
        uint64_t orig_pfn = *pfn;
 
        *pfn = range->values[HMM_PFN_NONE];
-       cpu_flags = pte_to_hmm_pfn_flags(range, pte);
-       hmm_pte_need_fault(hmm_vma_walk, orig_pfn, cpu_flags,
-                          &fault, &write_fault);
+       fault = write_fault = false;
 
        if (pte_none(pte)) {
+               hmm_pte_need_fault(hmm_vma_walk, orig_pfn, 0,
+                                  &fault, &write_fault);
                if (fault || write_fault)
                        goto fault;
                return 0;
@@ -546,7 +611,8 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
                                           &fault, &write_fault);
                        if (fault || write_fault)
                                goto fault;
-                       *pfn = hmm_pfn_from_pfn(range, swp_offset(entry));
+                       *pfn = hmm_device_entry_from_pfn(range,
+                                           swp_offset(entry));
                        *pfn |= cpu_flags;
                        return 0;
                }
@@ -557,7 +623,7 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
                                hmm_vma_walk->last = addr;
                                migration_entry_wait(vma->vm_mm,
                                                     pmdp, addr);
-                               return -EAGAIN;
+                               return -EBUSY;
                        }
                        return 0;
                }
@@ -565,15 +631,33 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
                /* Report error for everything else */
                *pfn = range->values[HMM_PFN_ERROR];
                return -EFAULT;
+       } else {
+               cpu_flags = pte_to_hmm_pfn_flags(range, pte);
+               hmm_pte_need_fault(hmm_vma_walk, orig_pfn, cpu_flags,
+                                  &fault, &write_fault);
        }
 
        if (fault || write_fault)
                goto fault;
 
-       *pfn = hmm_pfn_from_pfn(range, pte_pfn(pte)) | cpu_flags;
+       if (pte_devmap(pte)) {
+               hmm_vma_walk->pgmap = get_dev_pagemap(pte_pfn(pte),
+                                             hmm_vma_walk->pgmap);
+               if (unlikely(!hmm_vma_walk->pgmap))
+                       return -EBUSY;
+       } else if (IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL) && pte_special(pte)) {
+               *pfn = range->values[HMM_PFN_SPECIAL];
+               return -EFAULT;
+       }
+
+       *pfn = hmm_device_entry_from_pfn(range, pte_pfn(pte)) | cpu_flags;
        return 0;
 
 fault:
+       if (hmm_vma_walk->pgmap) {
+               put_dev_pagemap(hmm_vma_walk->pgmap);
+               hmm_vma_walk->pgmap = NULL;
+       }
        pte_unmap(ptep);
        /* Fault any virtual address we were asked to fault */
        return hmm_vma_walk_hole_(addr, end, fault, write_fault, walk);
@@ -615,7 +699,7 @@ again:
                if (fault || write_fault) {
                        hmm_vma_walk->last = addr;
                        pmd_migration_entry_wait(vma->vm_mm, pmdp);
-                       return -EAGAIN;
+                       return -EBUSY;
                }
                return 0;
        } else if (!pmd_present(pmd))
@@ -661,12 +745,158 @@ again:
                        return r;
                }
        }
+       if (hmm_vma_walk->pgmap) {
+               /*
+                * We do put_dev_pagemap() here and not in hmm_vma_handle_pte()
+                * so that we can leverage get_dev_pagemap() optimization which
+                * will not re-take a reference on a pgmap if we already have
+                * one.
+                */
+               put_dev_pagemap(hmm_vma_walk->pgmap);
+               hmm_vma_walk->pgmap = NULL;
+       }
        pte_unmap(ptep - 1);
 
        hmm_vma_walk->last = addr;
        return 0;
 }
 
+static int hmm_vma_walk_pud(pud_t *pudp,
+                           unsigned long start,
+                           unsigned long end,
+                           struct mm_walk *walk)
+{
+       struct hmm_vma_walk *hmm_vma_walk = walk->private;
+       struct hmm_range *range = hmm_vma_walk->range;
+       unsigned long addr = start, next;
+       pmd_t *pmdp;
+       pud_t pud;
+       int ret;
+
+again:
+       pud = READ_ONCE(*pudp);
+       if (pud_none(pud))
+               return hmm_vma_walk_hole(start, end, walk);
+
+       if (pud_huge(pud) && pud_devmap(pud)) {
+               unsigned long i, npages, pfn;
+               uint64_t *pfns, cpu_flags;
+               bool fault, write_fault;
+
+               if (!pud_present(pud))
+                       return hmm_vma_walk_hole(start, end, walk);
+
+               i = (addr - range->start) >> PAGE_SHIFT;
+               npages = (end - addr) >> PAGE_SHIFT;
+               pfns = &range->pfns[i];
+
+               cpu_flags = pud_to_hmm_pfn_flags(range, pud);
+               hmm_range_need_fault(hmm_vma_walk, pfns, npages,
+                                    cpu_flags, &fault, &write_fault);
+               if (fault || write_fault)
+                       return hmm_vma_walk_hole_(addr, end, fault,
+                                               write_fault, walk);
+
+#ifdef CONFIG_HUGETLB_PAGE
+               pfn = pud_pfn(pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT);
+               for (i = 0; i < npages; ++i, ++pfn) {
+                       hmm_vma_walk->pgmap = get_dev_pagemap(pfn,
+                                             hmm_vma_walk->pgmap);
+                       if (unlikely(!hmm_vma_walk->pgmap))
+                               return -EBUSY;
+                       pfns[i] = hmm_device_entry_from_pfn(range, pfn) |
+                                 cpu_flags;
+               }
+               if (hmm_vma_walk->pgmap) {
+                       put_dev_pagemap(hmm_vma_walk->pgmap);
+                       hmm_vma_walk->pgmap = NULL;
+               }
+               hmm_vma_walk->last = end;
+               return 0;
+#else
+               return -EINVAL;
+#endif
+       }
+
+       split_huge_pud(walk->vma, pudp, addr);
+       if (pud_none(*pudp))
+               goto again;
+
+       pmdp = pmd_offset(pudp, addr);
+       do {
+               next = pmd_addr_end(addr, end);
+               ret = hmm_vma_walk_pmd(pmdp, addr, next, walk);
+               if (ret)
+                       return ret;
+       } while (pmdp++, addr = next, addr != end);
+
+       return 0;
+}
+
+static int hmm_vma_walk_hugetlb_entry(pte_t *pte, unsigned long hmask,
+                                     unsigned long start, unsigned long end,
+                                     struct mm_walk *walk)
+{
+#ifdef CONFIG_HUGETLB_PAGE
+       unsigned long addr = start, i, pfn, mask, size, pfn_inc;
+       struct hmm_vma_walk *hmm_vma_walk = walk->private;
+       struct hmm_range *range = hmm_vma_walk->range;
+       struct vm_area_struct *vma = walk->vma;
+       struct hstate *h = hstate_vma(vma);
+       uint64_t orig_pfn, cpu_flags;
+       bool fault, write_fault;
+       spinlock_t *ptl;
+       pte_t entry;
+       int ret = 0;
+
+       size = 1UL << huge_page_shift(h);
+       mask = size - 1;
+       if (range->page_shift != PAGE_SHIFT) {
+               /* Make sure we are looking at full page. */
+               if (start & mask)
+                       return -EINVAL;
+               if (end < (start + size))
+                       return -EINVAL;
+               pfn_inc = size >> PAGE_SHIFT;
+       } else {
+               pfn_inc = 1;
+               size = PAGE_SIZE;
+       }
+
+
+       ptl = huge_pte_lock(hstate_vma(walk->vma), walk->mm, pte);
+       entry = huge_ptep_get(pte);
+
+       i = (start - range->start) >> range->page_shift;
+       orig_pfn = range->pfns[i];
+       range->pfns[i] = range->values[HMM_PFN_NONE];
+       cpu_flags = pte_to_hmm_pfn_flags(range, entry);
+       fault = write_fault = false;
+       hmm_pte_need_fault(hmm_vma_walk, orig_pfn, cpu_flags,
+                          &fault, &write_fault);
+       if (fault || write_fault) {
+               ret = -ENOENT;
+               goto unlock;
+       }
+
+       pfn = pte_pfn(entry) + ((start & mask) >> range->page_shift);
+       for (; addr < end; addr += size, i++, pfn += pfn_inc)
+               range->pfns[i] = hmm_device_entry_from_pfn(range, pfn) |
+                                cpu_flags;
+       hmm_vma_walk->last = end;
+
+unlock:
+       spin_unlock(ptl);
+
+       if (ret == -ENOENT)
+               return hmm_vma_walk_hole_(addr, end, fault, write_fault, walk);
+
+       return ret;
+#else /* CONFIG_HUGETLB_PAGE */
+       return -EINVAL;
+#endif
+}
+
 static void hmm_pfns_clear(struct hmm_range *range,
                           uint64_t *pfns,
                           unsigned long addr,
@@ -676,279 +906,437 @@ static void hmm_pfns_clear(struct hmm_range *range,
                *pfns = range->values[HMM_PFN_NONE];
 }
 
-static void hmm_pfns_special(struct hmm_range *range)
-{
-       unsigned long addr = range->start, i = 0;
-
-       for (; addr < range->end; addr += PAGE_SIZE, i++)
-               range->pfns[i] = range->values[HMM_PFN_SPECIAL];
-}
-
 /*
- * hmm_vma_get_pfns() - snapshot CPU page table for a range of virtual addresses
- * @range: range being snapshotted
- * Returns: -EINVAL if invalid argument, -ENOMEM out of memory, -EPERM invalid
- *          vma permission, 0 success
- *
- * This snapshots the CPU page table for a range of virtual addresses. Snapshot
- * validity is tracked by range struct. See hmm_vma_range_done() for further
- * information.
- *
- * The range struct is initialized here. It tracks the CPU page table, but only
- * if the function returns success (0), in which case the caller must then call
- * hmm_vma_range_done() to stop CPU page table update tracking on this range.
+ * hmm_range_register() - start tracking change to CPU page table over a range
+ * @range: range
+ * @mm: the mm struct for the range of virtual address
+ * @start: start virtual address (inclusive)
+ * @end: end virtual address (exclusive)
+ * @page_shift: expect page shift for the range
+ * Returns 0 on success, -EFAULT if the address space is no longer valid
  *
- * NOT CALLING hmm_vma_range_done() IF FUNCTION RETURNS 0 WILL LEAD TO SERIOUS
- * MEMORY CORRUPTION ! YOU HAVE BEEN WARNED !
+ * Track updates to the CPU page table see include/linux/hmm.h
  */
-int hmm_vma_get_pfns(struct hmm_range *range)
+int hmm_range_register(struct hmm_range *range,
+                      struct mm_struct *mm,
+                      unsigned long start,
+                      unsigned long end,
+                      unsigned page_shift)
 {
-       struct vm_area_struct *vma = range->vma;
-       struct hmm_vma_walk hmm_vma_walk;
-       struct mm_walk mm_walk;
-       struct hmm *hmm;
+       unsigned long mask = ((1UL << page_shift) - 1UL);
+
+       range->valid = false;
+       range->hmm = NULL;
 
-       /* Sanity check, this really should not happen ! */
-       if (range->start < vma->vm_start || range->start >= vma->vm_end)
+       if ((start & mask) || (end & mask))
                return -EINVAL;
-       if (range->end < vma->vm_start || range->end > vma->vm_end)
+       if (start >= end)
                return -EINVAL;
 
-       hmm = hmm_register(vma->vm_mm);
-       if (!hmm)
-               return -ENOMEM;
-       /* Caller must have registered a mirror, via hmm_mirror_register() ! */
-       if (!hmm->mmu_notifier.ops)
-               return -EINVAL;
+       range->page_shift = page_shift;
+       range->start = start;
+       range->end = end;
 
-       /* FIXME support hugetlb fs */
-       if (is_vm_hugetlb_page(vma) || (vma->vm_flags & VM_SPECIAL) ||
-                       vma_is_dax(vma)) {
-               hmm_pfns_special(range);
-               return -EINVAL;
-       }
+       range->hmm = hmm_get_or_create(mm);
+       if (!range->hmm)
+               return -EFAULT;
 
-       if (!(vma->vm_flags & VM_READ)) {
-               /*
-                * If vma do not allow read access, then assume that it does
-                * not allow write access, either. Architecture that allow
-                * write without read access are not supported by HMM, because
-                * operations such has atomic access would not work.
-                */
-               hmm_pfns_clear(range, range->pfns, range->start, range->end);
-               return -EPERM;
+       /* Check if hmm_mm_destroy() was call. */
+       if (range->hmm->mm == NULL || range->hmm->dead) {
+               hmm_put(range->hmm);
+               return -EFAULT;
        }
 
        /* Initialize range to track CPU page table update */
-       spin_lock(&hmm->lock);
-       range->valid = true;
-       list_add_rcu(&range->list, &hmm->ranges);
-       spin_unlock(&hmm->lock);
-
-       hmm_vma_walk.fault = false;
-       hmm_vma_walk.range = range;
-       mm_walk.private = &hmm_vma_walk;
-
-       mm_walk.vma = vma;
-       mm_walk.mm = vma->vm_mm;
-       mm_walk.pte_entry = NULL;
-       mm_walk.test_walk = NULL;
-       mm_walk.hugetlb_entry = NULL;
-       mm_walk.pmd_entry = hmm_vma_walk_pmd;
-       mm_walk.pte_hole = hmm_vma_walk_hole;
-
-       walk_page_range(range->start, range->end, &mm_walk);
+       mutex_lock(&range->hmm->lock);
+
+       list_add_rcu(&range->list, &range->hmm->ranges);
+
+       /*
+        * If there are any concurrent notifiers we have to wait for them for
+        * the range to be valid (see hmm_range_wait_until_valid()).
+        */
+       if (!range->hmm->notifiers)
+               range->valid = true;
+       mutex_unlock(&range->hmm->lock);
+
        return 0;
 }
-EXPORT_SYMBOL(hmm_vma_get_pfns);
+EXPORT_SYMBOL(hmm_range_register);
 
 /*
- * hmm_vma_range_done() - stop tracking change to CPU page table over a range
- * @range: range being tracked
- * Returns: false if range data has been invalidated, true otherwise
+ * hmm_range_unregister() - stop tracking change to CPU page table over a range
+ * @range: range
  *
  * Range struct is used to track updates to the CPU page table after a call to
- * either hmm_vma_get_pfns() or hmm_vma_fault(). Once the device driver is done
- * using the data,  or wants to lock updates to the data it got from those
- * functions, it must call the hmm_vma_range_done() function, which will then
- * stop tracking CPU page table updates.
- *
- * Note that device driver must still implement general CPU page table update
- * tracking either by using hmm_mirror (see hmm_mirror_register()) or by using
- * the mmu_notifier API directly.
- *
- * CPU page table update tracking done through hmm_range is only temporary and
- * to be used while trying to duplicate CPU page table contents for a range of
- * virtual addresses.
- *
- * There are two ways to use this :
- * again:
- *   hmm_vma_get_pfns(range); or hmm_vma_fault(...);
- *   trans = device_build_page_table_update_transaction(pfns);
- *   device_page_table_lock();
- *   if (!hmm_vma_range_done(range)) {
- *     device_page_table_unlock();
- *     goto again;
- *   }
- *   device_commit_transaction(trans);
- *   device_page_table_unlock();
+ * hmm_range_register(). See include/linux/hmm.h for how to use it.
+ */
+void hmm_range_unregister(struct hmm_range *range)
+{
+       /* Sanity check this really should not happen. */
+       if (range->hmm == NULL || range->end <= range->start)
+               return;
+
+       mutex_lock(&range->hmm->lock);
+       list_del_rcu(&range->list);
+       mutex_unlock(&range->hmm->lock);
+
+       /* Drop reference taken by hmm_range_register() */
+       range->valid = false;
+       hmm_put(range->hmm);
+       range->hmm = NULL;
+}
+EXPORT_SYMBOL(hmm_range_unregister);
+
+/*
+ * hmm_range_snapshot() - snapshot CPU page table for a range
+ * @range: range
+ * Returns: -EINVAL if invalid argument, -ENOMEM out of memory, -EPERM invalid
+ *          permission (for instance asking for write and range is read only),
+ *          -EAGAIN if you need to retry, -EFAULT invalid (ie either no valid
+ *          vma or it is illegal to access that range), number of valid pages
+ *          in range->pfns[] (from range start address).
  *
- * Or:
- *   hmm_vma_get_pfns(range); or hmm_vma_fault(...);
- *   device_page_table_lock();
- *   hmm_vma_range_done(range);
- *   device_update_page_table(range->pfns);
- *   device_page_table_unlock();
+ * This snapshots the CPU page table for a range of virtual addresses. Snapshot
+ * validity is tracked by range struct. See in include/linux/hmm.h for example
+ * on how to use.
  */
-bool hmm_vma_range_done(struct hmm_range *range)
+long hmm_range_snapshot(struct hmm_range *range)
 {
-       unsigned long npages = (range->end - range->start) >> PAGE_SHIFT;
-       struct hmm *hmm;
+       const unsigned long device_vma = VM_IO | VM_PFNMAP | VM_MIXEDMAP;
+       unsigned long start = range->start, end;
+       struct hmm_vma_walk hmm_vma_walk;
+       struct hmm *hmm = range->hmm;
+       struct vm_area_struct *vma;
+       struct mm_walk mm_walk;
 
-       if (range->end <= range->start) {
-               BUG();
-               return false;
-       }
+       /* Check if hmm_mm_destroy() was call. */
+       if (hmm->mm == NULL || hmm->dead)
+               return -EFAULT;
 
-       hmm = hmm_register(range->vma->vm_mm);
-       if (!hmm) {
-               memset(range->pfns, 0, sizeof(*range->pfns) * npages);
-               return false;
-       }
+       do {
+               /* If range is no longer valid force retry. */
+               if (!range->valid)
+                       return -EAGAIN;
 
-       spin_lock(&hmm->lock);
-       list_del_rcu(&range->list);
-       spin_unlock(&hmm->lock);
+               vma = find_vma(hmm->mm, start);
+               if (vma == NULL || (vma->vm_flags & device_vma))
+                       return -EFAULT;
+
+               if (is_vm_hugetlb_page(vma)) {
+                       struct hstate *h = hstate_vma(vma);
 
-       return range->valid;
+                       if (huge_page_shift(h) != range->page_shift &&
+                           range->page_shift != PAGE_SHIFT)
+                               return -EINVAL;
+               } else {
+                       if (range->page_shift != PAGE_SHIFT)
+                               return -EINVAL;
+               }
+
+               if (!(vma->vm_flags & VM_READ)) {
+                       /*
+                        * If vma do not allow read access, then assume that it
+                        * does not allow write access, either. HMM does not
+                        * support architecture that allow write without read.
+                        */
+                       hmm_pfns_clear(range, range->pfns,
+                               range->start, range->end);
+                       return -EPERM;
+               }
+
+               range->vma = vma;
+               hmm_vma_walk.pgmap = NULL;
+               hmm_vma_walk.last = start;
+               hmm_vma_walk.fault = false;
+               hmm_vma_walk.range = range;
+               mm_walk.private = &hmm_vma_walk;
+               end = min(range->end, vma->vm_end);
+
+               mm_walk.vma = vma;
+               mm_walk.mm = vma->vm_mm;
+               mm_walk.pte_entry = NULL;
+               mm_walk.test_walk = NULL;
+               mm_walk.hugetlb_entry = NULL;
+               mm_walk.pud_entry = hmm_vma_walk_pud;
+               mm_walk.pmd_entry = hmm_vma_walk_pmd;
+               mm_walk.pte_hole = hmm_vma_walk_hole;
+               mm_walk.hugetlb_entry = hmm_vma_walk_hugetlb_entry;
+
+               walk_page_range(start, end, &mm_walk);
+               start = end;
+       } while (start < range->end);
+
+       return (hmm_vma_walk.last - range->start) >> PAGE_SHIFT;
 }
-EXPORT_SYMBOL(hmm_vma_range_done);
+EXPORT_SYMBOL(hmm_range_snapshot);
 
 /*
- * hmm_vma_fault() - try to fault some address in a virtual address range
+ * hmm_range_fault() - try to fault some address in a virtual address range
  * @range: range being faulted
  * @block: allow blocking on fault (if true it sleeps and do not drop mmap_sem)
- * Returns: 0 success, error otherwise (-EAGAIN means mmap_sem have been drop)
+ * Returns: number of valid pages in range->pfns[] (from range start
+ *          address). This may be zero. If the return value is negative,
+ *          then one of the following values may be returned:
+ *
+ *           -EINVAL  invalid arguments or mm or virtual address are in an
+ *                    invalid vma (for instance device file vma).
+ *           -ENOMEM: Out of memory.
+ *           -EPERM:  Invalid permission (for instance asking for write and
+ *                    range is read only).
+ *           -EAGAIN: If you need to retry and mmap_sem was drop. This can only
+ *                    happens if block argument is false.
+ *           -EBUSY:  If the the range is being invalidated and you should wait
+ *                    for invalidation to finish.
+ *           -EFAULT: Invalid (ie either no valid vma or it is illegal to access
+ *                    that range), number of valid pages in range->pfns[] (from
+ *                    range start address).
  *
  * This is similar to a regular CPU page fault except that it will not trigger
- * any memory migration if the memory being faulted is not accessible by CPUs.
+ * any memory migration if the memory being faulted is not accessible by CPUs
+ * and caller does not ask for migration.
  *
  * On error, for one virtual address in the range, the function will mark the
  * corresponding HMM pfn entry with an error flag.
- *
- * Expected use pattern:
- * retry:
- *   down_read(&mm->mmap_sem);
- *   // Find vma and address device wants to fault, initialize hmm_pfn_t
- *   // array accordingly
- *   ret = hmm_vma_fault(range, write, block);
- *   switch (ret) {
- *   case -EAGAIN:
- *     hmm_vma_range_done(range);
- *     // You might want to rate limit or yield to play nicely, you may
- *     // also commit any valid pfn in the array assuming that you are
- *     // getting true from hmm_vma_range_monitor_end()
- *     goto retry;
- *   case 0:
- *     break;
- *   case -ENOMEM:
- *   case -EINVAL:
- *   case -EPERM:
- *   default:
- *     // Handle error !
- *     up_read(&mm->mmap_sem)
- *     return;
- *   }
- *   // Take device driver lock that serialize device page table update
- *   driver_lock_device_page_table_update();
- *   hmm_vma_range_done(range);
- *   // Commit pfns we got from hmm_vma_fault()
- *   driver_unlock_device_page_table_update();
- *   up_read(&mm->mmap_sem)
- *
- * YOU MUST CALL hmm_vma_range_done() AFTER THIS FUNCTION RETURN SUCCESS (0)
- * BEFORE FREEING THE range struct OR YOU WILL HAVE SERIOUS MEMORY CORRUPTION !
- *
- * YOU HAVE BEEN WARNED !
  */
-int hmm_vma_fault(struct hmm_range *range, bool block)
+long hmm_range_fault(struct hmm_range *range, bool block)
 {
-       struct vm_area_struct *vma = range->vma;
-       unsigned long start = range->start;
+       const unsigned long device_vma = VM_IO | VM_PFNMAP | VM_MIXEDMAP;
+       unsigned long start = range->start, end;
        struct hmm_vma_walk hmm_vma_walk;
+       struct hmm *hmm = range->hmm;
+       struct vm_area_struct *vma;
        struct mm_walk mm_walk;
-       struct hmm *hmm;
        int ret;
 
-       /* Sanity check, this really should not happen ! */
-       if (range->start < vma->vm_start || range->start >= vma->vm_end)
-               return -EINVAL;
-       if (range->end < vma->vm_start || range->end > vma->vm_end)
-               return -EINVAL;
+       /* Check if hmm_mm_destroy() was call. */
+       if (hmm->mm == NULL || hmm->dead)
+               return -EFAULT;
 
-       hmm = hmm_register(vma->vm_mm);
-       if (!hmm) {
-               hmm_pfns_clear(range, range->pfns, range->start, range->end);
-               return -ENOMEM;
-       }
-       /* Caller must have registered a mirror using hmm_mirror_register() */
-       if (!hmm->mmu_notifier.ops)
-               return -EINVAL;
+       do {
+               /* If range is no longer valid force retry. */
+               if (!range->valid) {
+                       up_read(&hmm->mm->mmap_sem);
+                       return -EAGAIN;
+               }
 
-       /* FIXME support hugetlb fs */
-       if (is_vm_hugetlb_page(vma) || (vma->vm_flags & VM_SPECIAL) ||
-                       vma_is_dax(vma)) {
-               hmm_pfns_special(range);
-               return -EINVAL;
-       }
+               vma = find_vma(hmm->mm, start);
+               if (vma == NULL || (vma->vm_flags & device_vma))
+                       return -EFAULT;
+
+               if (is_vm_hugetlb_page(vma)) {
+                       if (huge_page_shift(hstate_vma(vma)) !=
+                           range->page_shift &&
+                           range->page_shift != PAGE_SHIFT)
+                               return -EINVAL;
+               } else {
+                       if (range->page_shift != PAGE_SHIFT)
+                               return -EINVAL;
+               }
+
+               if (!(vma->vm_flags & VM_READ)) {
+                       /*
+                        * If vma do not allow read access, then assume that it
+                        * does not allow write access, either. HMM does not
+                        * support architecture that allow write without read.
+                        */
+                       hmm_pfns_clear(range, range->pfns,
+                               range->start, range->end);
+                       return -EPERM;
+               }
+
+               range->vma = vma;
+               hmm_vma_walk.pgmap = NULL;
+               hmm_vma_walk.last = start;
+               hmm_vma_walk.fault = true;
+               hmm_vma_walk.block = block;
+               hmm_vma_walk.range = range;
+               mm_walk.private = &hmm_vma_walk;
+               end = min(range->end, vma->vm_end);
+
+               mm_walk.vma = vma;
+               mm_walk.mm = vma->vm_mm;
+               mm_walk.pte_entry = NULL;
+               mm_walk.test_walk = NULL;
+               mm_walk.hugetlb_entry = NULL;
+               mm_walk.pud_entry = hmm_vma_walk_pud;
+               mm_walk.pmd_entry = hmm_vma_walk_pmd;
+               mm_walk.pte_hole = hmm_vma_walk_hole;
+               mm_walk.hugetlb_entry = hmm_vma_walk_hugetlb_entry;
+
+               do {
+                       ret = walk_page_range(start, end, &mm_walk);
+                       start = hmm_vma_walk.last;
+
+                       /* Keep trying while the range is valid. */
+               } while (ret == -EBUSY && range->valid);
+
+               if (ret) {
+                       unsigned long i;
+
+                       i = (hmm_vma_walk.last - range->start) >> PAGE_SHIFT;
+                       hmm_pfns_clear(range, &range->pfns[i],
+                               hmm_vma_walk.last, range->end);
+                       return ret;
+               }
+               start = end;
+
+       } while (start < range->end);
+
+       return (hmm_vma_walk.last - range->start) >> PAGE_SHIFT;
+}
+EXPORT_SYMBOL(hmm_range_fault);
+
+/**
+ * hmm_range_dma_map() - hmm_range_fault() and dma map page all in one.
+ * @range: range being faulted
+ * @device: device against to dma map page to
+ * @daddrs: dma address of mapped pages
+ * @block: allow blocking on fault (if true it sleeps and do not drop mmap_sem)
+ * Returns: number of pages mapped on success, -EAGAIN if mmap_sem have been
+ *          drop and you need to try again, some other error value otherwise
+ *
+ * Note same usage pattern as hmm_range_fault().
+ */
+long hmm_range_dma_map(struct hmm_range *range,
+                      struct device *device,
+                      dma_addr_t *daddrs,
+                      bool block)
+{
+       unsigned long i, npages, mapped;
+       long ret;
+
+       ret = hmm_range_fault(range, block);
+       if (ret <= 0)
+               return ret ? ret : -EBUSY;
+
+       npages = (range->end - range->start) >> PAGE_SHIFT;
+       for (i = 0, mapped = 0; i < npages; ++i) {
+               enum dma_data_direction dir = DMA_TO_DEVICE;
+               struct page *page;
 
-       if (!(vma->vm_flags & VM_READ)) {
                /*
-                * If vma do not allow read access, then assume that it does
-                * not allow write access, either. Architecture that allow
-                * write without read access are not supported by HMM, because
-                * operations such has atomic access would not work.
+                * FIXME need to update DMA API to provide invalid DMA address
+                * value instead of a function to test dma address value. This
+                * would remove lot of dumb code duplicated accross many arch.
+                *
+                * For now setting it to 0 here is good enough as the pfns[]
+                * value is what is use to check what is valid and what isn't.
                 */
-               hmm_pfns_clear(range, range->pfns, range->start, range->end);
-               return -EPERM;
+               daddrs[i] = 0;
+
+               page = hmm_device_entry_to_page(range, range->pfns[i]);
+               if (page == NULL)
+                       continue;
+
+               /* Check if range is being invalidated */
+               if (!range->valid) {
+                       ret = -EBUSY;
+                       goto unmap;
+               }
+
+               /* If it is read and write than map bi-directional. */
+               if (range->pfns[i] & range->flags[HMM_PFN_WRITE])
+                       dir = DMA_BIDIRECTIONAL;
+
+               daddrs[i] = dma_map_page(device, page, 0, PAGE_SIZE, dir);
+               if (dma_mapping_error(device, daddrs[i])) {
+                       ret = -EFAULT;
+                       goto unmap;
+               }
+
+               mapped++;
        }
 
-       /* Initialize range to track CPU page table update */
-       spin_lock(&hmm->lock);
-       range->valid = true;
-       list_add_rcu(&range->list, &hmm->ranges);
-       spin_unlock(&hmm->lock);
-
-       hmm_vma_walk.fault = true;
-       hmm_vma_walk.block = block;
-       hmm_vma_walk.range = range;
-       mm_walk.private = &hmm_vma_walk;
-       hmm_vma_walk.last = range->start;
-
-       mm_walk.vma = vma;
-       mm_walk.mm = vma->vm_mm;
-       mm_walk.pte_entry = NULL;
-       mm_walk.test_walk = NULL;
-       mm_walk.hugetlb_entry = NULL;
-       mm_walk.pmd_entry = hmm_vma_walk_pmd;
-       mm_walk.pte_hole = hmm_vma_walk_hole;
+       return mapped;
 
-       do {
-               ret = walk_page_range(start, range->end, &mm_walk);
-               start = hmm_vma_walk.last;
-       } while (ret == -EAGAIN);
+unmap:
+       for (npages = i, i = 0; (i < npages) && mapped; ++i) {
+               enum dma_data_direction dir = DMA_TO_DEVICE;
+               struct page *page;
 
-       if (ret) {
-               unsigned long i;
+               page = hmm_device_entry_to_page(range, range->pfns[i]);
+               if (page == NULL)
+                       continue;
+
+               if (dma_mapping_error(device, daddrs[i]))
+                       continue;
 
-               i = (hmm_vma_walk.last - range->start) >> PAGE_SHIFT;
-               hmm_pfns_clear(range, &range->pfns[i], hmm_vma_walk.last,
-                              range->end);
-               hmm_vma_range_done(range);
+               /* If it is read and write than map bi-directional. */
+               if (range->pfns[i] & range->flags[HMM_PFN_WRITE])
+                       dir = DMA_BIDIRECTIONAL;
+
+               dma_unmap_page(device, daddrs[i], PAGE_SIZE, dir);
+               mapped--;
        }
+
        return ret;
 }
-EXPORT_SYMBOL(hmm_vma_fault);
+EXPORT_SYMBOL(hmm_range_dma_map);
+
+/**
+ * hmm_range_dma_unmap() - unmap range of that was map with hmm_range_dma_map()
+ * @range: range being unmapped
+ * @vma: the vma against which the range (optional)
+ * @device: device against which dma map was done
+ * @daddrs: dma address of mapped pages
+ * @dirty: dirty page if it had the write flag set
+ * Returns: number of page unmapped on success, -EINVAL otherwise
+ *
+ * Note that caller MUST abide by mmu notifier or use HMM mirror and abide
+ * to the sync_cpu_device_pagetables() callback so that it is safe here to
+ * call set_page_dirty(). Caller must also take appropriate locks to avoid
+ * concurrent mmu notifier or sync_cpu_device_pagetables() to make progress.
+ */
+long hmm_range_dma_unmap(struct hmm_range *range,
+                        struct vm_area_struct *vma,
+                        struct device *device,
+                        dma_addr_t *daddrs,
+                        bool dirty)
+{
+       unsigned long i, npages;
+       long cpages = 0;
+
+       /* Sanity check. */
+       if (range->end <= range->start)
+               return -EINVAL;
+       if (!daddrs)
+               return -EINVAL;
+       if (!range->pfns)
+               return -EINVAL;
+
+       npages = (range->end - range->start) >> PAGE_SHIFT;
+       for (i = 0; i < npages; ++i) {
+               enum dma_data_direction dir = DMA_TO_DEVICE;
+               struct page *page;
+
+               page = hmm_device_entry_to_page(range, range->pfns[i]);
+               if (page == NULL)
+                       continue;
+
+               /* If it is read and write than map bi-directional. */
+               if (range->pfns[i] & range->flags[HMM_PFN_WRITE]) {
+                       dir = DMA_BIDIRECTIONAL;
+
+                       /*
+                        * See comments in function description on why it is
+                        * safe here to call set_page_dirty()
+                        */
+                       if (dirty)
+                               set_page_dirty(page);
+               }
+
+               /* Unmap and clear pfns/dma address */
+               dma_unmap_page(device, daddrs[i], PAGE_SIZE, dir);
+               range->pfns[i] = range->values[HMM_PFN_NONE];
+               /* FIXME see comments in hmm_vma_dma_map() */
+               daddrs[i] = 0;
+               cpages++;
+       }
+
+       return cpages;
+}
+EXPORT_SYMBOL(hmm_range_dma_unmap);
 #endif /* IS_ENABLED(CONFIG_HMM_MIRROR) */
 
 
index b6a34b3..9f8bce9 100644 (file)
@@ -509,7 +509,7 @@ void prep_transhuge_page(struct page *page)
        set_compound_page_dtor(page, TRANSHUGE_PAGE_DTOR);
 }
 
-unsigned long __thp_get_unmapped_area(struct file *filp, unsigned long len,
+static unsigned long __thp_get_unmapped_area(struct file *filp, unsigned long len,
                loff_t off, unsigned long flags, unsigned long size)
 {
        unsigned long addr;
@@ -793,11 +793,13 @@ out_unlock:
                pte_free(mm, pgtable);
 }
 
-vm_fault_t vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
-                       pmd_t *pmd, pfn_t pfn, bool write)
+vm_fault_t vmf_insert_pfn_pmd(struct vm_fault *vmf, pfn_t pfn, bool write)
 {
+       unsigned long addr = vmf->address & PMD_MASK;
+       struct vm_area_struct *vma = vmf->vma;
        pgprot_t pgprot = vma->vm_page_prot;
        pgtable_t pgtable = NULL;
+
        /*
         * If we had pmd_special, we could avoid all these restrictions,
         * but we need to be consistent with PTEs and architectures that
@@ -820,7 +822,7 @@ vm_fault_t vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
 
        track_pfn_insert(vma, &pgprot, pfn);
 
-       insert_pfn_pmd(vma, addr, pmd, pfn, pgprot, write, pgtable);
+       insert_pfn_pmd(vma, addr, vmf->pmd, pfn, pgprot, write, pgtable);
        return VM_FAULT_NOPAGE;
 }
 EXPORT_SYMBOL_GPL(vmf_insert_pfn_pmd);
@@ -869,10 +871,12 @@ out_unlock:
        spin_unlock(ptl);
 }
 
-vm_fault_t vmf_insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,
-                       pud_t *pud, pfn_t pfn, bool write)
+vm_fault_t vmf_insert_pfn_pud(struct vm_fault *vmf, pfn_t pfn, bool write)
 {
+       unsigned long addr = vmf->address & PUD_MASK;
+       struct vm_area_struct *vma = vmf->vma;
        pgprot_t pgprot = vma->vm_page_prot;
+
        /*
         * If we had pud_special, we could avoid all these restrictions,
         * but we need to be consistent with PTEs and architectures that
@@ -889,7 +893,7 @@ vm_fault_t vmf_insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,
 
        track_pfn_insert(vma, &pgprot, pfn);
 
-       insert_pfn_pud(vma, addr, pud, pfn, pgprot, write);
+       insert_pfn_pud(vma, addr, vmf->pud, pfn, pgprot, write);
        return VM_FAULT_NOPAGE;
 }
 EXPORT_SYMBOL_GPL(vmf_insert_pfn_pud);
@@ -1220,8 +1224,8 @@ static vm_fault_t do_huge_pmd_wp_page_fallback(struct vm_fault *vmf,
                cond_resched();
        }
 
-       mmu_notifier_range_init(&range, vma->vm_mm, haddr,
-                               haddr + HPAGE_PMD_SIZE);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, vma->vm_mm,
+                               haddr, haddr + HPAGE_PMD_SIZE);
        mmu_notifier_invalidate_range_start(&range);
 
        vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd);
@@ -1384,8 +1388,8 @@ alloc:
                                    vma, HPAGE_PMD_NR);
        __SetPageUptodate(new_page);
 
-       mmu_notifier_range_init(&range, vma->vm_mm, haddr,
-                               haddr + HPAGE_PMD_SIZE);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, vma->vm_mm,
+                               haddr, haddr + HPAGE_PMD_SIZE);
        mmu_notifier_invalidate_range_start(&range);
 
        spin_lock(vmf->ptl);
@@ -2060,7 +2064,8 @@ void __split_huge_pud(struct vm_area_struct *vma, pud_t *pud,
        spinlock_t *ptl;
        struct mmu_notifier_range range;
 
-       mmu_notifier_range_init(&range, vma->vm_mm, address & HPAGE_PUD_MASK,
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, vma->vm_mm,
+                               address & HPAGE_PUD_MASK,
                                (address & HPAGE_PUD_MASK) + HPAGE_PUD_SIZE);
        mmu_notifier_invalidate_range_start(&range);
        ptl = pud_lock(vma->vm_mm, pud);
@@ -2278,7 +2283,8 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
        spinlock_t *ptl;
        struct mmu_notifier_range range;
 
-       mmu_notifier_range_init(&range, vma->vm_mm, address & HPAGE_PMD_MASK,
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, vma->vm_mm,
+                               address & HPAGE_PMD_MASK,
                                (address & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE);
        mmu_notifier_invalidate_range_start(&range);
        ptl = pmd_lock(vma->vm_mm, pmd);
@@ -2492,6 +2498,9 @@ static void __split_huge_page(struct page *page, struct list_head *list,
                        if (IS_ENABLED(CONFIG_SHMEM) && PageSwapBacked(head))
                                shmem_uncharge(head->mapping->host, 1);
                        put_page(head + i);
+               } else if (!PageAnon(page)) {
+                       __xa_store(&head->mapping->i_pages, head[i].index,
+                                       head + i, 0);
                }
        }
 
index 641cedf..81718c5 100644 (file)
@@ -740,7 +740,15 @@ void resv_map_release(struct kref *ref)
 
 static inline struct resv_map *inode_resv_map(struct inode *inode)
 {
-       return inode->i_mapping->private_data;
+       /*
+        * At inode evict time, i_mapping may not point to the original
+        * address space within the inode.  This original address space
+        * contains the pointer to the resv_map.  So, always use the
+        * address space embedded within the inode.
+        * The VERY common case is inode->mapping == &inode->i_data but,
+        * this may not be true for device special inodes.
+        */
+       return (struct resv_map *)(&inode->i_data)->private_data;
 }
 
 static struct resv_map *vma_resv_map(struct vm_area_struct *vma)
@@ -1059,6 +1067,7 @@ static void free_gigantic_page(struct page *page, unsigned int order)
        free_contig_range(page_to_pfn(page), 1 << order);
 }
 
+#ifdef CONFIG_CONTIG_ALLOC
 static int __alloc_gigantic_page(unsigned long start_pfn,
                                unsigned long nr_pages, gfp_t gfp_mask)
 {
@@ -1143,11 +1152,20 @@ static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask,
 
 static void prep_new_huge_page(struct hstate *h, struct page *page, int nid);
 static void prep_compound_gigantic_page(struct page *page, unsigned int order);
+#else /* !CONFIG_CONTIG_ALLOC */
+static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask,
+                                       int nid, nodemask_t *nodemask)
+{
+       return NULL;
+}
+#endif /* CONFIG_CONTIG_ALLOC */
 
 #else /* !CONFIG_ARCH_HAS_GIGANTIC_PAGE */
-static inline bool gigantic_page_supported(void) { return false; }
 static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask,
-               int nid, nodemask_t *nodemask) { return NULL; }
+                                       int nid, nodemask_t *nodemask)
+{
+       return NULL;
+}
 static inline void free_gigantic_page(struct page *page, unsigned int order) { }
 static inline void destroy_compound_gigantic_page(struct page *page,
                                                unsigned int order) { }
@@ -1157,7 +1175,7 @@ static void update_and_free_page(struct hstate *h, struct page *page)
 {
        int i;
 
-       if (hstate_is_gigantic(h) && !gigantic_page_supported())
+       if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported())
                return;
 
        h->nr_huge_pages--;
@@ -1258,12 +1276,23 @@ void free_huge_page(struct page *page)
        ClearPagePrivate(page);
 
        /*
-        * A return code of zero implies that the subpool will be under its
-        * minimum size if the reservation is not restored after page is free.
-        * Therefore, force restore_reserve operation.
+        * If PagePrivate() was set on page, page allocation consumed a
+        * reservation.  If the page was associated with a subpool, there
+        * would have been a page reserved in the subpool before allocation
+        * via hugepage_subpool_get_pages().  Since we are 'restoring' the
+        * reservtion, do not call hugepage_subpool_put_pages() as this will
+        * remove the reserved page from the subpool.
         */
-       if (hugepage_subpool_put_pages(spool, 1) == 0)
-               restore_reserve = true;
+       if (!restore_reserve) {
+               /*
+                * A return code of zero implies that the subpool will be
+                * under its minimum size if the reservation is not restored
+                * after page is free.  Therefore, force restore_reserve
+                * operation.
+                */
+               if (hugepage_subpool_put_pages(spool, 1) == 0)
+                       restore_reserve = true;
+       }
 
        spin_lock(&hugetlb_lock);
        clear_page_huge_active(page);
@@ -1574,8 +1603,9 @@ static struct page *alloc_surplus_huge_page(struct hstate *h, gfp_t gfp_mask,
         */
        if (h->surplus_huge_pages >= h->nr_overcommit_huge_pages) {
                SetPageHugeTemporary(page);
+               spin_unlock(&hugetlb_lock);
                put_page(page);
-               page = NULL;
+               return NULL;
        } else {
                h->surplus_huge_pages++;
                h->surplus_huge_pages_node[page_to_nid(page)]++;
@@ -2277,13 +2307,47 @@ found:
 }
 
 #define persistent_huge_pages(h) (h->nr_huge_pages - h->surplus_huge_pages)
-static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
-                                               nodemask_t *nodes_allowed)
+static int set_max_huge_pages(struct hstate *h, unsigned long count, int nid,
+                             nodemask_t *nodes_allowed)
 {
        unsigned long min_count, ret;
 
-       if (hstate_is_gigantic(h) && !gigantic_page_supported())
-               return h->max_huge_pages;
+       spin_lock(&hugetlb_lock);
+
+       /*
+        * Check for a node specific request.
+        * Changing node specific huge page count may require a corresponding
+        * change to the global count.  In any case, the passed node mask
+        * (nodes_allowed) will restrict alloc/free to the specified node.
+        */
+       if (nid != NUMA_NO_NODE) {
+               unsigned long old_count = count;
+
+               count += h->nr_huge_pages - h->nr_huge_pages_node[nid];
+               /*
+                * User may have specified a large count value which caused the
+                * above calculation to overflow.  In this case, they wanted
+                * to allocate as many huge pages as possible.  Set count to
+                * largest possible value to align with their intention.
+                */
+               if (count < old_count)
+                       count = ULONG_MAX;
+       }
+
+       /*
+        * Gigantic pages runtime allocation depend on the capability for large
+        * page range allocation.
+        * If the system does not provide this feature, return an error when
+        * the user tries to allocate gigantic pages but let the user free the
+        * boottime allocated gigantic pages.
+        */
+       if (hstate_is_gigantic(h) && !IS_ENABLED(CONFIG_CONTIG_ALLOC)) {
+               if (count > persistent_huge_pages(h)) {
+                       spin_unlock(&hugetlb_lock);
+                       return -EINVAL;
+               }
+               /* Fall through to decrease pool */
+       }
 
        /*
         * Increase the pool size
@@ -2296,7 +2360,6 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
         * pool might be one hugepage larger than it needs to be, but
         * within all the constraints specified by the sysctls.
         */
-       spin_lock(&hugetlb_lock);
        while (h->surplus_huge_pages && count > persistent_huge_pages(h)) {
                if (!adjust_pool_surplus(h, nodes_allowed, -1))
                        break;
@@ -2351,9 +2414,10 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
                        break;
        }
 out:
-       ret = persistent_huge_pages(h);
+       h->max_huge_pages = persistent_huge_pages(h);
        spin_unlock(&hugetlb_lock);
-       return ret;
+
+       return 0;
 }
 
 #define HSTATE_ATTR_RO(_name) \
@@ -2403,41 +2467,32 @@ static ssize_t __nr_hugepages_store_common(bool obey_mempolicy,
                                           unsigned long count, size_t len)
 {
        int err;
-       NODEMASK_ALLOC(nodemask_t, nodes_allowed, GFP_KERNEL | __GFP_NORETRY);
+       nodemask_t nodes_allowed, *n_mask;
 
-       if (hstate_is_gigantic(h) && !gigantic_page_supported()) {
-               err = -EINVAL;
-               goto out;
-       }
+       if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported())
+               return -EINVAL;
 
        if (nid == NUMA_NO_NODE) {
                /*
                 * global hstate attribute
                 */
                if (!(obey_mempolicy &&
-                               init_nodemask_of_mempolicy(nodes_allowed))) {
-                       NODEMASK_FREE(nodes_allowed);
-                       nodes_allowed = &node_states[N_MEMORY];
-               }
-       } else if (nodes_allowed) {
+                               init_nodemask_of_mempolicy(&nodes_allowed)))
+                       n_mask = &node_states[N_MEMORY];
+               else
+                       n_mask = &nodes_allowed;
+       } else {
                /*
-                * per node hstate attribute: adjust count to global,
-                * but restrict alloc/free to the specified node.
+                * Node specific request.  count adjustment happens in
+                * set_max_huge_pages() after acquiring hugetlb_lock.
                 */
-               count += h->nr_huge_pages - h->nr_huge_pages_node[nid];
-               init_nodemask_of_node(nodes_allowed, nid);
-       } else
-               nodes_allowed = &node_states[N_MEMORY];
-
-       h->max_huge_pages = set_max_huge_pages(h, count, nodes_allowed);
+               init_nodemask_of_node(&nodes_allowed, nid);
+               n_mask = &nodes_allowed;
+       }
 
-       if (nodes_allowed != &node_states[N_MEMORY])
-               NODEMASK_FREE(nodes_allowed);
+       err = set_max_huge_pages(h, count, nid, n_mask);
 
-       return len;
-out:
-       NODEMASK_FREE(nodes_allowed);
-       return err;
+       return err ? err : len;
 }
 
 static ssize_t nr_hugepages_store_common(bool obey_mempolicy,
@@ -3247,7 +3302,8 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
        cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
 
        if (cow) {
-               mmu_notifier_range_init(&range, src, vma->vm_start,
+               mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, src,
+                                       vma->vm_start,
                                        vma->vm_end);
                mmu_notifier_invalidate_range_start(&range);
        }
@@ -3359,7 +3415,8 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
        /*
         * If sharing possible, alert mmu notifiers of worst case.
         */
-       mmu_notifier_range_init(&range, mm, start, end);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_UNMAP, 0, vma, mm, start,
+                               end);
        adjust_range_if_pmd_sharing_possible(vma, &range.start, &range.end);
        mmu_notifier_invalidate_range_start(&range);
        address = start;
@@ -3626,7 +3683,8 @@ retry_avoidcopy:
                            pages_per_huge_page(h));
        __SetPageUptodate(new_page);
 
-       mmu_notifier_range_init(&range, mm, haddr, haddr + huge_page_size(h));
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, mm, haddr,
+                               haddr + huge_page_size(h));
        mmu_notifier_invalidate_range_start(&range);
 
        /*
@@ -3777,8 +3835,7 @@ retry:
                         * handling userfault.  Reacquire after handling
                         * fault to make calling code simpler.
                         */
-                       hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping,
-                                                       idx, haddr);
+                       hash = hugetlb_fault_mutex_hash(h, mapping, idx, haddr);
                        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
                        ret = handle_userfault(&vmf, VM_UFFD_MISSING);
                        mutex_lock(&hugetlb_fault_mutex_table[hash]);
@@ -3886,21 +3943,14 @@ backout_unlocked:
 }
 
 #ifdef CONFIG_SMP
-u32 hugetlb_fault_mutex_hash(struct hstate *h, struct mm_struct *mm,
-                           struct vm_area_struct *vma,
-                           struct address_space *mapping,
+u32 hugetlb_fault_mutex_hash(struct hstate *h, struct address_space *mapping,
                            pgoff_t idx, unsigned long address)
 {
        unsigned long key[2];
        u32 hash;
 
-       if (vma->vm_flags & VM_SHARED) {
-               key[0] = (unsigned long) mapping;
-               key[1] = idx;
-       } else {
-               key[0] = (unsigned long) mm;
-               key[1] = address >> huge_page_shift(h);
-       }
+       key[0] = (unsigned long) mapping;
+       key[1] = idx;
 
        hash = jhash2((u32 *)&key, sizeof(key)/sizeof(u32), 0);
 
@@ -3911,9 +3961,7 @@ u32 hugetlb_fault_mutex_hash(struct hstate *h, struct mm_struct *mm,
  * For uniprocesor systems we always use a single mutex, so just
  * return 0 and avoid the hashing overhead.
  */
-u32 hugetlb_fault_mutex_hash(struct hstate *h, struct mm_struct *mm,
-                           struct vm_area_struct *vma,
-                           struct address_space *mapping,
+u32 hugetlb_fault_mutex_hash(struct hstate *h, struct address_space *mapping,
                            pgoff_t idx, unsigned long address)
 {
        return 0;
@@ -3958,7 +4006,7 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
         * get spurious allocation failures if two CPUs race to instantiate
         * the same page in the page cache.
         */
-       hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping, idx, haddr);
+       hash = hugetlb_fault_mutex_hash(h, mapping, idx, haddr);
        mutex_lock(&hugetlb_fault_mutex_table[hash]);
 
        entry = huge_ptep_get(ptep);
@@ -4371,7 +4419,8 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
         * start/end.  Set range.start/range.end to cover the maximum possible
         * range if PMD sharing is possible.
         */
-       mmu_notifier_range_init(&range, mm, start, end);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_PROTECTION_VMA,
+                               0, vma, mm, start, end);
        adjust_range_if_pmd_sharing_possible(vma, &range.start, &range.end);
 
        BUG_ON(address >= end);
@@ -4477,6 +4526,11 @@ int hugetlb_reserve_pages(struct inode *inode,
         * called to make the mapping read-write. Assume !vma is a shm mapping
         */
        if (!vma || vma->vm_flags & VM_MAYSHARE) {
+               /*
+                * resv_map can not be NULL as hugetlb_reserve_pages is only
+                * called for inodes for which resv_maps were created (see
+                * hugetlbfs_get_inode).
+                */
                resv_map = inode_resv_map(inode);
 
                chg = region_chg(resv_map, from, to);
@@ -4568,6 +4622,10 @@ long hugetlb_unreserve_pages(struct inode *inode, long start, long end,
        struct hugepage_subpool *spool = subpool_inode(inode);
        long gbl_reserve;
 
+       /*
+        * Since this routine can be called in the evict inode path for all
+        * hugetlbfs inodes, resv_map could be NULL.
+        */
        if (resv_map) {
                chg = region_del(resv_map, start, end);
                /*
index 4490443..a335f7c 100644 (file)
@@ -1016,7 +1016,8 @@ static void collapse_huge_page(struct mm_struct *mm,
        pte = pte_offset_map(pmd, address);
        pte_ptl = pte_lockptr(mm, pmd);
 
-       mmu_notifier_range_init(&range, mm, address, address + HPAGE_PMD_SIZE);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, NULL, mm,
+                               address, address + HPAGE_PMD_SIZE);
        mmu_notifier_invalidate_range_start(&range);
        pmd_ptl = pmd_lock(mm, pmd); /* probably unnecessary */
        /*
@@ -1374,7 +1375,7 @@ static void collapse_shmem(struct mm_struct *mm,
                                result = SCAN_FAIL;
                                goto xa_locked;
                        }
-                       xas_store(&xas, new_page + (index % HPAGE_PMD_NR));
+                       xas_store(&xas, new_page);
                        nr_none++;
                        continue;
                }
@@ -1450,7 +1451,7 @@ static void collapse_shmem(struct mm_struct *mm,
                list_add_tail(&page->lru, &pagelist);
 
                /* Finally, replace with the new page. */
-               xas_store(&xas, new_page + (index % HPAGE_PMD_NR));
+               xas_store(&xas, new_page);
                continue;
 out_unlock:
                unlock_page(page);
index fc64874..81c20ed 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -1066,7 +1066,8 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
 
        BUG_ON(PageTransCompound(page));
 
-       mmu_notifier_range_init(&range, mm, pvmw.address,
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, mm,
+                               pvmw.address,
                                pvmw.address + PAGE_SIZE);
        mmu_notifier_invalidate_range_start(&range);
 
@@ -1154,7 +1155,8 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
        if (!pmd)
                goto out;
 
-       mmu_notifier_range_init(&range, mm, addr, addr + PAGE_SIZE);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, mm, addr,
+                               addr + PAGE_SIZE);
        mmu_notifier_invalidate_range_start(&range);
 
        ptep = pte_offset_map_lock(mm, pmd, addr, &ptl);
index bb3a455..628022e 100644 (file)
@@ -472,7 +472,8 @@ static int madvise_free_single_vma(struct vm_area_struct *vma,
        range.end = min(vma->vm_end, end_addr);
        if (range.end <= vma->vm_start)
                return -EINVAL;
-       mmu_notifier_range_init(&range, mm, range.start, range.end);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, mm,
+                               range.start, range.end);
 
        lru_add_drain();
        tlb_gather_mmu(&tlb, mm, range.start, range.end);
index a48f520..6bbad46 100644 (file)
@@ -94,7 +94,7 @@
  * :c:func:`mem_init` function frees all the memory to the buddy page
  * allocator.
  *
- * If an architecure enables %CONFIG_ARCH_DISCARD_MEMBLOCK, the
+ * Unless an architecure enables %CONFIG_ARCH_KEEP_MEMBLOCK, the
  * memblock data structures will be discarded after the system
  * initialization compltes.
  */
@@ -375,7 +375,7 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u
        }
 }
 
-#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
+#ifndef CONFIG_ARCH_KEEP_MEMBLOCK
 /**
  * memblock_discard - discard memory and reserved arrays if they were allocated
  */
@@ -1255,6 +1255,70 @@ int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size,
        return 0;
 }
 #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
+#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
+/**
+ * __next_mem_pfn_range_in_zone - iterator for for_each_*_range_in_zone()
+ *
+ * @idx: pointer to u64 loop variable
+ * @zone: zone in which all of the memory blocks reside
+ * @out_spfn: ptr to ulong for start pfn of the range, can be %NULL
+ * @out_epfn: ptr to ulong for end pfn of the range, can be %NULL
+ *
+ * This function is meant to be a zone/pfn specific wrapper for the
+ * for_each_mem_range type iterators. Specifically they are used in the
+ * deferred memory init routines and as such we were duplicating much of
+ * this logic throughout the code. So instead of having it in multiple
+ * locations it seemed like it would make more sense to centralize this to
+ * one new iterator that does everything they need.
+ */
+void __init_memblock
+__next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone,
+                            unsigned long *out_spfn, unsigned long *out_epfn)
+{
+       int zone_nid = zone_to_nid(zone);
+       phys_addr_t spa, epa;
+       int nid;
+
+       __next_mem_range(idx, zone_nid, MEMBLOCK_NONE,
+                        &memblock.memory, &memblock.reserved,
+                        &spa, &epa, &nid);
+
+       while (*idx != U64_MAX) {
+               unsigned long epfn = PFN_DOWN(epa);
+               unsigned long spfn = PFN_UP(spa);
+
+               /*
+                * Verify the end is at least past the start of the zone and
+                * that we have at least one PFN to initialize.
+                */
+               if (zone->zone_start_pfn < epfn && spfn < epfn) {
+                       /* if we went too far just stop searching */
+                       if (zone_end_pfn(zone) <= spfn) {
+                               *idx = U64_MAX;
+                               break;
+                       }
+
+                       if (out_spfn)
+                               *out_spfn = max(zone->zone_start_pfn, spfn);
+                       if (out_epfn)
+                               *out_epfn = min(zone_end_pfn(zone), epfn);
+
+                       return;
+               }
+
+               __next_mem_range(idx, zone_nid, MEMBLOCK_NONE,
+                                &memblock.memory, &memblock.reserved,
+                                &spa, &epa, &nid);
+       }
+
+       /* signal end of iteration */
+       if (out_spfn)
+               *out_spfn = ULONG_MAX;
+       if (out_epfn)
+               *out_epfn = 0;
+}
+
+#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
 
 /**
  * memblock_alloc_range_nid - allocate boot memory block
@@ -1923,7 +1987,7 @@ unsigned long __init memblock_free_all(void)
        return pages;
 }
 
-#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_ARCH_DISCARD_MEMBLOCK)
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_ARCH_KEEP_MEMBLOCK)
 
 static int memblock_debug_show(struct seq_file *m, void *private)
 {
index 81a0d39..e50a2db 100644 (file)
@@ -687,10 +687,119 @@ mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_node *mctz)
        return mz;
 }
 
-static unsigned long memcg_sum_events(struct mem_cgroup *memcg,
-                                     int event)
+/**
+ * __mod_memcg_state - update cgroup memory statistics
+ * @memcg: the memory cgroup
+ * @idx: the stat item - can be enum memcg_stat_item or enum node_stat_item
+ * @val: delta to add to the counter, can be negative
+ */
+void __mod_memcg_state(struct mem_cgroup *memcg, int idx, int val)
 {
-       return atomic_long_read(&memcg->events[event]);
+       long x;
+
+       if (mem_cgroup_disabled())
+               return;
+
+       x = val + __this_cpu_read(memcg->vmstats_percpu->stat[idx]);
+       if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) {
+               struct mem_cgroup *mi;
+
+               atomic_long_add(x, &memcg->vmstats_local[idx]);
+               for (mi = memcg; mi; mi = parent_mem_cgroup(mi))
+                       atomic_long_add(x, &mi->vmstats[idx]);
+               x = 0;
+       }
+       __this_cpu_write(memcg->vmstats_percpu->stat[idx], x);
+}
+
+static struct mem_cgroup_per_node *
+parent_nodeinfo(struct mem_cgroup_per_node *pn, int nid)
+{
+       struct mem_cgroup *parent;
+
+       parent = parent_mem_cgroup(pn->memcg);
+       if (!parent)
+               return NULL;
+       return mem_cgroup_nodeinfo(parent, nid);
+}
+
+/**
+ * __mod_lruvec_state - update lruvec memory statistics
+ * @lruvec: the lruvec
+ * @idx: the stat item
+ * @val: delta to add to the counter, can be negative
+ *
+ * The lruvec is the intersection of the NUMA node and a cgroup. This
+ * function updates the all three counters that are affected by a
+ * change of state at this level: per-node, per-cgroup, per-lruvec.
+ */
+void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
+                       int val)
+{
+       pg_data_t *pgdat = lruvec_pgdat(lruvec);
+       struct mem_cgroup_per_node *pn;
+       struct mem_cgroup *memcg;
+       long x;
+
+       /* Update node */
+       __mod_node_page_state(pgdat, idx, val);
+
+       if (mem_cgroup_disabled())
+               return;
+
+       pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
+       memcg = pn->memcg;
+
+       /* Update memcg */
+       __mod_memcg_state(memcg, idx, val);
+
+       /* Update lruvec */
+       x = val + __this_cpu_read(pn->lruvec_stat_cpu->count[idx]);
+       if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) {
+               struct mem_cgroup_per_node *pi;
+
+               atomic_long_add(x, &pn->lruvec_stat_local[idx]);
+               for (pi = pn; pi; pi = parent_nodeinfo(pi, pgdat->node_id))
+                       atomic_long_add(x, &pi->lruvec_stat[idx]);
+               x = 0;
+       }
+       __this_cpu_write(pn->lruvec_stat_cpu->count[idx], x);
+}
+
+/**
+ * __count_memcg_events - account VM events in a cgroup
+ * @memcg: the memory cgroup
+ * @idx: the event item
+ * @count: the number of events that occured
+ */
+void __count_memcg_events(struct mem_cgroup *memcg, enum vm_event_item idx,
+                         unsigned long count)
+{
+       unsigned long x;
+
+       if (mem_cgroup_disabled())
+               return;
+
+       x = count + __this_cpu_read(memcg->vmstats_percpu->events[idx]);
+       if (unlikely(x > MEMCG_CHARGE_BATCH)) {
+               struct mem_cgroup *mi;
+
+               atomic_long_add(x, &memcg->vmevents_local[idx]);
+               for (mi = memcg; mi; mi = parent_mem_cgroup(mi))
+                       atomic_long_add(x, &mi->vmevents[idx]);
+               x = 0;
+       }
+       __this_cpu_write(memcg->vmstats_percpu->events[idx], x);
+}
+
+static unsigned long memcg_events(struct mem_cgroup *memcg, int event)
+{
+       return atomic_long_read(&memcg->vmevents[event]);
+}
+
+static unsigned long memcg_events_local(struct mem_cgroup *memcg, int event)
+{
+       return atomic_long_read(&memcg->vmevents_local[event]);
 }
 
 static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg,
@@ -722,35 +831,7 @@ static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg,
                nr_pages = -nr_pages; /* for event */
        }
 
-       __this_cpu_add(memcg->stat_cpu->nr_page_events, nr_pages);
-}
-
-unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
-                                          int nid, unsigned int lru_mask)
-{
-       struct lruvec *lruvec = mem_cgroup_lruvec(NODE_DATA(nid), memcg);
-       unsigned long nr = 0;
-       enum lru_list lru;
-
-       VM_BUG_ON((unsigned)nid >= nr_node_ids);
-
-       for_each_lru(lru) {
-               if (!(BIT(lru) & lru_mask))
-                       continue;
-               nr += mem_cgroup_get_lru_size(lruvec, lru);
-       }
-       return nr;
-}
-
-static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *memcg,
-                       unsigned int lru_mask)
-{
-       unsigned long nr = 0;
-       int nid;
-
-       for_each_node_state(nid, N_MEMORY)
-               nr += mem_cgroup_node_nr_lru_pages(memcg, nid, lru_mask);
-       return nr;
+       __this_cpu_add(memcg->vmstats_percpu->nr_page_events, nr_pages);
 }
 
 static bool mem_cgroup_event_ratelimit(struct mem_cgroup *memcg,
@@ -758,8 +839,8 @@ static bool mem_cgroup_event_ratelimit(struct mem_cgroup *memcg,
 {
        unsigned long val, next;
 
-       val = __this_cpu_read(memcg->stat_cpu->nr_page_events);
-       next = __this_cpu_read(memcg->stat_cpu->targets[target]);
+       val = __this_cpu_read(memcg->vmstats_percpu->nr_page_events);
+       next = __this_cpu_read(memcg->vmstats_percpu->targets[target]);
        /* from time_after() in jiffies.h */
        if ((long)(next - val) < 0) {
                switch (target) {
@@ -775,7 +856,7 @@ static bool mem_cgroup_event_ratelimit(struct mem_cgroup *memcg,
                default:
                        break;
                }
-               __this_cpu_write(memcg->stat_cpu->targets[target], next);
+               __this_cpu_write(memcg->vmstats_percpu->targets[target], next);
                return true;
        }
        return false;
@@ -1353,12 +1434,14 @@ void mem_cgroup_print_oom_meminfo(struct mem_cgroup *memcg)
                        if (memcg1_stats[i] == MEMCG_SWAP && !do_swap_account)
                                continue;
                        pr_cont(" %s:%luKB", memcg1_stat_names[i],
-                               K(memcg_page_state(iter, memcg1_stats[i])));
+                               K(memcg_page_state_local(iter,
+                                                        memcg1_stats[i])));
                }
 
                for (i = 0; i < NR_LRU_LISTS; i++)
                        pr_cont(" %s:%luKB", mem_cgroup_lru_names[i],
-                               K(mem_cgroup_nr_lru_pages(iter, BIT(i))));
+                               K(memcg_page_state_local(iter,
+                                                        NR_LRU_BASE + i)));
 
                pr_cont("\n");
        }
@@ -1422,11 +1505,15 @@ static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
 static bool test_mem_cgroup_node_reclaimable(struct mem_cgroup *memcg,
                int nid, bool noswap)
 {
-       if (mem_cgroup_node_nr_lru_pages(memcg, nid, LRU_ALL_FILE))
+       struct lruvec *lruvec = mem_cgroup_lruvec(NODE_DATA(nid), memcg);
+
+       if (lruvec_page_state(lruvec, NR_INACTIVE_FILE) ||
+           lruvec_page_state(lruvec, NR_ACTIVE_FILE))
                return true;
        if (noswap || !total_swap_pages)
                return false;
-       if (mem_cgroup_node_nr_lru_pages(memcg, nid, LRU_ALL_ANON))
+       if (lruvec_page_state(lruvec, NR_INACTIVE_ANON) ||
+           lruvec_page_state(lruvec, NR_ACTIVE_ANON))
                return true;
        return false;
 
@@ -2100,7 +2187,7 @@ static void drain_all_stock(struct mem_cgroup *root_memcg)
 static int memcg_hotplug_cpu_dead(unsigned int cpu)
 {
        struct memcg_stock_pcp *stock;
-       struct mem_cgroup *memcg;
+       struct mem_cgroup *memcg, *mi;
 
        stock = &per_cpu(memcg_stock, cpu);
        drain_stock(stock);
@@ -2112,9 +2199,12 @@ static int memcg_hotplug_cpu_dead(unsigned int cpu)
                        int nid;
                        long x;
 
-                       x = this_cpu_xchg(memcg->stat_cpu->count[i], 0);
-                       if (x)
-                               atomic_long_add(x, &memcg->stat[i]);
+                       x = this_cpu_xchg(memcg->vmstats_percpu->stat[i], 0);
+                       if (x) {
+                               atomic_long_add(x, &memcg->vmstats_local[i]);
+                               for (mi = memcg; mi; mi = parent_mem_cgroup(mi))
+                                       atomic_long_add(x, &memcg->vmstats[i]);
+                       }
 
                        if (i >= NR_VM_NODE_STAT_ITEMS)
                                continue;
@@ -2124,17 +2214,24 @@ static int memcg_hotplug_cpu_dead(unsigned int cpu)
 
                                pn = mem_cgroup_nodeinfo(memcg, nid);
                                x = this_cpu_xchg(pn->lruvec_stat_cpu->count[i], 0);
-                               if (x)
-                                       atomic_long_add(x, &pn->lruvec_stat[i]);
+                               if (x) {
+                                       atomic_long_add(x, &pn->lruvec_stat_local[i]);
+                                       do {
+                                               atomic_long_add(x, &pn->lruvec_stat[i]);
+                                       } while ((pn = parent_nodeinfo(pn, nid)));
+                               }
                        }
                }
 
                for (i = 0; i < NR_VM_EVENT_ITEMS; i++) {
                        long x;
 
-                       x = this_cpu_xchg(memcg->stat_cpu->events[i], 0);
-                       if (x)
-                               atomic_long_add(x, &memcg->events[i]);
+                       x = this_cpu_xchg(memcg->vmstats_percpu->events[i], 0);
+                       if (x) {
+                               atomic_long_add(x, &memcg->vmevents_local[i]);
+                               for (mi = memcg; mi; mi = parent_mem_cgroup(mi))
+                                       atomic_long_add(x, &memcg->vmevents[i]);
+                       }
                }
        }
 
@@ -2964,50 +3061,15 @@ static int mem_cgroup_hierarchy_write(struct cgroup_subsys_state *css,
        return retval;
 }
 
-struct accumulated_stats {
-       unsigned long stat[MEMCG_NR_STAT];
-       unsigned long events[NR_VM_EVENT_ITEMS];
-       unsigned long lru_pages[NR_LRU_LISTS];
-       const unsigned int *stats_array;
-       const unsigned int *events_array;
-       int stats_size;
-       int events_size;
-};
-
-static void accumulate_memcg_tree(struct mem_cgroup *memcg,
-                                 struct accumulated_stats *acc)
-{
-       struct mem_cgroup *mi;
-       int i;
-
-       for_each_mem_cgroup_tree(mi, memcg) {
-               for (i = 0; i < acc->stats_size; i++)
-                       acc->stat[i] += memcg_page_state(mi,
-                               acc->stats_array ? acc->stats_array[i] : i);
-
-               for (i = 0; i < acc->events_size; i++)
-                       acc->events[i] += memcg_sum_events(mi,
-                               acc->events_array ? acc->events_array[i] : i);
-
-               for (i = 0; i < NR_LRU_LISTS; i++)
-                       acc->lru_pages[i] +=
-                               mem_cgroup_nr_lru_pages(mi, BIT(i));
-       }
-}
-
 static unsigned long mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
 {
-       unsigned long val = 0;
+       unsigned long val;
 
        if (mem_cgroup_is_root(memcg)) {
-               struct mem_cgroup *iter;
-
-               for_each_mem_cgroup_tree(iter, memcg) {
-                       val += memcg_page_state(iter, MEMCG_CACHE);
-                       val += memcg_page_state(iter, MEMCG_RSS);
-                       if (swap)
-                               val += memcg_page_state(iter, MEMCG_SWAP);
-               }
+               val = memcg_page_state(memcg, MEMCG_CACHE) +
+                       memcg_page_state(memcg, MEMCG_RSS);
+               if (swap)
+                       val += memcg_page_state(memcg, MEMCG_SWAP);
        } else {
                if (!swap)
                        val = page_counter_read(&memcg->memory);
@@ -3331,6 +3393,42 @@ static int mem_cgroup_move_charge_write(struct cgroup_subsys_state *css,
 #endif
 
 #ifdef CONFIG_NUMA
+
+#define LRU_ALL_FILE (BIT(LRU_INACTIVE_FILE) | BIT(LRU_ACTIVE_FILE))
+#define LRU_ALL_ANON (BIT(LRU_INACTIVE_ANON) | BIT(LRU_ACTIVE_ANON))
+#define LRU_ALL             ((1 << NR_LRU_LISTS) - 1)
+
+static unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
+                                          int nid, unsigned int lru_mask)
+{
+       struct lruvec *lruvec = mem_cgroup_lruvec(NODE_DATA(nid), memcg);
+       unsigned long nr = 0;
+       enum lru_list lru;
+
+       VM_BUG_ON((unsigned)nid >= nr_node_ids);
+
+       for_each_lru(lru) {
+               if (!(BIT(lru) & lru_mask))
+                       continue;
+               nr += lruvec_page_state_local(lruvec, NR_LRU_BASE + lru);
+       }
+       return nr;
+}
+
+static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *memcg,
+                                            unsigned int lru_mask)
+{
+       unsigned long nr = 0;
+       enum lru_list lru;
+
+       for_each_lru(lru) {
+               if (!(BIT(lru) & lru_mask))
+                       continue;
+               nr += memcg_page_state_local(memcg, NR_LRU_BASE + lru);
+       }
+       return nr;
+}
+
 static int memcg_numa_stat_show(struct seq_file *m, void *v)
 {
        struct numa_stat {
@@ -3402,7 +3500,6 @@ static int memcg_stat_show(struct seq_file *m, void *v)
        unsigned long memory, memsw;
        struct mem_cgroup *mi;
        unsigned int i;
-       struct accumulated_stats acc;
 
        BUILD_BUG_ON(ARRAY_SIZE(memcg1_stat_names) != ARRAY_SIZE(memcg1_stats));
        BUILD_BUG_ON(ARRAY_SIZE(mem_cgroup_lru_names) != NR_LRU_LISTS);
@@ -3411,17 +3508,18 @@ static int memcg_stat_show(struct seq_file *m, void *v)
                if (memcg1_stats[i] == MEMCG_SWAP && !do_memsw_account())
                        continue;
                seq_printf(m, "%s %lu\n", memcg1_stat_names[i],
-                          memcg_page_state(memcg, memcg1_stats[i]) *
+                          memcg_page_state_local(memcg, memcg1_stats[i]) *
                           PAGE_SIZE);
        }
 
        for (i = 0; i < ARRAY_SIZE(memcg1_events); i++)
                seq_printf(m, "%s %lu\n", memcg1_event_names[i],
-                          memcg_sum_events(memcg, memcg1_events[i]));
+                          memcg_events_local(memcg, memcg1_events[i]));
 
        for (i = 0; i < NR_LRU_LISTS; i++)
                seq_printf(m, "%s %lu\n", mem_cgroup_lru_names[i],
-                          mem_cgroup_nr_lru_pages(memcg, BIT(i)) * PAGE_SIZE);
+                          memcg_page_state_local(memcg, NR_LRU_BASE + i) *
+                          PAGE_SIZE);
 
        /* Hierarchical information */
        memory = memsw = PAGE_COUNTER_MAX;
@@ -3435,27 +3533,21 @@ static int memcg_stat_show(struct seq_file *m, void *v)
                seq_printf(m, "hierarchical_memsw_limit %llu\n",
                           (u64)memsw * PAGE_SIZE);
 
-       memset(&acc, 0, sizeof(acc));
-       acc.stats_size = ARRAY_SIZE(memcg1_stats);
-       acc.stats_array = memcg1_stats;
-       acc.events_size = ARRAY_SIZE(memcg1_events);
-       acc.events_array = memcg1_events;
-       accumulate_memcg_tree(memcg, &acc);
-
        for (i = 0; i < ARRAY_SIZE(memcg1_stats); i++) {
                if (memcg1_stats[i] == MEMCG_SWAP && !do_memsw_account())
                        continue;
                seq_printf(m, "total_%s %llu\n", memcg1_stat_names[i],
-                          (u64)acc.stat[i] * PAGE_SIZE);
+                          (u64)memcg_page_state(memcg, i) * PAGE_SIZE);
        }
 
        for (i = 0; i < ARRAY_SIZE(memcg1_events); i++)
                seq_printf(m, "total_%s %llu\n", memcg1_event_names[i],
-                          (u64)acc.events[i]);
+                          (u64)memcg_events(memcg, i));
 
        for (i = 0; i < NR_LRU_LISTS; i++)
                seq_printf(m, "total_%s %llu\n", mem_cgroup_lru_names[i],
-                          (u64)acc.lru_pages[i] * PAGE_SIZE);
+                          (u64)memcg_page_state(memcg, NR_LRU_BASE + i) *
+                          PAGE_SIZE);
 
 #ifdef CONFIG_DEBUG_VM
        {
@@ -3888,11 +3980,11 @@ struct wb_domain *mem_cgroup_wb_domain(struct bdi_writeback *wb)
  */
 static unsigned long memcg_exact_page_state(struct mem_cgroup *memcg, int idx)
 {
-       long x = atomic_long_read(&memcg->stat[idx]);
+       long x = atomic_long_read(&memcg->vmstats[idx]);
        int cpu;
 
        for_each_online_cpu(cpu)
-               x += per_cpu_ptr(memcg->stat_cpu, cpu)->count[idx];
+               x += per_cpu_ptr(memcg->vmstats_percpu, cpu)->stat[idx];
        if (x < 0)
                x = 0;
        return x;
@@ -3927,8 +4019,8 @@ void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pfilepages,
 
        /* this should eventually include NR_UNSTABLE_NFS */
        *pwriteback = memcg_exact_page_state(memcg, NR_WRITEBACK);
-       *pfilepages = mem_cgroup_nr_lru_pages(memcg, (1 << LRU_INACTIVE_FILE) |
-                                                    (1 << LRU_ACTIVE_FILE));
+       *pfilepages = memcg_exact_page_state(memcg, NR_INACTIVE_FILE) +
+                       memcg_exact_page_state(memcg, NR_ACTIVE_FILE);
        *pheadroom = PAGE_COUNTER_MAX;
 
        while ((parent = parent_mem_cgroup(memcg))) {
@@ -4432,7 +4524,7 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
 
        for_each_node(node)
                free_mem_cgroup_per_node_info(memcg, node);
-       free_percpu(memcg->stat_cpu);
+       free_percpu(memcg->vmstats_percpu);
        kfree(memcg);
 }
 
@@ -4461,8 +4553,8 @@ static struct mem_cgroup *mem_cgroup_alloc(void)
        if (memcg->id.id < 0)
                goto fail;
 
-       memcg->stat_cpu = alloc_percpu(struct mem_cgroup_stat_cpu);
-       if (!memcg->stat_cpu)
+       memcg->vmstats_percpu = alloc_percpu(struct memcg_vmstats_percpu);
+       if (!memcg->vmstats_percpu)
                goto fail;
 
        for_each_node(node)
@@ -5548,7 +5640,6 @@ static int memory_events_show(struct seq_file *m, void *v)
 static int memory_stat_show(struct seq_file *m, void *v)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_seq(m);
-       struct accumulated_stats acc;
        int i;
 
        /*
@@ -5562,31 +5653,27 @@ static int memory_stat_show(struct seq_file *m, void *v)
         * Current memory state:
         */
 
-       memset(&acc, 0, sizeof(acc));
-       acc.stats_size = MEMCG_NR_STAT;
-       acc.events_size = NR_VM_EVENT_ITEMS;
-       accumulate_memcg_tree(memcg, &acc);
-
        seq_printf(m, "anon %llu\n",
-                  (u64)acc.stat[MEMCG_RSS] * PAGE_SIZE);
+                  (u64)memcg_page_state(memcg, MEMCG_RSS) * PAGE_SIZE);
        seq_printf(m, "file %llu\n",
-                  (u64)acc.stat[MEMCG_CACHE] * PAGE_SIZE);
+                  (u64)memcg_page_state(memcg, MEMCG_CACHE) * PAGE_SIZE);
        seq_printf(m, "kernel_stack %llu\n",
-                  (u64)acc.stat[MEMCG_KERNEL_STACK_KB] * 1024);
+                  (u64)memcg_page_state(memcg, MEMCG_KERNEL_STACK_KB) * 1024);
        seq_printf(m, "slab %llu\n",
-                  (u64)(acc.stat[NR_SLAB_RECLAIMABLE] +
-                        acc.stat[NR_SLAB_UNRECLAIMABLE]) * PAGE_SIZE);
+                  (u64)(memcg_page_state(memcg, NR_SLAB_RECLAIMABLE) +
+                        memcg_page_state(memcg, NR_SLAB_UNRECLAIMABLE)) *
+                  PAGE_SIZE);
        seq_printf(m, "sock %llu\n",
-                  (u64)acc.stat[MEMCG_SOCK] * PAGE_SIZE);
+                  (u64)memcg_page_state(memcg, MEMCG_SOCK) * PAGE_SIZE);
 
        seq_printf(m, "shmem %llu\n",
-                  (u64)acc.stat[NR_SHMEM] * PAGE_SIZE);
+                  (u64)memcg_page_state(memcg, NR_SHMEM) * PAGE_SIZE);
        seq_printf(m, "file_mapped %llu\n",
-                  (u64)acc.stat[NR_FILE_MAPPED] * PAGE_SIZE);
+                  (u64)memcg_page_state(memcg, NR_FILE_MAPPED) * PAGE_SIZE);
        seq_printf(m, "file_dirty %llu\n",
-                  (u64)acc.stat[NR_FILE_DIRTY] * PAGE_SIZE);
+                  (u64)memcg_page_state(memcg, NR_FILE_DIRTY) * PAGE_SIZE);
        seq_printf(m, "file_writeback %llu\n",
-                  (u64)acc.stat[NR_WRITEBACK] * PAGE_SIZE);
+                  (u64)memcg_page_state(memcg, NR_WRITEBACK) * PAGE_SIZE);
 
        /*
         * TODO: We should eventually replace our own MEMCG_RSS_HUGE counter
@@ -5595,43 +5682,47 @@ static int memory_stat_show(struct seq_file *m, void *v)
         * where the page->mem_cgroup is set up and stable.
         */
        seq_printf(m, "anon_thp %llu\n",
-                  (u64)acc.stat[MEMCG_RSS_HUGE] * PAGE_SIZE);
+                  (u64)memcg_page_state(memcg, MEMCG_RSS_HUGE) * PAGE_SIZE);
 
        for (i = 0; i < NR_LRU_LISTS; i++)
                seq_printf(m, "%s %llu\n", mem_cgroup_lru_names[i],
-                          (u64)acc.lru_pages[i] * PAGE_SIZE);
+                          (u64)memcg_page_state(memcg, NR_LRU_BASE + i) *
+                          PAGE_SIZE);
 
        seq_printf(m, "slab_reclaimable %llu\n",
-                  (u64)acc.stat[NR_SLAB_RECLAIMABLE] * PAGE_SIZE);
+                  (u64)memcg_page_state(memcg, NR_SLAB_RECLAIMABLE) *
+                  PAGE_SIZE);
        seq_printf(m, "slab_unreclaimable %llu\n",
-                  (u64)acc.stat[NR_SLAB_UNRECLAIMABLE] * PAGE_SIZE);
+                  (u64)memcg_page_state(memcg, NR_SLAB_UNRECLAIMABLE) *
+                  PAGE_SIZE);
 
        /* Accumulated memory events */
 
-       seq_printf(m, "pgfault %lu\n", acc.events[PGFAULT]);
-       seq_printf(m, "pgmajfault %lu\n", acc.events[PGMAJFAULT]);
+       seq_printf(m, "pgfault %lu\n", memcg_events(memcg, PGFAULT));
+       seq_printf(m, "pgmajfault %lu\n", memcg_events(memcg, PGMAJFAULT));
 
        seq_printf(m, "workingset_refault %lu\n",
-                  acc.stat[WORKINGSET_REFAULT]);
+                  memcg_page_state(memcg, WORKINGSET_REFAULT));
        seq_printf(m, "workingset_activate %lu\n",
-                  acc.stat[WORKINGSET_ACTIVATE]);
+                  memcg_page_state(memcg, WORKINGSET_ACTIVATE));
        seq_printf(m, "workingset_nodereclaim %lu\n",
-                  acc.stat[WORKINGSET_NODERECLAIM]);
-
-       seq_printf(m, "pgrefill %lu\n", acc.events[PGREFILL]);
-       seq_printf(m, "pgscan %lu\n", acc.events[PGSCAN_KSWAPD] +
-                  acc.events[PGSCAN_DIRECT]);
-       seq_printf(m, "pgsteal %lu\n", acc.events[PGSTEAL_KSWAPD] +
-                  acc.events[PGSTEAL_DIRECT]);
-       seq_printf(m, "pgactivate %lu\n", acc.events[PGACTIVATE]);
-       seq_printf(m, "pgdeactivate %lu\n", acc.events[PGDEACTIVATE]);
-       seq_printf(m, "pglazyfree %lu\n", acc.events[PGLAZYFREE]);
-       seq_printf(m, "pglazyfreed %lu\n", acc.events[PGLAZYFREED]);
+                  memcg_page_state(memcg, WORKINGSET_NODERECLAIM));
+
+       seq_printf(m, "pgrefill %lu\n", memcg_events(memcg, PGREFILL));
+       seq_printf(m, "pgscan %lu\n", memcg_events(memcg, PGSCAN_KSWAPD) +
+                  memcg_events(memcg, PGSCAN_DIRECT));
+       seq_printf(m, "pgsteal %lu\n", memcg_events(memcg, PGSTEAL_KSWAPD) +
+                  memcg_events(memcg, PGSTEAL_DIRECT));
+       seq_printf(m, "pgactivate %lu\n", memcg_events(memcg, PGACTIVATE));
+       seq_printf(m, "pgdeactivate %lu\n", memcg_events(memcg, PGDEACTIVATE));
+       seq_printf(m, "pglazyfree %lu\n", memcg_events(memcg, PGLAZYFREE));
+       seq_printf(m, "pglazyfreed %lu\n", memcg_events(memcg, PGLAZYFREED));
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
-       seq_printf(m, "thp_fault_alloc %lu\n", acc.events[THP_FAULT_ALLOC]);
+       seq_printf(m, "thp_fault_alloc %lu\n",
+                  memcg_events(memcg, THP_FAULT_ALLOC));
        seq_printf(m, "thp_collapse_alloc %lu\n",
-                  acc.events[THP_COLLAPSE_ALLOC]);
+                  memcg_events(memcg, THP_COLLAPSE_ALLOC));
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
        return 0;
@@ -6067,7 +6158,7 @@ static void uncharge_batch(const struct uncharge_gather *ug)
        __mod_memcg_state(ug->memcg, MEMCG_RSS_HUGE, -ug->nr_huge);
        __mod_memcg_state(ug->memcg, NR_SHMEM, -ug->nr_shmem);
        __count_memcg_events(ug->memcg, PGPGOUT, ug->pgpgout);
-       __this_cpu_add(ug->memcg->stat_cpu->nr_page_events, nr_pages);
+       __this_cpu_add(ug->memcg->vmstats_percpu->nr_page_events, nr_pages);
        memcg_check_events(ug->memcg, ug->dummy_page);
        local_irq_restore(flags);
 
index 650e65a..2647c89 100644 (file)
@@ -39,6 +39,7 @@ static void memfd_tag_pins(struct xa_state *xas)
        xas_for_each(xas, page, ULONG_MAX) {
                if (xa_is_value(page))
                        continue;
+               page = find_subpage(page, xas->xa_index);
                if (page_count(page) - page_mapcount(page) > 1)
                        xas_set_mark(xas, MEMFD_TAG_PINNED);
 
@@ -88,6 +89,7 @@ static int memfd_wait_for_pins(struct address_space *mapping)
                        bool clear = true;
                        if (xa_is_value(page))
                                continue;
+                       page = find_subpage(page, xas.xa_index);
                        if (page_count(page) - page_mapcount(page) != 1) {
                                /*
                                 * On the last scan, we clean up all those tags
index f7d962d..96f1d47 100644 (file)
@@ -1010,7 +1010,8 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
        is_cow = is_cow_mapping(vma->vm_flags);
 
        if (is_cow) {
-               mmu_notifier_range_init(&range, src_mm, addr, end);
+               mmu_notifier_range_init(&range, MMU_NOTIFY_PROTECTION_PAGE,
+                                       0, vma, src_mm, addr, end);
                mmu_notifier_invalidate_range_start(&range);
        }
 
@@ -1334,7 +1335,8 @@ void unmap_vmas(struct mmu_gather *tlb,
 {
        struct mmu_notifier_range range;
 
-       mmu_notifier_range_init(&range, vma->vm_mm, start_addr, end_addr);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_UNMAP, 0, vma, vma->vm_mm,
+                               start_addr, end_addr);
        mmu_notifier_invalidate_range_start(&range);
        for ( ; vma && vma->vm_start < end_addr; vma = vma->vm_next)
                unmap_single_vma(tlb, vma, start_addr, end_addr, NULL);
@@ -1356,7 +1358,8 @@ void zap_page_range(struct vm_area_struct *vma, unsigned long start,
        struct mmu_gather tlb;
 
        lru_add_drain();
-       mmu_notifier_range_init(&range, vma->vm_mm, start, start + size);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, vma->vm_mm,
+                               start, start + size);
        tlb_gather_mmu(&tlb, vma->vm_mm, start, range.end);
        update_hiwater_rss(vma->vm_mm);
        mmu_notifier_invalidate_range_start(&range);
@@ -1382,7 +1385,8 @@ static void zap_page_range_single(struct vm_area_struct *vma, unsigned long addr
        struct mmu_gather tlb;
 
        lru_add_drain();
-       mmu_notifier_range_init(&range, vma->vm_mm, address, address + size);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, vma->vm_mm,
+                               address, address + size);
        tlb_gather_mmu(&tlb, vma->vm_mm, address, range.end);
        update_hiwater_rss(vma->vm_mm);
        mmu_notifier_invalidate_range_start(&range);
@@ -1523,6 +1527,87 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
 }
 EXPORT_SYMBOL(vm_insert_page);
 
+/*
+ * __vm_map_pages - maps range of kernel pages into user vma
+ * @vma: user vma to map to
+ * @pages: pointer to array of source kernel pages
+ * @num: number of pages in page array
+ * @offset: user's requested vm_pgoff
+ *
+ * This allows drivers to map range of kernel pages into a user vma.
+ *
+ * Return: 0 on success and error code otherwise.
+ */
+static int __vm_map_pages(struct vm_area_struct *vma, struct page **pages,
+                               unsigned long num, unsigned long offset)
+{
+       unsigned long count = vma_pages(vma);
+       unsigned long uaddr = vma->vm_start;
+       int ret, i;
+
+       /* Fail if the user requested offset is beyond the end of the object */
+       if (offset > num)
+               return -ENXIO;
+
+       /* Fail if the user requested size exceeds available object size */
+       if (count > num - offset)
+               return -ENXIO;
+
+       for (i = 0; i < count; i++) {
+               ret = vm_insert_page(vma, uaddr, pages[offset + i]);
+               if (ret < 0)
+                       return ret;
+               uaddr += PAGE_SIZE;
+       }
+
+       return 0;
+}
+
+/**
+ * vm_map_pages - maps range of kernel pages starts with non zero offset
+ * @vma: user vma to map to
+ * @pages: pointer to array of source kernel pages
+ * @num: number of pages in page array
+ *
+ * Maps an object consisting of @num pages, catering for the user's
+ * requested vm_pgoff
+ *
+ * If we fail to insert any page into the vma, the function will return
+ * immediately leaving any previously inserted pages present.  Callers
+ * from the mmap handler may immediately return the error as their caller
+ * will destroy the vma, removing any successfully inserted pages. Other
+ * callers should make their own arrangements for calling unmap_region().
+ *
+ * Context: Process context. Called by mmap handlers.
+ * Return: 0 on success and error code otherwise.
+ */
+int vm_map_pages(struct vm_area_struct *vma, struct page **pages,
+                               unsigned long num)
+{
+       return __vm_map_pages(vma, pages, num, vma->vm_pgoff);
+}
+EXPORT_SYMBOL(vm_map_pages);
+
+/**
+ * vm_map_pages_zero - map range of kernel pages starts with zero offset
+ * @vma: user vma to map to
+ * @pages: pointer to array of source kernel pages
+ * @num: number of pages in page array
+ *
+ * Similar to vm_map_pages(), except that it explicitly sets the offset
+ * to 0. This function is intended for the drivers that did not consider
+ * vm_pgoff.
+ *
+ * Context: Process context. Called by mmap handlers.
+ * Return: 0 on success and error code otherwise.
+ */
+int vm_map_pages_zero(struct vm_area_struct *vma, struct page **pages,
+                               unsigned long num)
+{
+       return __vm_map_pages(vma, pages, num, 0);
+}
+EXPORT_SYMBOL(vm_map_pages_zero);
+
 static vm_fault_t insert_pfn(struct vm_area_struct *vma, unsigned long addr,
                        pfn_t pfn, pgprot_t prot, bool mkwrite)
 {
@@ -2279,7 +2364,8 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
 
        __SetPageUptodate(new_page);
 
-       mmu_notifier_range_init(&range, mm, vmf->address & PAGE_MASK,
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, mm,
+                               vmf->address & PAGE_MASK,
                                (vmf->address & PAGE_MASK) + PAGE_SIZE);
        mmu_notifier_invalidate_range_start(&range);
 
@@ -4104,8 +4190,9 @@ static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address,
                        goto out;
 
                if (range) {
-                       mmu_notifier_range_init(range, mm, address & PMD_MASK,
-                                            (address & PMD_MASK) + PMD_SIZE);
+                       mmu_notifier_range_init(range, MMU_NOTIFY_CLEAR, 0,
+                                               NULL, mm, address & PMD_MASK,
+                                               (address & PMD_MASK) + PMD_SIZE);
                        mmu_notifier_invalidate_range_start(range);
                }
                *ptlp = pmd_lock(mm, pmd);
@@ -4122,8 +4209,9 @@ static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address,
                goto out;
 
        if (range) {
-               mmu_notifier_range_init(range, mm, address & PAGE_MASK,
-                                    (address & PAGE_MASK) + PAGE_SIZE);
+               mmu_notifier_range_init(range, MMU_NOTIFY_CLEAR, 0, NULL, mm,
+                                       address & PAGE_MASK,
+                                       (address & PAGE_MASK) + PAGE_SIZE);
                mmu_notifier_invalidate_range_start(range);
        }
        ptep = pte_offset_map_lock(mm, pmd, address, ptlp);
index b236069..328878b 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/tlbflush.h>
 
 #include "internal.h"
+#include "shuffle.h"
 
 /*
  * online_page_callback contains pointer to current page onlining function.
@@ -273,12 +274,12 @@ static int __meminit __add_section(int nid, unsigned long phys_start_pfn,
  * add the new pages.
  */
 int __ref __add_pages(int nid, unsigned long phys_start_pfn,
-               unsigned long nr_pages, struct vmem_altmap *altmap,
-               bool want_memblock)
+               unsigned long nr_pages, struct mhp_restrictions *restrictions)
 {
        unsigned long i;
        int err = 0;
        int start_sec, end_sec;
+       struct vmem_altmap *altmap = restrictions->altmap;
 
        /* during initialize mem_map, align hot-added range to section */
        start_sec = pfn_to_section_nr(phys_start_pfn);
@@ -299,7 +300,7 @@ int __ref __add_pages(int nid, unsigned long phys_start_pfn,
 
        for (i = start_sec; i <= end_sec; i++) {
                err = __add_section(nid, section_nr_to_pfn(i), altmap,
-                               want_memblock);
+                               restrictions->flags & MHP_MEMBLOCK_API);
 
                /*
                 * EEXIST is finally dealt with by ioresource collision
@@ -516,26 +517,23 @@ static void __remove_zone(struct zone *zone, unsigned long start_pfn)
        pgdat_resize_unlock(zone->zone_pgdat, &flags);
 }
 
-static int __remove_section(struct zone *zone, struct mem_section *ms,
-               unsigned long map_offset, struct vmem_altmap *altmap)
+static void __remove_section(struct zone *zone, struct mem_section *ms,
+                            unsigned long map_offset,
+                            struct vmem_altmap *altmap)
 {
        unsigned long start_pfn;
        int scn_nr;
-       int ret = -EINVAL;
 
-       if (!valid_section(ms))
-               return ret;
+       if (WARN_ON_ONCE(!valid_section(ms)))
+               return;
 
-       ret = unregister_memory_section(ms);
-       if (ret)
-               return ret;
+       unregister_memory_section(ms);
 
        scn_nr = __section_nr(ms);
        start_pfn = section_nr_to_pfn((unsigned long)scn_nr);
        __remove_zone(zone, start_pfn);
 
        sparse_remove_one_section(zone, ms, map_offset, altmap);
-       return 0;
 }
 
 /**
@@ -550,31 +548,17 @@ static int __remove_section(struct zone *zone, struct mem_section *ms,
  * sure that pages are marked reserved and zones are adjust properly by
  * calling offline_pages().
  */
-int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
-                unsigned long nr_pages, struct vmem_altmap *altmap)
+void __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
+                   unsigned long nr_pages, struct vmem_altmap *altmap)
 {
        unsigned long i;
        unsigned long map_offset = 0;
-       int sections_to_remove, ret = 0;
+       int sections_to_remove;
 
        /* In the ZONE_DEVICE case device driver owns the memory region */
        if (is_dev_zone(zone)) {
                if (altmap)
                        map_offset = vmem_altmap_offset(altmap);
-       } else {
-               resource_size_t start, size;
-
-               start = phys_start_pfn << PAGE_SHIFT;
-               size = nr_pages * PAGE_SIZE;
-
-               ret = release_mem_region_adjustable(&iomem_resource, start,
-                                       size);
-               if (ret) {
-                       resource_size_t endres = start + size - 1;
-
-                       pr_warn("Unable to release resource <%pa-%pa> (%d)\n",
-                                       &start, &endres, ret);
-               }
        }
 
        clear_zone_contiguous(zone);
@@ -590,16 +574,12 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
                unsigned long pfn = phys_start_pfn + i*PAGES_PER_SECTION;
 
                cond_resched();
-               ret = __remove_section(zone, __pfn_to_section(pfn), map_offset,
-                               altmap);
+               __remove_section(zone, __pfn_to_section(pfn), map_offset,
+                                altmap);
                map_offset = 0;
-               if (ret)
-                       break;
        }
 
        set_zone_contiguous(zone);
-
-       return ret;
 }
 #endif /* CONFIG_MEMORY_HOTREMOVE */
 
@@ -714,7 +694,7 @@ static void node_states_check_changes_online(unsigned long nr_pages,
        if (zone_idx(zone) <= ZONE_NORMAL && !node_state(nid, N_NORMAL_MEMORY))
                arg->status_change_nid_normal = nid;
 #ifdef CONFIG_HIGHMEM
-       if (zone_idx(zone) <= N_HIGH_MEMORY && !node_state(nid, N_HIGH_MEMORY))
+       if (zone_idx(zone) <= ZONE_HIGHMEM && !node_state(nid, N_HIGH_MEMORY))
                arg->status_change_nid_high = nid;
 #endif
 }
@@ -912,6 +892,8 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
        zone->zone_pgdat->node_present_pages += onlined_pages;
        pgdat_resize_unlock(zone->zone_pgdat, &flags);
 
+       shuffle_zone(zone);
+
        if (onlined_pages) {
                node_states_set_node(nid, &arg);
                if (need_zonelists_rebuild)
@@ -1097,6 +1079,9 @@ static int online_memory_block(struct memory_block *mem, void *arg)
  */
 int __ref add_memory_resource(int nid, struct resource *res)
 {
+       struct mhp_restrictions restrictions = {
+               .flags = MHP_MEMBLOCK_API,
+       };
        u64 start, size;
        bool new_node = false;
        int ret;
@@ -1124,7 +1109,7 @@ int __ref add_memory_resource(int nid, struct resource *res)
        new_node = ret;
 
        /* call arch's memory hotadd */
-       ret = arch_add_memory(nid, start, size, NULL, true);
+       ret = arch_add_memory(nid, start, size, &restrictions);
        if (ret < 0)
                goto error;
 
@@ -1341,8 +1326,7 @@ static unsigned long scan_movable_pages(unsigned long start, unsigned long end)
                if (!PageHuge(page))
                        continue;
                head = compound_head(page);
-               if (hugepage_migration_supported(page_hstate(head)) &&
-                   page_huge_active(head))
+               if (page_huge_active(head))
                        return pfn;
                skip = (1 << compound_order(head)) - (page - head);
                pfn += skip - 1;
@@ -1382,10 +1366,6 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
 
                if (PageHuge(page)) {
                        struct page *head = compound_head(page);
-                       if (compound_order(head) > PFN_SECTION_SHIFT) {
-                               ret = -EBUSY;
-                               break;
-                       }
                        pfn = page_to_pfn(head) + (1<<compound_order(head)) - 1;
                        isolate_huge_page(head, &source);
                        continue;
@@ -1454,15 +1434,10 @@ static int
 offline_isolated_pages_cb(unsigned long start, unsigned long nr_pages,
                        void *data)
 {
-       __offline_isolated_pages(start, start + nr_pages);
-       return 0;
-}
+       unsigned long *offlined_pages = (unsigned long *)data;
 
-static void
-offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
-{
-       walk_system_ram_range(start_pfn, end_pfn - start_pfn, NULL,
-                               offline_isolated_pages_cb);
+       *offlined_pages += __offline_isolated_pages(start, start + nr_pages);
+       return 0;
 }
 
 /*
@@ -1472,26 +1447,7 @@ static int
 check_pages_isolated_cb(unsigned long start_pfn, unsigned long nr_pages,
                        void *data)
 {
-       int ret;
-       long offlined = *(long *)data;
-       ret = test_pages_isolated(start_pfn, start_pfn + nr_pages, true);
-       offlined = nr_pages;
-       if (!ret)
-               *(long *)data += offlined;
-       return ret;
-}
-
-static long
-check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
-{
-       long offlined = 0;
-       int ret;
-
-       ret = walk_system_ram_range(start_pfn, end_pfn - start_pfn, &offlined,
-                       check_pages_isolated_cb);
-       if (ret < 0)
-               offlined = (long)ret;
-       return offlined;
+       return test_pages_isolated(start_pfn, start_pfn + nr_pages, true);
 }
 
 static int __init cmdline_parse_movable_node(char *p)
@@ -1576,7 +1532,7 @@ static int __ref __offline_pages(unsigned long start_pfn,
                  unsigned long end_pfn)
 {
        unsigned long pfn, nr_pages;
-       long offlined_pages;
+       unsigned long offlined_pages = 0;
        int ret, node, nr_isolate_pageblock;
        unsigned long flags;
        unsigned long valid_start, valid_end;
@@ -1652,14 +1608,15 @@ static int __ref __offline_pages(unsigned long start_pfn,
                        goto failed_removal_isolated;
                }
                /* check again */
-               offlined_pages = check_pages_isolated(start_pfn, end_pfn);
-       } while (offlined_pages < 0);
+               ret = walk_system_ram_range(start_pfn, end_pfn - start_pfn,
+                                           NULL, check_pages_isolated_cb);
+       } while (ret);
 
-       pr_info("Offlined Pages %ld\n", offlined_pages);
        /* Ok, all of our target is isolated.
           We cannot do rollback at this point. */
-       offline_isolated_pages(start_pfn, end_pfn);
-
+       walk_system_ram_range(start_pfn, end_pfn - start_pfn,
+                             &offlined_pages, offline_isolated_pages_cb);
+       pr_info("Offlined Pages %ld\n", offlined_pages);
        /*
         * Onlining will reset pagetype flags and makes migrate type
         * MOVABLE, so just need to decrease the number of isolated
@@ -1843,6 +1800,26 @@ void try_offline_node(int nid)
 }
 EXPORT_SYMBOL(try_offline_node);
 
+static void __release_memory_resource(resource_size_t start,
+                                     resource_size_t size)
+{
+       int ret;
+
+       /*
+        * When removing memory in the same granularity as it was added,
+        * this function never fails. It might only fail if resources
+        * have to be adjusted or split. We'll ignore the error, as
+        * removing of memory cannot fail.
+        */
+       ret = release_mem_region_adjustable(&iomem_resource, start, size);
+       if (ret) {
+               resource_size_t endres = start + size - 1;
+
+               pr_warn("Unable to release resource <%pa-%pa> (%d)\n",
+                       &start, &endres, ret);
+       }
+}
+
 /**
  * remove_memory
  * @nid: the node ID
@@ -1877,6 +1854,7 @@ void __ref __remove_memory(int nid, u64 start, u64 size)
        memblock_remove(start, size);
 
        arch_remove_memory(nid, start, size, NULL);
+       __release_memory_resource(start, size);
 
        try_offline_node(nid);
 
index 663a544..f2ecc28 100644 (file)
@@ -463,7 +463,7 @@ int migrate_page_move_mapping(struct address_space *mapping,
 
                for (i = 1; i < HPAGE_PMD_NR; i++) {
                        xas_next(&xas);
-                       xas_store(&xas, newpage + i);
+                       xas_store(&xas, newpage);
                }
        }
 
@@ -2356,7 +2356,8 @@ static void migrate_vma_collect(struct migrate_vma *migrate)
        mm_walk.mm = migrate->vma->vm_mm;
        mm_walk.private = migrate;
 
-       mmu_notifier_range_init(&range, mm_walk.mm, migrate->start,
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, NULL, mm_walk.mm,
+                               migrate->start,
                                migrate->end);
        mmu_notifier_invalidate_range_start(&range);
        walk_page_range(migrate->start, migrate->end, &mm_walk);
@@ -2764,6 +2765,8 @@ static void migrate_vma_pages(struct migrate_vma *migrate)
                                notified = true;
 
                                mmu_notifier_range_init(&range,
+                                                       MMU_NOTIFY_CLEAR, 0,
+                                                       NULL,
                                                        migrate->vma->vm_mm,
                                                        addr, migrate->end);
                                mmu_notifier_invalidate_range_start(&range);
index 218099b..c3f058b 100644 (file)
@@ -169,6 +169,22 @@ out:
        return 0;
 }
 
+static inline bool can_do_mincore(struct vm_area_struct *vma)
+{
+       if (vma_is_anonymous(vma))
+               return true;
+       if (!vma->vm_file)
+               return false;
+       /*
+        * Reveal pagecache information only for non-anonymous mappings that
+        * correspond to the files the calling process could (if tried) open
+        * for writing; otherwise we'd be including shared non-exclusive
+        * mappings, which opens a side channel.
+        */
+       return inode_owner_or_capable(file_inode(vma->vm_file)) ||
+               inode_permission(file_inode(vma->vm_file), MAY_WRITE) == 0;
+}
+
 /*
  * Do a chunk of "sys_mincore()". We've already checked
  * all the arguments, we hold the mmap semaphore: we should
@@ -189,8 +205,13 @@ static long do_mincore(unsigned long addr, unsigned long pages, unsigned char *v
        vma = find_vma(current->mm, addr);
        if (!vma || addr < vma->vm_start)
                return -ENOMEM;
-       mincore_walk.mm = vma->vm_mm;
        end = min(vma->vm_end, addr + (pages << PAGE_SHIFT));
+       if (!can_do_mincore(vma)) {
+               unsigned long pages = DIV_ROUND_UP(end - addr, PAGE_SIZE);
+               memset(vec, 1, pages);
+               return pages;
+       }
+       mincore_walk.mm = vma->vm_mm;
        err = walk_page_range(addr, end, &mincore_walk);
        if (err < 0)
                return err;
index 9c884ab..ee36068 100644 (file)
@@ -180,7 +180,7 @@ int __mmu_notifier_invalidate_range_start(struct mmu_notifier_range *range)
                        if (_ret) {
                                pr_info("%pS callback failed with %d in %sblockable context.\n",
                                        mn->ops->invalidate_range_start, _ret,
-                                       !range->blockable ? "non-" : "");
+                                       !mmu_notifier_range_blockable(range) ? "non-" : "");
                                ret = _ret;
                        }
                }
@@ -395,3 +395,13 @@ void mmu_notifier_unregister_no_release(struct mmu_notifier *mn,
        mmdrop(mm);
 }
 EXPORT_SYMBOL_GPL(mmu_notifier_unregister_no_release);
+
+bool
+mmu_notifier_range_update_to_read_only(const struct mmu_notifier_range *range)
+{
+       if (!range->vma || range->event != MMU_NOTIFY_PROTECTION_VMA)
+               return false;
+       /* Return true if the vma still have the read flag set. */
+       return range->vma->vm_flags & VM_READ;
+}
+EXPORT_SYMBOL_GPL(mmu_notifier_range_update_to_read_only);
index 028c724..bf38dfb 100644 (file)
@@ -39,7 +39,6 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                unsigned long addr, unsigned long end, pgprot_t newprot,
                int dirty_accountable, int prot_numa)
 {
-       struct mm_struct *mm = vma->vm_mm;
        pte_t *pte, oldpte;
        spinlock_t *ptl;
        unsigned long pages = 0;
@@ -136,7 +135,7 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                                newpte = swp_entry_to_pte(entry);
                                if (pte_swp_soft_dirty(oldpte))
                                        newpte = pte_swp_mksoft_dirty(newpte);
-                               set_pte_at(mm, addr, pte, newpte);
+                               set_pte_at(vma->vm_mm, addr, pte, newpte);
 
                                pages++;
                        }
@@ -150,7 +149,7 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                                 */
                                make_device_private_entry_read(&entry);
                                newpte = swp_entry_to_pte(entry);
-                               set_pte_at(mm, addr, pte, newpte);
+                               set_pte_at(vma->vm_mm, addr, pte, newpte);
 
                                pages++;
                        }
@@ -185,7 +184,9 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
 
                /* invoke the mmu notifier if the pmd is populated */
                if (!range.start) {
-                       mmu_notifier_range_init(&range, vma->vm_mm, addr, end);
+                       mmu_notifier_range_init(&range,
+                               MMU_NOTIFY_PROTECTION_VMA, 0,
+                               vma, vma->vm_mm, addr, end);
                        mmu_notifier_invalidate_range_start(&range);
                }
 
index e3edef6..fc241d2 100644 (file)
@@ -249,7 +249,8 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
        old_end = old_addr + len;
        flush_cache_range(vma, old_addr, old_end);
 
-       mmu_notifier_range_init(&range, vma->vm_mm, old_addr, old_end);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_UNMAP, 0, vma, vma->vm_mm,
+                               old_addr, old_end);
        mmu_notifier_invalidate_range_start(&range);
 
        for (; old_addr < old_end; old_addr += extent, new_addr += extent) {
index 749276b..b492fd1 100644 (file)
@@ -473,6 +473,20 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
 }
 EXPORT_SYMBOL(vm_insert_page);
 
+int vm_map_pages(struct vm_area_struct *vma, struct page **pages,
+                       unsigned long num)
+{
+       return -EINVAL;
+}
+EXPORT_SYMBOL(vm_map_pages);
+
+int vm_map_pages_zero(struct vm_area_struct *vma, struct page **pages,
+                               unsigned long num)
+{
+       return -EINVAL;
+}
+EXPORT_SYMBOL(vm_map_pages_zero);
+
 /*
  *  sys_brk() for the most part doesn't need the global kernel
  *  lock, except when an application is doing something nasty
index 3a24848..539c91d 100644 (file)
@@ -531,7 +531,8 @@ bool __oom_reap_task_mm(struct mm_struct *mm)
                        struct mmu_notifier_range range;
                        struct mmu_gather tlb;
 
-                       mmu_notifier_range_init(&range, mm, vma->vm_start,
+                       mmu_notifier_range_init(&range, MMU_NOTIFY_UNMAP, 0,
+                                               vma, mm, vma->vm_start,
                                                vma->vm_end);
                        tlb_gather_mmu(&tlb, mm, range.start, range.end);
                        if (mmu_notifier_invalidate_range_start_nonblock(&range)) {
index 9f61dfe..0765648 100644 (file)
@@ -2808,6 +2808,18 @@ int __test_set_page_writeback(struct page *page, bool keep_write)
 }
 EXPORT_SYMBOL(__test_set_page_writeback);
 
+/*
+ * Wait for a page to complete writeback
+ */
+void wait_on_page_writeback(struct page *page)
+{
+       if (PageWriteback(page)) {
+               trace_wait_on_page_writeback(page, page_mapping(page));
+               wait_on_page_bit(page, PG_writeback);
+       }
+}
+EXPORT_SYMBOL_GPL(wait_on_page_writeback);
+
 /**
  * wait_for_stable_page() - wait for writeback to finish, if necessary.
  * @page:      The page to wait on.
index 5966110..3b13d39 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/mempolicy.h>
 #include <linux/memremap.h>
 #include <linux/stop_machine.h>
+#include <linux/random.h>
 #include <linux/sort.h>
 #include <linux/pfn.h>
 #include <linux/backing-dev.h>
@@ -72,6 +73,7 @@
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
 #include "internal.h"
+#include "shuffle.h"
 
 /* prevent >1 _updater_ of zone percpu pageset ->high and ->batch fields */
 static DEFINE_MUTEX(pcp_batch_high_lock);
@@ -755,12 +757,6 @@ static inline void set_page_order(struct page *page, unsigned int order)
        __SetPageBuddy(page);
 }
 
-static inline void rmv_page_order(struct page *page)
-{
-       __ClearPageBuddy(page);
-       set_page_private(page, 0);
-}
-
 /*
  * This function checks whether a page is free && is the buddy
  * we can coalesce a page and its buddy if
@@ -918,13 +914,10 @@ continue_merging:
                 * Our buddy is free or it is CONFIG_DEBUG_PAGEALLOC guard page,
                 * merge with it and move up one order.
                 */
-               if (page_is_guard(buddy)) {
+               if (page_is_guard(buddy))
                        clear_page_guard(zone, buddy, order, migratetype);
-               } else {
-                       list_del(&buddy->lru);
-                       zone->free_area[order].nr_free--;
-                       rmv_page_order(buddy);
-               }
+               else
+                       del_page_from_free_area(buddy, &zone->free_area[order]);
                combined_pfn = buddy_pfn & pfn;
                page = page + (combined_pfn - pfn);
                pfn = combined_pfn;
@@ -966,7 +959,8 @@ done_merging:
         * so it's less likely to be used soon and more likely to be merged
         * as a higher order page
         */
-       if ((order < MAX_ORDER-2) && pfn_valid_within(buddy_pfn)) {
+       if ((order < MAX_ORDER-2) && pfn_valid_within(buddy_pfn)
+                       && !is_shuffle_order(order)) {
                struct page *higher_page, *higher_buddy;
                combined_pfn = buddy_pfn & pfn;
                higher_page = page + (combined_pfn - pfn);
@@ -974,15 +968,18 @@ done_merging:
                higher_buddy = higher_page + (buddy_pfn - combined_pfn);
                if (pfn_valid_within(buddy_pfn) &&
                    page_is_buddy(higher_page, higher_buddy, order + 1)) {
-                       list_add_tail(&page->lru,
-                               &zone->free_area[order].free_list[migratetype]);
-                       goto out;
+                       add_to_free_area_tail(page, &zone->free_area[order],
+                                             migratetype);
+                       return;
                }
        }
 
-       list_add(&page->lru, &zone->free_area[order].free_list[migratetype]);
-out:
-       zone->free_area[order].nr_free++;
+       if (is_shuffle_order(order))
+               add_to_free_area_random(page, &zone->free_area[order],
+                               migratetype);
+       else
+               add_to_free_area(page, &zone->free_area[order], migratetype);
+
 }
 
 /*
@@ -1416,36 +1413,22 @@ int __meminit early_pfn_to_nid(unsigned long pfn)
 #endif
 
 #ifdef CONFIG_NODES_SPAN_OTHER_NODES
-static inline bool __meminit __maybe_unused
-meminit_pfn_in_nid(unsigned long pfn, int node,
-                  struct mminit_pfnnid_cache *state)
+/* Only safe to use early in boot when initialisation is single-threaded */
+static inline bool __meminit early_pfn_in_nid(unsigned long pfn, int node)
 {
        int nid;
 
-       nid = __early_pfn_to_nid(pfn, state);
+       nid = __early_pfn_to_nid(pfn, &early_pfnnid_cache);
        if (nid >= 0 && nid != node)
                return false;
        return true;
 }
 
-/* Only safe to use early in boot when initialisation is single-threaded */
-static inline bool __meminit early_pfn_in_nid(unsigned long pfn, int node)
-{
-       return meminit_pfn_in_nid(pfn, node, &early_pfnnid_cache);
-}
-
 #else
-
 static inline bool __meminit early_pfn_in_nid(unsigned long pfn, int node)
 {
        return true;
 }
-static inline bool __meminit  __maybe_unused
-meminit_pfn_in_nid(unsigned long pfn, int node,
-                  struct mminit_pfnnid_cache *state)
-{
-       return true;
-}
 #endif
 
 
@@ -1574,21 +1557,13 @@ static inline void __init pgdat_init_report_one_done(void)
  *
  * Then, we check if a current large page is valid by only checking the validity
  * of the head pfn.
- *
- * Finally, meminit_pfn_in_nid is checked on systems where pfns can interleave
- * within a node: a pfn is between start and end of a node, but does not belong
- * to this memory node.
  */
-static inline bool __init
-deferred_pfn_valid(int nid, unsigned long pfn,
-                  struct mminit_pfnnid_cache *nid_init_state)
+static inline bool __init deferred_pfn_valid(unsigned long pfn)
 {
        if (!pfn_valid_within(pfn))
                return false;
        if (!(pfn & (pageblock_nr_pages - 1)) && !pfn_valid(pfn))
                return false;
-       if (!meminit_pfn_in_nid(pfn, nid, nid_init_state))
-               return false;
        return true;
 }
 
@@ -1596,15 +1571,14 @@ deferred_pfn_valid(int nid, unsigned long pfn,
  * Free pages to buddy allocator. Try to free aligned pages in
  * pageblock_nr_pages sizes.
  */
-static void __init deferred_free_pages(int nid, int zid, unsigned long pfn,
+static void __init deferred_free_pages(unsigned long pfn,
                                       unsigned long end_pfn)
 {
-       struct mminit_pfnnid_cache nid_init_state = { };
        unsigned long nr_pgmask = pageblock_nr_pages - 1;
        unsigned long nr_free = 0;
 
        for (; pfn < end_pfn; pfn++) {
-               if (!deferred_pfn_valid(nid, pfn, &nid_init_state)) {
+               if (!deferred_pfn_valid(pfn)) {
                        deferred_free_range(pfn - nr_free, nr_free);
                        nr_free = 0;
                } else if (!(pfn & nr_pgmask)) {
@@ -1624,17 +1598,18 @@ static void __init deferred_free_pages(int nid, int zid, unsigned long pfn,
  * by performing it only once every pageblock_nr_pages.
  * Return number of pages initialized.
  */
-static unsigned long  __init deferred_init_pages(int nid, int zid,
+static unsigned long  __init deferred_init_pages(struct zone *zone,
                                                 unsigned long pfn,
                                                 unsigned long end_pfn)
 {
-       struct mminit_pfnnid_cache nid_init_state = { };
        unsigned long nr_pgmask = pageblock_nr_pages - 1;
+       int nid = zone_to_nid(zone);
        unsigned long nr_pages = 0;
+       int zid = zone_idx(zone);
        struct page *page = NULL;
 
        for (; pfn < end_pfn; pfn++) {
-               if (!deferred_pfn_valid(nid, pfn, &nid_init_state)) {
+               if (!deferred_pfn_valid(pfn)) {
                        page = NULL;
                        continue;
                } else if (!page || !(pfn & nr_pgmask)) {
@@ -1649,18 +1624,100 @@ static unsigned long  __init deferred_init_pages(int nid, int zid,
        return (nr_pages);
 }
 
+/*
+ * This function is meant to pre-load the iterator for the zone init.
+ * Specifically it walks through the ranges until we are caught up to the
+ * first_init_pfn value and exits there. If we never encounter the value we
+ * return false indicating there are no valid ranges left.
+ */
+static bool __init
+deferred_init_mem_pfn_range_in_zone(u64 *i, struct zone *zone,
+                                   unsigned long *spfn, unsigned long *epfn,
+                                   unsigned long first_init_pfn)
+{
+       u64 j;
+
+       /*
+        * Start out by walking through the ranges in this zone that have
+        * already been initialized. We don't need to do anything with them
+        * so we just need to flush them out of the system.
+        */
+       for_each_free_mem_pfn_range_in_zone(j, zone, spfn, epfn) {
+               if (*epfn <= first_init_pfn)
+                       continue;
+               if (*spfn < first_init_pfn)
+                       *spfn = first_init_pfn;
+               *i = j;
+               return true;
+       }
+
+       return false;
+}
+
+/*
+ * Initialize and free pages. We do it in two loops: first we initialize
+ * struct page, then free to buddy allocator, because while we are
+ * freeing pages we can access pages that are ahead (computing buddy
+ * page in __free_one_page()).
+ *
+ * In order to try and keep some memory in the cache we have the loop
+ * broken along max page order boundaries. This way we will not cause
+ * any issues with the buddy page computation.
+ */
+static unsigned long __init
+deferred_init_maxorder(u64 *i, struct zone *zone, unsigned long *start_pfn,
+                      unsigned long *end_pfn)
+{
+       unsigned long mo_pfn = ALIGN(*start_pfn + 1, MAX_ORDER_NR_PAGES);
+       unsigned long spfn = *start_pfn, epfn = *end_pfn;
+       unsigned long nr_pages = 0;
+       u64 j = *i;
+
+       /* First we loop through and initialize the page values */
+       for_each_free_mem_pfn_range_in_zone_from(j, zone, start_pfn, end_pfn) {
+               unsigned long t;
+
+               if (mo_pfn <= *start_pfn)
+                       break;
+
+               t = min(mo_pfn, *end_pfn);
+               nr_pages += deferred_init_pages(zone, *start_pfn, t);
+
+               if (mo_pfn < *end_pfn) {
+                       *start_pfn = mo_pfn;
+                       break;
+               }
+       }
+
+       /* Reset values and now loop through freeing pages as needed */
+       swap(j, *i);
+
+       for_each_free_mem_pfn_range_in_zone_from(j, zone, &spfn, &epfn) {
+               unsigned long t;
+
+               if (mo_pfn <= spfn)
+                       break;
+
+               t = min(mo_pfn, epfn);
+               deferred_free_pages(spfn, t);
+
+               if (mo_pfn <= epfn)
+                       break;
+       }
+
+       return nr_pages;
+}
+
 /* Initialise remaining memory on a node */
 static int __init deferred_init_memmap(void *data)
 {
        pg_data_t *pgdat = data;
-       int nid = pgdat->node_id;
+       const struct cpumask *cpumask = cpumask_of_node(pgdat->node_id);
+       unsigned long spfn = 0, epfn = 0, nr_pages = 0;
+       unsigned long first_init_pfn, flags;
        unsigned long start = jiffies;
-       unsigned long nr_pages = 0;
-       unsigned long spfn, epfn, first_init_pfn, flags;
-       phys_addr_t spa, epa;
-       int zid;
        struct zone *zone;
-       const struct cpumask *cpumask = cpumask_of_node(pgdat->node_id);
+       int zid;
        u64 i;
 
        /* Bind memory initialisation thread to a local node if possible */
@@ -1686,31 +1743,27 @@ static int __init deferred_init_memmap(void *data)
                if (first_init_pfn < zone_end_pfn(zone))
                        break;
        }
-       first_init_pfn = max(zone->zone_start_pfn, first_init_pfn);
+
+       /* If the zone is empty somebody else may have cleared out the zone */
+       if (!deferred_init_mem_pfn_range_in_zone(&i, zone, &spfn, &epfn,
+                                                first_init_pfn))
+               goto zone_empty;
 
        /*
-        * Initialize and free pages. We do it in two loops: first we initialize
-        * struct page, than free to buddy allocator, because while we are
-        * freeing pages we can access pages that are ahead (computing buddy
-        * page in __free_one_page()).
+        * Initialize and free pages in MAX_ORDER sized increments so
+        * that we can avoid introducing any issues with the buddy
+        * allocator.
         */
-       for_each_free_mem_range(i, nid, MEMBLOCK_NONE, &spa, &epa, NULL) {
-               spfn = max_t(unsigned long, first_init_pfn, PFN_UP(spa));
-               epfn = min_t(unsigned long, zone_end_pfn(zone), PFN_DOWN(epa));
-               nr_pages += deferred_init_pages(nid, zid, spfn, epfn);
-       }
-       for_each_free_mem_range(i, nid, MEMBLOCK_NONE, &spa, &epa, NULL) {
-               spfn = max_t(unsigned long, first_init_pfn, PFN_UP(spa));
-               epfn = min_t(unsigned long, zone_end_pfn(zone), PFN_DOWN(epa));
-               deferred_free_pages(nid, zid, spfn, epfn);
-       }
+       while (spfn < epfn)
+               nr_pages += deferred_init_maxorder(&i, zone, &spfn, &epfn);
+zone_empty:
        pgdat_resize_unlock(pgdat, &flags);
 
        /* Sanity check that the next zone really is unpopulated */
        WARN_ON(++zid < MAX_NR_ZONES && populated_zone(++zone));
 
-       pr_info("node %d initialised, %lu pages in %ums\n", nid, nr_pages,
-                                       jiffies_to_msecs(jiffies - start));
+       pr_info("node %d initialised, %lu pages in %ums\n",
+               pgdat->node_id, nr_pages, jiffies_to_msecs(jiffies - start));
 
        pgdat_init_report_one_done();
        return 0;
@@ -1734,14 +1787,11 @@ static int __init deferred_init_memmap(void *data)
 static noinline bool __init
 deferred_grow_zone(struct zone *zone, unsigned int order)
 {
-       int zid = zone_idx(zone);
-       int nid = zone_to_nid(zone);
-       pg_data_t *pgdat = NODE_DATA(nid);
        unsigned long nr_pages_needed = ALIGN(1 << order, PAGES_PER_SECTION);
-       unsigned long nr_pages = 0;
-       unsigned long first_init_pfn, spfn, epfn, t, flags;
+       pg_data_t *pgdat = zone->zone_pgdat;
        unsigned long first_deferred_pfn = pgdat->first_deferred_pfn;
-       phys_addr_t spa, epa;
+       unsigned long spfn, epfn, flags;
+       unsigned long nr_pages = 0;
        u64 i;
 
        /* Only the last zone may have deferred pages */
@@ -1770,38 +1820,35 @@ deferred_grow_zone(struct zone *zone, unsigned int order)
                return true;
        }
 
-       first_init_pfn = max(zone->zone_start_pfn, first_deferred_pfn);
-
-       if (first_init_pfn >= pgdat_end_pfn(pgdat)) {
+       /* If the zone is empty somebody else may have cleared out the zone */
+       if (!deferred_init_mem_pfn_range_in_zone(&i, zone, &spfn, &epfn,
+                                                first_deferred_pfn)) {
+               pgdat->first_deferred_pfn = ULONG_MAX;
                pgdat_resize_unlock(pgdat, &flags);
-               return false;
+               return true;
        }
 
-       for_each_free_mem_range(i, nid, MEMBLOCK_NONE, &spa, &epa, NULL) {
-               spfn = max_t(unsigned long, first_init_pfn, PFN_UP(spa));
-               epfn = min_t(unsigned long, zone_end_pfn(zone), PFN_DOWN(epa));
+       /*
+        * Initialize and free pages in MAX_ORDER sized increments so
+        * that we can avoid introducing any issues with the buddy
+        * allocator.
+        */
+       while (spfn < epfn) {
+               /* update our first deferred PFN for this section */
+               first_deferred_pfn = spfn;
 
-               while (spfn < epfn && nr_pages < nr_pages_needed) {
-                       t = ALIGN(spfn + PAGES_PER_SECTION, PAGES_PER_SECTION);
-                       first_deferred_pfn = min(t, epfn);
-                       nr_pages += deferred_init_pages(nid, zid, spfn,
-                                                       first_deferred_pfn);
-                       spfn = first_deferred_pfn;
-               }
+               nr_pages += deferred_init_maxorder(&i, zone, &spfn, &epfn);
 
+               /* We should only stop along section boundaries */
+               if ((first_deferred_pfn ^ spfn) < PAGES_PER_SECTION)
+                       continue;
+
+               /* If our quota has been met we can stop here */
                if (nr_pages >= nr_pages_needed)
                        break;
        }
 
-       for_each_free_mem_range(i, nid, MEMBLOCK_NONE, &spa, &epa, NULL) {
-               spfn = max_t(unsigned long, first_init_pfn, PFN_UP(spa));
-               epfn = min_t(unsigned long, first_deferred_pfn, PFN_DOWN(epa));
-               deferred_free_pages(nid, zid, spfn, epfn);
-
-               if (first_deferred_pfn == epfn)
-                       break;
-       }
-       pgdat->first_deferred_pfn = first_deferred_pfn;
+       pgdat->first_deferred_pfn = spfn;
        pgdat_resize_unlock(pgdat, &flags);
 
        return nr_pages > 0;
@@ -1824,9 +1871,9 @@ _deferred_grow_zone(struct zone *zone, unsigned int order)
 void __init page_alloc_init_late(void)
 {
        struct zone *zone;
+       int nid;
 
 #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
-       int nid;
 
        /* There will be num_node_state(N_MEMORY) threads */
        atomic_set(&pgdat_init_n_undone, num_node_state(N_MEMORY));
@@ -1846,10 +1893,12 @@ void __init page_alloc_init_late(void)
        /* Reinit limits that are based on free pages after the kernel is up */
        files_maxfiles_init();
 #endif
-#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
+
        /* Discard memblock private memory */
        memblock_discard();
-#endif
+
+       for_each_node_state(nid, N_MEMORY)
+               shuffle_free_memory(NODE_DATA(nid));
 
        for_each_populated_zone(zone)
                set_zone_contiguous(zone);
@@ -1921,8 +1970,7 @@ static inline void expand(struct zone *zone, struct page *page,
                if (set_page_guard(zone, &page[size], high, migratetype))
                        continue;
 
-               list_add(&page[size].lru, &area->free_list[migratetype]);
-               area->nr_free++;
+               add_to_free_area(&page[size], area, migratetype);
                set_page_order(&page[size], high);
        }
 }
@@ -1937,7 +1985,7 @@ static void check_new_page_bad(struct page *page)
        if (unlikely(page->mapping != NULL))
                bad_reason = "non-NULL mapping";
        if (unlikely(page_ref_count(page) != 0))
-               bad_reason = "nonzero _count";
+               bad_reason = "nonzero _refcount";
        if (unlikely(page->flags & __PG_HWPOISON)) {
                bad_reason = "HWPoisoned (hardware-corrupted)";
                bad_flags = __PG_HWPOISON;
@@ -2064,13 +2112,10 @@ struct page *__rmqueue_smallest(struct zone *zone, unsigned int order,
        /* Find a page of the appropriate size in the preferred list */
        for (current_order = order; current_order < MAX_ORDER; ++current_order) {
                area = &(zone->free_area[current_order]);
-               page = list_first_entry_or_null(&area->free_list[migratetype],
-                                                       struct page, lru);
+               page = get_page_from_free_area(area, migratetype);
                if (!page)
                        continue;
-               list_del(&page->lru);
-               rmv_page_order(page);
-               area->nr_free--;
+               del_page_from_free_area(page, area);
                expand(zone, page, order, current_order, area, migratetype);
                set_pcppage_migratetype(page, migratetype);
                return page;
@@ -2156,8 +2201,7 @@ static int move_freepages(struct zone *zone,
                }
 
                order = page_order(page);
-               list_move(&page->lru,
-                         &zone->free_area[order].free_list[migratetype]);
+               move_to_free_area(page, &zone->free_area[order], migratetype);
                page += 1 << order;
                pages_moved += 1 << order;
        }
@@ -2345,7 +2389,7 @@ static void steal_suitable_fallback(struct zone *zone, struct page *page,
 
 single_page:
        area = &zone->free_area[current_order];
-       list_move(&page->lru, &area->free_list[start_type]);
+       move_to_free_area(page, area, start_type);
 }
 
 /*
@@ -2369,7 +2413,7 @@ int find_suitable_fallback(struct free_area *area, unsigned int order,
                if (fallback_mt == MIGRATE_TYPES)
                        break;
 
-               if (list_empty(&area->free_list[fallback_mt]))
+               if (free_area_empty(area, fallback_mt))
                        continue;
 
                if (can_steal_fallback(order, migratetype))
@@ -2456,9 +2500,7 @@ static bool unreserve_highatomic_pageblock(const struct alloc_context *ac,
                for (order = 0; order < MAX_ORDER; order++) {
                        struct free_area *area = &(zone->free_area[order]);
 
-                       page = list_first_entry_or_null(
-                                       &area->free_list[MIGRATE_HIGHATOMIC],
-                                       struct page, lru);
+                       page = get_page_from_free_area(area, MIGRATE_HIGHATOMIC);
                        if (!page)
                                continue;
 
@@ -2581,8 +2623,7 @@ find_smallest:
        VM_BUG_ON(current_order == MAX_ORDER);
 
 do_steal:
-       page = list_first_entry(&area->free_list[fallback_mt],
-                                                       struct page, lru);
+       page = get_page_from_free_area(area, fallback_mt);
 
        steal_suitable_fallback(zone, page, alloc_flags, start_migratetype,
                                                                can_steal);
@@ -3019,6 +3060,7 @@ EXPORT_SYMBOL_GPL(split_page);
 
 int __isolate_free_page(struct page *page, unsigned int order)
 {
+       struct free_area *area = &page_zone(page)->free_area[order];
        unsigned long watermark;
        struct zone *zone;
        int mt;
@@ -3043,9 +3085,8 @@ int __isolate_free_page(struct page *page, unsigned int order)
        }
 
        /* Remove page from free list */
-       list_del(&page->lru);
-       zone->free_area[order].nr_free--;
-       rmv_page_order(page);
+
+       del_page_from_free_area(page, area);
 
        /*
         * Set the pageblock if the isolated page is at least half of a
@@ -3120,9 +3161,8 @@ static struct page *__rmqueue_pcplist(struct zone *zone, int migratetype,
 
 /* Lock and remove page from the per-cpu list */
 static struct page *rmqueue_pcplist(struct zone *preferred_zone,
-                       struct zone *zone, unsigned int order,
-                       gfp_t gfp_flags, int migratetype,
-                       unsigned int alloc_flags)
+                       struct zone *zone, gfp_t gfp_flags,
+                       int migratetype, unsigned int alloc_flags)
 {
        struct per_cpu_pages *pcp;
        struct list_head *list;
@@ -3134,7 +3174,7 @@ static struct page *rmqueue_pcplist(struct zone *preferred_zone,
        list = &pcp->lists[migratetype];
        page = __rmqueue_pcplist(zone,  migratetype, alloc_flags, pcp, list);
        if (page) {
-               __count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order);
+               __count_zid_vm_events(PGALLOC, page_zonenum(page), 1);
                zone_statistics(preferred_zone, zone);
        }
        local_irq_restore(flags);
@@ -3154,8 +3194,8 @@ struct page *rmqueue(struct zone *preferred_zone,
        struct page *page;
 
        if (likely(order == 0)) {
-               page = rmqueue_pcplist(preferred_zone, zone, order,
-                               gfp_flags, migratetype, alloc_flags);
+               page = rmqueue_pcplist(preferred_zone, zone, gfp_flags,
+                                       migratetype, alloc_flags);
                goto out;
        }
 
@@ -3343,13 +3383,13 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark,
                        continue;
 
                for (mt = 0; mt < MIGRATE_PCPTYPES; mt++) {
-                       if (!list_empty(&area->free_list[mt]))
+                       if (!free_area_empty(area, mt))
                                return true;
                }
 
 #ifdef CONFIG_CMA
                if ((alloc_flags & ALLOC_CMA) &&
-                   !list_empty(&area->free_list[MIGRATE_CMA])) {
+                   !free_area_empty(area, MIGRATE_CMA)) {
                        return true;
                }
 #endif
@@ -4821,7 +4861,7 @@ static void *make_alloc_exact(unsigned long addr, unsigned int order,
 /**
  * alloc_pages_exact - allocate an exact number physically-contiguous pages.
  * @size: the number of bytes to allocate
- * @gfp_mask: GFP flags for the allocation
+ * @gfp_mask: GFP flags for the allocation, must not contain __GFP_COMP
  *
  * This function is similar to alloc_pages(), except that it allocates the
  * minimum number of pages to satisfy the request.  alloc_pages() can only
@@ -4838,6 +4878,9 @@ void *alloc_pages_exact(size_t size, gfp_t gfp_mask)
        unsigned int order = get_order(size);
        unsigned long addr;
 
+       if (WARN_ON_ONCE(gfp_mask & __GFP_COMP))
+               gfp_mask &= ~__GFP_COMP;
+
        addr = __get_free_pages(gfp_mask, order);
        return make_alloc_exact(addr, order, size);
 }
@@ -4848,7 +4891,7 @@ EXPORT_SYMBOL(alloc_pages_exact);
  *                        pages on a node.
  * @nid: the preferred node ID where memory should be allocated
  * @size: the number of bytes to allocate
- * @gfp_mask: GFP flags for the allocation
+ * @gfp_mask: GFP flags for the allocation, must not contain __GFP_COMP
  *
  * Like alloc_pages_exact(), but try to allocate on node nid first before falling
  * back.
@@ -4858,7 +4901,12 @@ EXPORT_SYMBOL(alloc_pages_exact);
 void * __meminit alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask)
 {
        unsigned int order = get_order(size);
-       struct page *p = alloc_pages_node(nid, gfp_mask, order);
+       struct page *p;
+
+       if (WARN_ON_ONCE(gfp_mask & __GFP_COMP))
+               gfp_mask &= ~__GFP_COMP;
+
+       p = alloc_pages_node(nid, gfp_mask, order);
        if (!p)
                return NULL;
        return make_alloc_exact((unsigned long)page_address(p), order, size);
@@ -5268,7 +5316,7 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)
 
                        types[order] = 0;
                        for (type = 0; type < MIGRATE_TYPES; type++) {
-                               if (!list_empty(&area->free_list[type]))
+                               if (!free_area_empty(area, type))
                                        types[order] |= 1 << type;
                        }
                }
@@ -6247,13 +6295,15 @@ static unsigned long __init zone_spanned_pages_in_node(int nid,
                                        unsigned long *zone_end_pfn,
                                        unsigned long *ignored)
 {
+       unsigned long zone_low = arch_zone_lowest_possible_pfn[zone_type];
+       unsigned long zone_high = arch_zone_highest_possible_pfn[zone_type];
        /* When hotadd a new node from cpu_up(), the node should be empty */
        if (!node_start_pfn && !node_end_pfn)
                return 0;
 
        /* Get the start and end of the zone */
-       *zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type];
-       *zone_end_pfn = arch_zone_highest_possible_pfn[zone_type];
+       *zone_start_pfn = clamp(node_start_pfn, zone_low, zone_high);
+       *zone_end_pfn = clamp(node_end_pfn, zone_low, zone_high);
        adjust_zone_range_for_zone_movable(nid, zone_type,
                                node_start_pfn, node_end_pfn,
                                zone_start_pfn, zone_end_pfn);
@@ -8129,8 +8179,7 @@ unmovable:
        return true;
 }
 
-#if (defined(CONFIG_MEMORY_ISOLATION) && defined(CONFIG_COMPACTION)) || defined(CONFIG_CMA)
-
+#ifdef CONFIG_CONTIG_ALLOC
 static unsigned long pfn_max_align_down(unsigned long pfn)
 {
        return pfn & ~(max_t(unsigned long, MAX_ORDER_NR_PAGES,
@@ -8339,8 +8388,9 @@ done:
                                pfn_max_align_up(end), migratetype);
        return ret;
 }
+#endif /* CONFIG_CONTIG_ALLOC */
 
-void free_contig_range(unsigned long pfn, unsigned nr_pages)
+void free_contig_range(unsigned long pfn, unsigned int nr_pages)
 {
        unsigned int count = 0;
 
@@ -8352,7 +8402,6 @@ void free_contig_range(unsigned long pfn, unsigned nr_pages)
        }
        WARN(count != 0, "%d pages are still in use!\n", count);
 }
-#endif
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
@@ -8394,7 +8443,7 @@ void zone_pcp_reset(struct zone *zone)
  * All pages in the range must be in a single zone and isolated
  * before calling this.
  */
-void
+unsigned long
 __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
 {
        struct page *page;
@@ -8402,12 +8451,15 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
        unsigned int order, i;
        unsigned long pfn;
        unsigned long flags;
+       unsigned long offlined_pages = 0;
+
        /* find the first valid pfn */
        for (pfn = start_pfn; pfn < end_pfn; pfn++)
                if (pfn_valid(pfn))
                        break;
        if (pfn == end_pfn)
-               return;
+               return offlined_pages;
+
        offline_mem_sections(pfn, end_pfn);
        zone = page_zone(pfn_to_page(pfn));
        spin_lock_irqsave(&zone->lock, flags);
@@ -8425,24 +8477,26 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
                if (unlikely(!PageBuddy(page) && PageHWPoison(page))) {
                        pfn++;
                        SetPageReserved(page);
+                       offlined_pages++;
                        continue;
                }
 
                BUG_ON(page_count(page));
                BUG_ON(!PageBuddy(page));
                order = page_order(page);
+               offlined_pages += 1 << order;
 #ifdef CONFIG_DEBUG_VM
                pr_info("remove from free list %lx %d %lx\n",
                        pfn, 1 << order, end_pfn);
 #endif
-               list_del(&page->lru);
-               rmv_page_order(page);
-               zone->free_area[order].nr_free--;
+               del_page_from_free_area(page, &zone->free_area[order]);
                for (i = 0; i < (1 << order); i++)
                        SetPageReserved((page+i));
                pfn += (1 << order);
        }
        spin_unlock_irqrestore(&zone->lock, flags);
+
+       return offlined_pages;
 }
 #endif
 
index 0192807..e3638a5 100644 (file)
@@ -151,8 +151,6 @@ __first_valid_page(unsigned long pfn, unsigned long nr_pages)
        for (i = 0; i < nr_pages; i++) {
                struct page *page;
 
-               if (!pfn_valid_within(pfn + i))
-                       continue;
                page = pfn_to_online_page(pfn + i);
                if (!page)
                        continue;
index b1739dc..0468ba5 100644 (file)
@@ -9,8 +9,17 @@
  * pcpu_block_md is the metadata block struct.
  * Each chunk's bitmap is split into a number of full blocks.
  * All units are in terms of bits.
+ *
+ * The scan hint is the largest known contiguous area before the contig hint.
+ * It is not necessarily the actual largest contig hint though.  There is an
+ * invariant that the scan_hint_start > contig_hint_start iff
+ * scan_hint == contig_hint.  This is necessary because when scanning forward,
+ * we don't know if a new contig hint would be better than the current one.
  */
 struct pcpu_block_md {
+       int                     scan_hint;      /* scan hint for block */
+       int                     scan_hint_start; /* block relative starting
+                                                   position of the scan hint */
        int                     contig_hint;    /* contig hint for block */
        int                     contig_hint_start; /* block relative starting
                                                      position of the contig hint */
@@ -19,6 +28,7 @@ struct pcpu_block_md {
        int                     right_free;     /* size of free space along
                                                   the right side of the block */
        int                     first_free;     /* block position of first free */
+       int                     nr_bits;        /* total bits responsible for */
 };
 
 struct pcpu_chunk {
@@ -29,9 +39,7 @@ struct pcpu_chunk {
 
        struct list_head        list;           /* linked to pcpu_slot lists */
        int                     free_bytes;     /* free bytes in the chunk */
-       int                     contig_bits;    /* max contiguous size hint */
-       int                     contig_bits_start; /* contig_bits starting
-                                                     offset */
+       struct pcpu_block_md    chunk_md;
        void                    *base_addr;     /* base address of this chunk */
 
        unsigned long           *alloc_map;     /* allocation map */
@@ -39,7 +47,6 @@ struct pcpu_chunk {
        struct pcpu_block_md    *md_blocks;     /* metadata blocks */
 
        void                    *data;          /* chunk data */
-       int                     first_bit;      /* no free below this */
        bool                    immutable;      /* no [de]population allowed */
        int                     start_offset;   /* the overlap with the previous
                                                   region to have a page aligned
index b68d5df..3a2ff5c 100644 (file)
@@ -70,7 +70,7 @@ static struct pcpu_chunk *pcpu_create_chunk(gfp_t gfp)
        chunk->base_addr = page_address(pages);
 
        spin_lock_irqsave(&pcpu_lock, flags);
-       pcpu_chunk_populated(chunk, 0, nr_pages, false);
+       pcpu_chunk_populated(chunk, 0, nr_pages);
        spin_unlock_irqrestore(&pcpu_lock, flags);
 
        pcpu_stats_chunk_alloc();
index b5fdd43..ef5034a 100644 (file)
@@ -53,6 +53,7 @@ static int find_max_nr_alloc(void)
 static void chunk_map_stats(struct seq_file *m, struct pcpu_chunk *chunk,
                            int *buffer)
 {
+       struct pcpu_block_md *chunk_md = &chunk->chunk_md;
        int i, last_alloc, as_len, start, end;
        int *alloc_sizes, *p;
        /* statistics */
@@ -121,9 +122,9 @@ static void chunk_map_stats(struct seq_file *m, struct pcpu_chunk *chunk,
        P("nr_alloc", chunk->nr_alloc);
        P("max_alloc_size", chunk->max_alloc_size);
        P("empty_pop_pages", chunk->nr_empty_pop_pages);
-       P("first_bit", chunk->first_bit);
+       P("first_bit", chunk_md->first_free);
        P("free_bytes", chunk->free_bytes);
-       P("contig_bytes", chunk->contig_bits * PCPU_MIN_ALLOC_SIZE);
+       P("contig_bytes", chunk_md->contig_hint * PCPU_MIN_ALLOC_SIZE);
        P("sum_frag", sum_frag);
        P("max_frag", max_frag);
        P("cur_min_alloc", cur_min_alloc);
index 68dd2e7..2df0ee6 100644 (file)
@@ -94,6 +94,8 @@
 
 /* the slots are sorted by free bytes left, 1-31 bytes share the same slot */
 #define PCPU_SLOT_BASE_SHIFT           5
+/* chunks in slots below this are subject to being sidelined on failed alloc */
+#define PCPU_SLOT_FAIL_THRESHOLD       3
 
 #define PCPU_EMPTY_POP_PAGES_LOW       2
 #define PCPU_EMPTY_POP_PAGES_HIGH      4
@@ -231,10 +233,13 @@ static int pcpu_size_to_slot(int size)
 
 static int pcpu_chunk_slot(const struct pcpu_chunk *chunk)
 {
-       if (chunk->free_bytes < PCPU_MIN_ALLOC_SIZE || chunk->contig_bits == 0)
+       const struct pcpu_block_md *chunk_md = &chunk->chunk_md;
+
+       if (chunk->free_bytes < PCPU_MIN_ALLOC_SIZE ||
+           chunk_md->contig_hint == 0)
                return 0;
 
-       return pcpu_size_to_slot(chunk->free_bytes);
+       return pcpu_size_to_slot(chunk_md->contig_hint * PCPU_MIN_ALLOC_SIZE);
 }
 
 /* set the pointer to a chunk in a page struct */
@@ -318,6 +323,34 @@ static unsigned long pcpu_block_off_to_off(int index, int off)
        return index * PCPU_BITMAP_BLOCK_BITS + off;
 }
 
+/*
+ * pcpu_next_hint - determine which hint to use
+ * @block: block of interest
+ * @alloc_bits: size of allocation
+ *
+ * This determines if we should scan based on the scan_hint or first_free.
+ * In general, we want to scan from first_free to fulfill allocations by
+ * first fit.  However, if we know a scan_hint at position scan_hint_start
+ * cannot fulfill an allocation, we can begin scanning from there knowing
+ * the contig_hint will be our fallback.
+ */
+static int pcpu_next_hint(struct pcpu_block_md *block, int alloc_bits)
+{
+       /*
+        * The three conditions below determine if we can skip past the
+        * scan_hint.  First, does the scan hint exist.  Second, is the
+        * contig_hint after the scan_hint (possibly not true iff
+        * contig_hint == scan_hint).  Third, is the allocation request
+        * larger than the scan_hint.
+        */
+       if (block->scan_hint &&
+           block->contig_hint_start > block->scan_hint_start &&
+           alloc_bits > block->scan_hint)
+               return block->scan_hint_start + block->scan_hint;
+
+       return block->first_free;
+}
+
 /**
  * pcpu_next_md_free_region - finds the next hint free area
  * @chunk: chunk of interest
@@ -413,9 +446,11 @@ static void pcpu_next_fit_region(struct pcpu_chunk *chunk, int alloc_bits,
                if (block->contig_hint &&
                    block->contig_hint_start >= block_off &&
                    block->contig_hint >= *bits + alloc_bits) {
+                       int start = pcpu_next_hint(block, alloc_bits);
+
                        *bits += alloc_bits + block->contig_hint_start -
-                                block->first_free;
-                       *bit_off = pcpu_block_off_to_off(i, block->first_free);
+                                start;
+                       *bit_off = pcpu_block_off_to_off(i, start);
                        return;
                }
                /* reset to satisfy the second predicate above */
@@ -488,6 +523,22 @@ static void pcpu_mem_free(void *ptr)
        kvfree(ptr);
 }
 
+static void __pcpu_chunk_move(struct pcpu_chunk *chunk, int slot,
+                             bool move_front)
+{
+       if (chunk != pcpu_reserved_chunk) {
+               if (move_front)
+                       list_move(&chunk->list, &pcpu_slot[slot]);
+               else
+                       list_move_tail(&chunk->list, &pcpu_slot[slot]);
+       }
+}
+
+static void pcpu_chunk_move(struct pcpu_chunk *chunk, int slot)
+{
+       __pcpu_chunk_move(chunk, slot, true);
+}
+
 /**
  * pcpu_chunk_relocate - put chunk in the appropriate chunk slot
  * @chunk: chunk of interest
@@ -505,110 +556,39 @@ static void pcpu_chunk_relocate(struct pcpu_chunk *chunk, int oslot)
 {
        int nslot = pcpu_chunk_slot(chunk);
 
-       if (chunk != pcpu_reserved_chunk && oslot != nslot) {
-               if (oslot < nslot)
-                       list_move(&chunk->list, &pcpu_slot[nslot]);
-               else
-                       list_move_tail(&chunk->list, &pcpu_slot[nslot]);
-       }
+       if (oslot != nslot)
+               __pcpu_chunk_move(chunk, nslot, oslot < nslot);
 }
 
-/**
- * pcpu_cnt_pop_pages- counts populated backing pages in range
+/*
+ * pcpu_update_empty_pages - update empty page counters
  * @chunk: chunk of interest
- * @bit_off: start offset
- * @bits: size of area to check
- *
- * Calculates the number of populated pages in the region
- * [page_start, page_end).  This keeps track of how many empty populated
- * pages are available and decide if async work should be scheduled.
+ * @nr: nr of empty pages
  *
- * RETURNS:
- * The nr of populated pages.
+ * This is used to keep track of the empty pages now based on the premise
+ * a md_block covers a page.  The hint update functions recognize if a block
+ * is made full or broken to calculate deltas for keeping track of free pages.
  */
-static inline int pcpu_cnt_pop_pages(struct pcpu_chunk *chunk, int bit_off,
-                                    int bits)
+static inline void pcpu_update_empty_pages(struct pcpu_chunk *chunk, int nr)
 {
-       int page_start = PFN_UP(bit_off * PCPU_MIN_ALLOC_SIZE);
-       int page_end = PFN_DOWN((bit_off + bits) * PCPU_MIN_ALLOC_SIZE);
-
-       if (page_start >= page_end)
-               return 0;
-
-       /*
-        * bitmap_weight counts the number of bits set in a bitmap up to
-        * the specified number of bits.  This is counting the populated
-        * pages up to page_end and then subtracting the populated pages
-        * up to page_start to count the populated pages in
-        * [page_start, page_end).
-        */
-       return bitmap_weight(chunk->populated, page_end) -
-              bitmap_weight(chunk->populated, page_start);
-}
-
-/**
- * pcpu_chunk_update - updates the chunk metadata given a free area
- * @chunk: chunk of interest
- * @bit_off: chunk offset
- * @bits: size of free area
- *
- * This updates the chunk's contig hint and starting offset given a free area.
- * Choose the best starting offset if the contig hint is equal.
- */
-static void pcpu_chunk_update(struct pcpu_chunk *chunk, int bit_off, int bits)
-{
-       if (bits > chunk->contig_bits) {
-               chunk->contig_bits_start = bit_off;
-               chunk->contig_bits = bits;
-       } else if (bits == chunk->contig_bits && chunk->contig_bits_start &&
-                  (!bit_off ||
-                   __ffs(bit_off) > __ffs(chunk->contig_bits_start))) {
-               /* use the start with the best alignment */
-               chunk->contig_bits_start = bit_off;
-       }
+       chunk->nr_empty_pop_pages += nr;
+       if (chunk != pcpu_reserved_chunk)
+               pcpu_nr_empty_pop_pages += nr;
 }
 
-/**
- * pcpu_chunk_refresh_hint - updates metadata about a chunk
- * @chunk: chunk of interest
- *
- * Iterates over the metadata blocks to find the largest contig area.
- * It also counts the populated pages and uses the delta to update the
- * global count.
- *
- * Updates:
- *      chunk->contig_bits
- *      chunk->contig_bits_start
- *      nr_empty_pop_pages (chunk and global)
+/*
+ * pcpu_region_overlap - determines if two regions overlap
+ * @a: start of first region, inclusive
+ * @b: end of first region, exclusive
+ * @x: start of second region, inclusive
+ * @y: end of second region, exclusive
+ *
+ * This is used to determine if the hint region [a, b) overlaps with the
+ * allocated region [x, y).
  */
-static void pcpu_chunk_refresh_hint(struct pcpu_chunk *chunk)
+static inline bool pcpu_region_overlap(int a, int b, int x, int y)
 {
-       int bit_off, bits, nr_empty_pop_pages;
-
-       /* clear metadata */
-       chunk->contig_bits = 0;
-
-       bit_off = chunk->first_bit;
-       bits = nr_empty_pop_pages = 0;
-       pcpu_for_each_md_free_region(chunk, bit_off, bits) {
-               pcpu_chunk_update(chunk, bit_off, bits);
-
-               nr_empty_pop_pages += pcpu_cnt_pop_pages(chunk, bit_off, bits);
-       }
-
-       /*
-        * Keep track of nr_empty_pop_pages.
-        *
-        * The chunk maintains the previous number of free pages it held,
-        * so the delta is used to update the global counter.  The reserved
-        * chunk is not part of the free page count as they are populated
-        * at init and are special to serving reserved allocations.
-        */
-       if (chunk != pcpu_reserved_chunk)
-               pcpu_nr_empty_pop_pages +=
-                       (nr_empty_pop_pages - chunk->nr_empty_pop_pages);
-
-       chunk->nr_empty_pop_pages = nr_empty_pop_pages;
+       return (a < y) && (x < b);
 }
 
 /**
@@ -629,16 +609,132 @@ static void pcpu_block_update(struct pcpu_block_md *block, int start, int end)
        if (start == 0)
                block->left_free = contig;
 
-       if (end == PCPU_BITMAP_BLOCK_BITS)
+       if (end == block->nr_bits)
                block->right_free = contig;
 
        if (contig > block->contig_hint) {
+               /* promote the old contig_hint to be the new scan_hint */
+               if (start > block->contig_hint_start) {
+                       if (block->contig_hint > block->scan_hint) {
+                               block->scan_hint_start =
+                                       block->contig_hint_start;
+                               block->scan_hint = block->contig_hint;
+                       } else if (start < block->scan_hint_start) {
+                               /*
+                                * The old contig_hint == scan_hint.  But, the
+                                * new contig is larger so hold the invariant
+                                * scan_hint_start < contig_hint_start.
+                                */
+                               block->scan_hint = 0;
+                       }
+               } else {
+                       block->scan_hint = 0;
+               }
                block->contig_hint_start = start;
                block->contig_hint = contig;
-       } else if (block->contig_hint_start && contig == block->contig_hint &&
-                  (!start || __ffs(start) > __ffs(block->contig_hint_start))) {
-               /* use the start with the best alignment */
-               block->contig_hint_start = start;
+       } else if (contig == block->contig_hint) {
+               if (block->contig_hint_start &&
+                   (!start ||
+                    __ffs(start) > __ffs(block->contig_hint_start))) {
+                       /* start has a better alignment so use it */
+                       block->contig_hint_start = start;
+                       if (start < block->scan_hint_start &&
+                           block->contig_hint > block->scan_hint)
+                               block->scan_hint = 0;
+               } else if (start > block->scan_hint_start ||
+                          block->contig_hint > block->scan_hint) {
+                       /*
+                        * Knowing contig == contig_hint, update the scan_hint
+                        * if it is farther than or larger than the current
+                        * scan_hint.
+                        */
+                       block->scan_hint_start = start;
+                       block->scan_hint = contig;
+               }
+       } else {
+               /*
+                * The region is smaller than the contig_hint.  So only update
+                * the scan_hint if it is larger than or equal and farther than
+                * the current scan_hint.
+                */
+               if ((start < block->contig_hint_start &&
+                    (contig > block->scan_hint ||
+                     (contig == block->scan_hint &&
+                      start > block->scan_hint_start)))) {
+                       block->scan_hint_start = start;
+                       block->scan_hint = contig;
+               }
+       }
+}
+
+/*
+ * pcpu_block_update_scan - update a block given a free area from a scan
+ * @chunk: chunk of interest
+ * @bit_off: chunk offset
+ * @bits: size of free area
+ *
+ * Finding the final allocation spot first goes through pcpu_find_block_fit()
+ * to find a block that can hold the allocation and then pcpu_alloc_area()
+ * where a scan is used.  When allocations require specific alignments,
+ * we can inadvertently create holes which will not be seen in the alloc
+ * or free paths.
+ *
+ * This takes a given free area hole and updates a block as it may change the
+ * scan_hint.  We need to scan backwards to ensure we don't miss free bits
+ * from alignment.
+ */
+static void pcpu_block_update_scan(struct pcpu_chunk *chunk, int bit_off,
+                                  int bits)
+{
+       int s_off = pcpu_off_to_block_off(bit_off);
+       int e_off = s_off + bits;
+       int s_index, l_bit;
+       struct pcpu_block_md *block;
+
+       if (e_off > PCPU_BITMAP_BLOCK_BITS)
+               return;
+
+       s_index = pcpu_off_to_block_index(bit_off);
+       block = chunk->md_blocks + s_index;
+
+       /* scan backwards in case of alignment skipping free bits */
+       l_bit = find_last_bit(pcpu_index_alloc_map(chunk, s_index), s_off);
+       s_off = (s_off == l_bit) ? 0 : l_bit + 1;
+
+       pcpu_block_update(block, s_off, e_off);
+}
+
+/**
+ * pcpu_chunk_refresh_hint - updates metadata about a chunk
+ * @chunk: chunk of interest
+ * @full_scan: if we should scan from the beginning
+ *
+ * Iterates over the metadata blocks to find the largest contig area.
+ * A full scan can be avoided on the allocation path as this is triggered
+ * if we broke the contig_hint.  In doing so, the scan_hint will be before
+ * the contig_hint or after if the scan_hint == contig_hint.  This cannot
+ * be prevented on freeing as we want to find the largest area possibly
+ * spanning blocks.
+ */
+static void pcpu_chunk_refresh_hint(struct pcpu_chunk *chunk, bool full_scan)
+{
+       struct pcpu_block_md *chunk_md = &chunk->chunk_md;
+       int bit_off, bits;
+
+       /* promote scan_hint to contig_hint */
+       if (!full_scan && chunk_md->scan_hint) {
+               bit_off = chunk_md->scan_hint_start + chunk_md->scan_hint;
+               chunk_md->contig_hint_start = chunk_md->scan_hint_start;
+               chunk_md->contig_hint = chunk_md->scan_hint;
+               chunk_md->scan_hint = 0;
+       } else {
+               bit_off = chunk_md->first_free;
+               chunk_md->contig_hint = 0;
+       }
+
+       bits = 0;
+       pcpu_for_each_md_free_region(chunk, bit_off, bits) {
+               pcpu_block_update(chunk_md, bit_off, bit_off + bits);
        }
 }
 
@@ -654,14 +750,23 @@ static void pcpu_block_refresh_hint(struct pcpu_chunk *chunk, int index)
 {
        struct pcpu_block_md *block = chunk->md_blocks + index;
        unsigned long *alloc_map = pcpu_index_alloc_map(chunk, index);
-       int rs, re;     /* region start, region end */
+       int rs, re, start;      /* region start, region end */
+
+       /* promote scan_hint to contig_hint */
+       if (block->scan_hint) {
+               start = block->scan_hint_start + block->scan_hint;
+               block->contig_hint_start = block->scan_hint_start;
+               block->contig_hint = block->scan_hint;
+               block->scan_hint = 0;
+       } else {
+               start = block->first_free;
+               block->contig_hint = 0;
+       }
 
-       /* clear hints */
-       block->contig_hint = 0;
-       block->left_free = block->right_free = 0;
+       block->right_free = 0;
 
        /* iterate over free areas and update the contig hints */
-       pcpu_for_each_unpop_region(alloc_map, rs, re, block->first_free,
+       pcpu_for_each_unpop_region(alloc_map, rs, re, start,
                                   PCPU_BITMAP_BLOCK_BITS) {
                pcpu_block_update(block, rs, re);
        }
@@ -680,6 +785,8 @@ static void pcpu_block_refresh_hint(struct pcpu_chunk *chunk, int index)
 static void pcpu_block_update_hint_alloc(struct pcpu_chunk *chunk, int bit_off,
                                         int bits)
 {
+       struct pcpu_block_md *chunk_md = &chunk->chunk_md;
+       int nr_empty_pages = 0;
        struct pcpu_block_md *s_block, *e_block, *block;
        int s_index, e_index;   /* block indexes of the freed allocation */
        int s_off, e_off;       /* block offsets of the freed allocation */
@@ -704,15 +811,29 @@ static void pcpu_block_update_hint_alloc(struct pcpu_chunk *chunk, int bit_off,
         * If the allocation breaks the contig_hint, a scan is required to
         * restore this hint.
         */
+       if (s_block->contig_hint == PCPU_BITMAP_BLOCK_BITS)
+               nr_empty_pages++;
+
        if (s_off == s_block->first_free)
                s_block->first_free = find_next_zero_bit(
                                        pcpu_index_alloc_map(chunk, s_index),
                                        PCPU_BITMAP_BLOCK_BITS,
                                        s_off + bits);
 
-       if (s_off >= s_block->contig_hint_start &&
-           s_off < s_block->contig_hint_start + s_block->contig_hint) {
+       if (pcpu_region_overlap(s_block->scan_hint_start,
+                               s_block->scan_hint_start + s_block->scan_hint,
+                               s_off,
+                               s_off + bits))
+               s_block->scan_hint = 0;
+
+       if (pcpu_region_overlap(s_block->contig_hint_start,
+                               s_block->contig_hint_start +
+                               s_block->contig_hint,
+                               s_off,
+                               s_off + bits)) {
                /* block contig hint is broken - scan to fix it */
+               if (!s_off)
+                       s_block->left_free = 0;
                pcpu_block_refresh_hint(chunk, s_index);
        } else {
                /* update left and right contig manually */
@@ -728,6 +849,9 @@ static void pcpu_block_update_hint_alloc(struct pcpu_chunk *chunk, int bit_off,
         * Update e_block.
         */
        if (s_index != e_index) {
+               if (e_block->contig_hint == PCPU_BITMAP_BLOCK_BITS)
+                       nr_empty_pages++;
+
                /*
                 * When the allocation is across blocks, the end is along
                 * the left part of the e_block.
@@ -740,11 +864,14 @@ static void pcpu_block_update_hint_alloc(struct pcpu_chunk *chunk, int bit_off,
                        /* reset the block */
                        e_block++;
                } else {
+                       if (e_off > e_block->scan_hint_start)
+                               e_block->scan_hint = 0;
+
+                       e_block->left_free = 0;
                        if (e_off > e_block->contig_hint_start) {
                                /* contig hint is broken - scan to fix it */
                                pcpu_block_refresh_hint(chunk, e_index);
                        } else {
-                               e_block->left_free = 0;
                                e_block->right_free =
                                        min_t(int, e_block->right_free,
                                              PCPU_BITMAP_BLOCK_BITS - e_off);
@@ -752,21 +879,36 @@ static void pcpu_block_update_hint_alloc(struct pcpu_chunk *chunk, int bit_off,
                }
 
                /* update in-between md_blocks */
+               nr_empty_pages += (e_index - s_index - 1);
                for (block = s_block + 1; block < e_block; block++) {
+                       block->scan_hint = 0;
                        block->contig_hint = 0;
                        block->left_free = 0;
                        block->right_free = 0;
                }
        }
 
+       if (nr_empty_pages)
+               pcpu_update_empty_pages(chunk, -nr_empty_pages);
+
+       if (pcpu_region_overlap(chunk_md->scan_hint_start,
+                               chunk_md->scan_hint_start +
+                               chunk_md->scan_hint,
+                               bit_off,
+                               bit_off + bits))
+               chunk_md->scan_hint = 0;
+
        /*
         * The only time a full chunk scan is required is if the chunk
         * contig hint is broken.  Otherwise, it means a smaller space
         * was used and therefore the chunk contig hint is still correct.
         */
-       if (bit_off >= chunk->contig_bits_start  &&
-           bit_off < chunk->contig_bits_start + chunk->contig_bits)
-               pcpu_chunk_refresh_hint(chunk);
+       if (pcpu_region_overlap(chunk_md->contig_hint_start,
+                               chunk_md->contig_hint_start +
+                               chunk_md->contig_hint,
+                               bit_off,
+                               bit_off + bits))
+               pcpu_chunk_refresh_hint(chunk, false);
 }
 
 /**
@@ -782,13 +924,15 @@ static void pcpu_block_update_hint_alloc(struct pcpu_chunk *chunk, int bit_off,
  *
  * A chunk update is triggered if a page becomes free, a block becomes free,
  * or the free spans across blocks.  This tradeoff is to minimize iterating
- * over the block metadata to update chunk->contig_bits.  chunk->contig_bits
- * may be off by up to a page, but it will never be more than the available
- * space.  If the contig hint is contained in one block, it will be accurate.
+ * over the block metadata to update chunk_md->contig_hint.
+ * chunk_md->contig_hint may be off by up to a page, but it will never be more
+ * than the available space.  If the contig hint is contained in one block, it
+ * will be accurate.
  */
 static void pcpu_block_update_hint_free(struct pcpu_chunk *chunk, int bit_off,
                                        int bits)
 {
+       int nr_empty_pages = 0;
        struct pcpu_block_md *s_block, *e_block, *block;
        int s_index, e_index;   /* block indexes of the freed allocation */
        int s_off, e_off;       /* block offsets of the freed allocation */
@@ -842,16 +986,22 @@ static void pcpu_block_update_hint_free(struct pcpu_chunk *chunk, int bit_off,
 
        /* update s_block */
        e_off = (s_index == e_index) ? end : PCPU_BITMAP_BLOCK_BITS;
+       if (!start && e_off == PCPU_BITMAP_BLOCK_BITS)
+               nr_empty_pages++;
        pcpu_block_update(s_block, start, e_off);
 
        /* freeing in the same block */
        if (s_index != e_index) {
                /* update e_block */
+               if (end == PCPU_BITMAP_BLOCK_BITS)
+                       nr_empty_pages++;
                pcpu_block_update(e_block, 0, end);
 
                /* reset md_blocks in the middle */
+               nr_empty_pages += (e_index - s_index - 1);
                for (block = s_block + 1; block < e_block; block++) {
                        block->first_free = 0;
+                       block->scan_hint = 0;
                        block->contig_hint_start = 0;
                        block->contig_hint = PCPU_BITMAP_BLOCK_BITS;
                        block->left_free = PCPU_BITMAP_BLOCK_BITS;
@@ -859,19 +1009,21 @@ static void pcpu_block_update_hint_free(struct pcpu_chunk *chunk, int bit_off,
                }
        }
 
+       if (nr_empty_pages)
+               pcpu_update_empty_pages(chunk, nr_empty_pages);
+
        /*
-        * Refresh chunk metadata when the free makes a page free, a block
-        * free, or spans across blocks.  The contig hint may be off by up to
-        * a page, but if the hint is contained in a block, it will be accurate
-        * with the else condition below.
+        * Refresh chunk metadata when the free makes a block free or spans
+        * across blocks.  The contig_hint may be off by up to a page, but if
+        * the contig_hint is contained in a block, it will be accurate with
+        * the else condition below.
         */
-       if ((ALIGN_DOWN(end, min(PCPU_BITS_PER_PAGE, PCPU_BITMAP_BLOCK_BITS)) >
-            ALIGN(start, min(PCPU_BITS_PER_PAGE, PCPU_BITMAP_BLOCK_BITS))) ||
-           s_index != e_index)
-               pcpu_chunk_refresh_hint(chunk);
+       if (((end - start) >= PCPU_BITMAP_BLOCK_BITS) || s_index != e_index)
+               pcpu_chunk_refresh_hint(chunk, true);
        else
-               pcpu_chunk_update(chunk, pcpu_block_off_to_off(s_index, start),
-                                 s_block->contig_hint);
+               pcpu_block_update(&chunk->chunk_md,
+                                 pcpu_block_off_to_off(s_index, start),
+                                 end);
 }
 
 /**
@@ -926,6 +1078,7 @@ static bool pcpu_is_populated(struct pcpu_chunk *chunk, int bit_off, int bits,
 static int pcpu_find_block_fit(struct pcpu_chunk *chunk, int alloc_bits,
                               size_t align, bool pop_only)
 {
+       struct pcpu_block_md *chunk_md = &chunk->chunk_md;
        int bit_off, bits, next_off;
 
        /*
@@ -934,12 +1087,12 @@ static int pcpu_find_block_fit(struct pcpu_chunk *chunk, int alloc_bits,
         * cannot fit in the global hint, there is memory pressure and creating
         * a new chunk would happen soon.
         */
-       bit_off = ALIGN(chunk->contig_bits_start, align) -
-                 chunk->contig_bits_start;
-       if (bit_off + alloc_bits > chunk->contig_bits)
+       bit_off = ALIGN(chunk_md->contig_hint_start, align) -
+                 chunk_md->contig_hint_start;
+       if (bit_off + alloc_bits > chunk_md->contig_hint)
                return -1;
 
-       bit_off = chunk->first_bit;
+       bit_off = pcpu_next_hint(chunk_md, alloc_bits);
        bits = 0;
        pcpu_for_each_fit_region(chunk, alloc_bits, align, bit_off, bits) {
                if (!pop_only || pcpu_is_populated(chunk, bit_off, bits,
@@ -956,6 +1109,62 @@ static int pcpu_find_block_fit(struct pcpu_chunk *chunk, int alloc_bits,
        return bit_off;
 }
 
+/*
+ * pcpu_find_zero_area - modified from bitmap_find_next_zero_area_off()
+ * @map: the address to base the search on
+ * @size: the bitmap size in bits
+ * @start: the bitnumber to start searching at
+ * @nr: the number of zeroed bits we're looking for
+ * @align_mask: alignment mask for zero area
+ * @largest_off: offset of the largest area skipped
+ * @largest_bits: size of the largest area skipped
+ *
+ * The @align_mask should be one less than a power of 2.
+ *
+ * This is a modified version of bitmap_find_next_zero_area_off() to remember
+ * the largest area that was skipped.  This is imperfect, but in general is
+ * good enough.  The largest remembered region is the largest failed region
+ * seen.  This does not include anything we possibly skipped due to alignment.
+ * pcpu_block_update_scan() does scan backwards to try and recover what was
+ * lost to alignment.  While this can cause scanning to miss earlier possible
+ * free areas, smaller allocations will eventually fill those holes.
+ */
+static unsigned long pcpu_find_zero_area(unsigned long *map,
+                                        unsigned long size,
+                                        unsigned long start,
+                                        unsigned long nr,
+                                        unsigned long align_mask,
+                                        unsigned long *largest_off,
+                                        unsigned long *largest_bits)
+{
+       unsigned long index, end, i, area_off, area_bits;
+again:
+       index = find_next_zero_bit(map, size, start);
+
+       /* Align allocation */
+       index = __ALIGN_MASK(index, align_mask);
+       area_off = index;
+
+       end = index + nr;
+       if (end > size)
+               return end;
+       i = find_next_bit(map, end, index);
+       if (i < end) {
+               area_bits = i - area_off;
+               /* remember largest unused area with best alignment */
+               if (area_bits > *largest_bits ||
+                   (area_bits == *largest_bits && *largest_off &&
+                    (!area_off || __ffs(area_off) > __ffs(*largest_off)))) {
+                       *largest_off = area_off;
+                       *largest_bits = area_bits;
+               }
+
+               start = i + 1;
+               goto again;
+       }
+       return index;
+}
+
 /**
  * pcpu_alloc_area - allocates an area from a pcpu_chunk
  * @chunk: chunk of interest
@@ -978,7 +1187,9 @@ static int pcpu_find_block_fit(struct pcpu_chunk *chunk, int alloc_bits,
 static int pcpu_alloc_area(struct pcpu_chunk *chunk, int alloc_bits,
                           size_t align, int start)
 {
+       struct pcpu_block_md *chunk_md = &chunk->chunk_md;
        size_t align_mask = (align) ? (align - 1) : 0;
+       unsigned long area_off = 0, area_bits = 0;
        int bit_off, end, oslot;
 
        lockdep_assert_held(&pcpu_lock);
@@ -988,12 +1199,16 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int alloc_bits,
        /*
         * Search to find a fit.
         */
-       end = start + alloc_bits + PCPU_BITMAP_BLOCK_BITS;
-       bit_off = bitmap_find_next_zero_area(chunk->alloc_map, end, start,
-                                            alloc_bits, align_mask);
+       end = min_t(int, start + alloc_bits + PCPU_BITMAP_BLOCK_BITS,
+                   pcpu_chunk_map_bits(chunk));
+       bit_off = pcpu_find_zero_area(chunk->alloc_map, end, start, alloc_bits,
+                                     align_mask, &area_off, &area_bits);
        if (bit_off >= end)
                return -1;
 
+       if (area_bits)
+               pcpu_block_update_scan(chunk, area_off, area_bits);
+
        /* update alloc map */
        bitmap_set(chunk->alloc_map, bit_off, alloc_bits);
 
@@ -1005,8 +1220,8 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int alloc_bits,
        chunk->free_bytes -= alloc_bits * PCPU_MIN_ALLOC_SIZE;
 
        /* update first free bit */
-       if (bit_off == chunk->first_bit)
-               chunk->first_bit = find_next_zero_bit(
+       if (bit_off == chunk_md->first_free)
+               chunk_md->first_free = find_next_zero_bit(
                                        chunk->alloc_map,
                                        pcpu_chunk_map_bits(chunk),
                                        bit_off + alloc_bits);
@@ -1028,6 +1243,7 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int alloc_bits,
  */
 static void pcpu_free_area(struct pcpu_chunk *chunk, int off)
 {
+       struct pcpu_block_md *chunk_md = &chunk->chunk_md;
        int bit_off, bits, end, oslot;
 
        lockdep_assert_held(&pcpu_lock);
@@ -1047,24 +1263,34 @@ static void pcpu_free_area(struct pcpu_chunk *chunk, int off)
        chunk->free_bytes += bits * PCPU_MIN_ALLOC_SIZE;
 
        /* update first free bit */
-       chunk->first_bit = min(chunk->first_bit, bit_off);
+       chunk_md->first_free = min(chunk_md->first_free, bit_off);
 
        pcpu_block_update_hint_free(chunk, bit_off, bits);
 
        pcpu_chunk_relocate(chunk, oslot);
 }
 
+static void pcpu_init_md_block(struct pcpu_block_md *block, int nr_bits)
+{
+       block->scan_hint = 0;
+       block->contig_hint = nr_bits;
+       block->left_free = nr_bits;
+       block->right_free = nr_bits;
+       block->first_free = 0;
+       block->nr_bits = nr_bits;
+}
+
 static void pcpu_init_md_blocks(struct pcpu_chunk *chunk)
 {
        struct pcpu_block_md *md_block;
 
+       /* init the chunk's block */
+       pcpu_init_md_block(&chunk->chunk_md, pcpu_chunk_map_bits(chunk));
+
        for (md_block = chunk->md_blocks;
             md_block != chunk->md_blocks + pcpu_chunk_nr_blocks(chunk);
-            md_block++) {
-               md_block->contig_hint = PCPU_BITMAP_BLOCK_BITS;
-               md_block->left_free = PCPU_BITMAP_BLOCK_BITS;
-               md_block->right_free = PCPU_BITMAP_BLOCK_BITS;
-       }
+            md_block++)
+               pcpu_init_md_block(md_block, PCPU_BITMAP_BLOCK_BITS);
 }
 
 /**
@@ -1143,11 +1369,8 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr,
        chunk->immutable = true;
        bitmap_fill(chunk->populated, chunk->nr_pages);
        chunk->nr_populated = chunk->nr_pages;
-       chunk->nr_empty_pop_pages =
-               pcpu_cnt_pop_pages(chunk, start_offset / PCPU_MIN_ALLOC_SIZE,
-                                  map_size / PCPU_MIN_ALLOC_SIZE);
+       chunk->nr_empty_pop_pages = chunk->nr_pages;
 
-       chunk->contig_bits = map_size / PCPU_MIN_ALLOC_SIZE;
        chunk->free_bytes = map_size;
 
        if (chunk->start_offset) {
@@ -1157,7 +1380,7 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr,
                set_bit(0, chunk->bound_map);
                set_bit(offset_bits, chunk->bound_map);
 
-               chunk->first_bit = offset_bits;
+               chunk->chunk_md.first_free = offset_bits;
 
                pcpu_block_update_hint_alloc(chunk, 0, offset_bits);
        }
@@ -1210,7 +1433,6 @@ static struct pcpu_chunk *pcpu_alloc_chunk(gfp_t gfp)
        pcpu_init_md_blocks(chunk);
 
        /* init metadata */
-       chunk->contig_bits = region_bits;
        chunk->free_bytes = chunk->nr_pages * PAGE_SIZE;
 
        return chunk;
@@ -1240,7 +1462,6 @@ static void pcpu_free_chunk(struct pcpu_chunk *chunk)
  * @chunk: pcpu_chunk which got populated
  * @page_start: the start page
  * @page_end: the end page
- * @for_alloc: if this is to populate for allocation
  *
  * Pages in [@page_start,@page_end) have been populated to @chunk.  Update
  * the bookkeeping information accordingly.  Must be called after each
@@ -1250,7 +1471,7 @@ static void pcpu_free_chunk(struct pcpu_chunk *chunk)
  * is to serve an allocation in that area.
  */
 static void pcpu_chunk_populated(struct pcpu_chunk *chunk, int page_start,
-                                int page_end, bool for_alloc)
+                                int page_end)
 {
        int nr = page_end - page_start;
 
@@ -1260,10 +1481,7 @@ static void pcpu_chunk_populated(struct pcpu_chunk *chunk, int page_start,
        chunk->nr_populated += nr;
        pcpu_nr_populated += nr;
 
-       if (!for_alloc) {
-               chunk->nr_empty_pop_pages += nr;
-               pcpu_nr_empty_pop_pages += nr;
-       }
+       pcpu_update_empty_pages(chunk, nr);
 }
 
 /**
@@ -1285,9 +1503,9 @@ static void pcpu_chunk_depopulated(struct pcpu_chunk *chunk,
 
        bitmap_clear(chunk->populated, page_start, nr);
        chunk->nr_populated -= nr;
-       chunk->nr_empty_pop_pages -= nr;
-       pcpu_nr_empty_pop_pages -= nr;
        pcpu_nr_populated -= nr;
+
+       pcpu_update_empty_pages(chunk, -nr);
 }
 
 /*
@@ -1374,7 +1592,7 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved,
        bool is_atomic = (gfp & GFP_KERNEL) != GFP_KERNEL;
        bool do_warn = !(gfp & __GFP_NOWARN);
        static int warn_limit = 10;
-       struct pcpu_chunk *chunk;
+       struct pcpu_chunk *chunk, *next;
        const char *err;
        int slot, off, cpu, ret;
        unsigned long flags;
@@ -1436,11 +1654,14 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved,
 restart:
        /* search through normal chunks */
        for (slot = pcpu_size_to_slot(size); slot < pcpu_nr_slots; slot++) {
-               list_for_each_entry(chunk, &pcpu_slot[slot], list) {
+               list_for_each_entry_safe(chunk, next, &pcpu_slot[slot], list) {
                        off = pcpu_find_block_fit(chunk, bits, bit_align,
                                                  is_atomic);
-                       if (off < 0)
+                       if (off < 0) {
+                               if (slot < PCPU_SLOT_FAIL_THRESHOLD)
+                                       pcpu_chunk_move(chunk, 0);
                                continue;
+                       }
 
                        off = pcpu_alloc_area(chunk, bits, bit_align, off);
                        if (off >= 0)
@@ -1499,7 +1720,7 @@ area_found:
                                err = "failed to populate";
                                goto fail_unlock;
                        }
-                       pcpu_chunk_populated(chunk, rs, re, true);
+                       pcpu_chunk_populated(chunk, rs, re);
                        spin_unlock_irqrestore(&pcpu_lock, flags);
                }
 
@@ -1698,7 +1919,7 @@ retry_pop:
                        if (!ret) {
                                nr_to_pop -= nr;
                                spin_lock_irq(&pcpu_lock);
-                               pcpu_chunk_populated(chunk, rs, rs + nr, false);
+                               pcpu_chunk_populated(chunk, rs, rs + nr);
                                spin_unlock_irq(&pcpu_lock);
                        } else {
                                nr_to_pop = 0;
@@ -1738,6 +1959,7 @@ void free_percpu(void __percpu *ptr)
        struct pcpu_chunk *chunk;
        unsigned long flags;
        int off;
+       bool need_balance = false;
 
        if (!ptr)
                return;
@@ -1759,7 +1981,7 @@ void free_percpu(void __percpu *ptr)
 
                list_for_each_entry(pos, &pcpu_slot[pcpu_nr_slots - 1], list)
                        if (pos != chunk) {
-                               pcpu_schedule_balance_work();
+                               need_balance = true;
                                break;
                        }
        }
@@ -1767,6 +1989,9 @@ void free_percpu(void __percpu *ptr)
        trace_percpu_free_percpu(chunk->base_addr, off, ptr);
 
        spin_unlock_irqrestore(&pcpu_lock, flags);
+
+       if (need_balance)
+               pcpu_schedule_balance_work();
 }
 EXPORT_SYMBOL_GPL(free_percpu);
 
index b30c7c7..e5dfe2a 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -850,7 +850,7 @@ int page_referenced(struct page *page,
        };
 
        *vm_flags = 0;
-       if (!page_mapped(page))
+       if (!pra.mapcount)
                return 0;
 
        if (!page_rmapping(page))
@@ -896,7 +896,8 @@ static bool page_mkclean_one(struct page *page, struct vm_area_struct *vma,
         * We have to assume the worse case ie pmd for invalidation. Note that
         * the page can not be free from this function.
         */
-       mmu_notifier_range_init(&range, vma->vm_mm, address,
+       mmu_notifier_range_init(&range, MMU_NOTIFY_PROTECTION_PAGE,
+                               0, vma, vma->vm_mm, address,
                                min(vma->vm_end, address +
                                    (PAGE_SIZE << compound_order(page))));
        mmu_notifier_invalidate_range_start(&range);
@@ -928,7 +929,7 @@ static bool page_mkclean_one(struct page *page, struct vm_area_struct *vma,
                                continue;
 
                        flush_cache_page(vma, address, page_to_pfn(page));
-                       entry = pmdp_huge_clear_flush(vma, address, pmd);
+                       entry = pmdp_invalidate(vma, address, pmd);
                        entry = pmd_wrprotect(entry);
                        entry = pmd_mkclean(entry);
                        set_pmd_at(vma->vm_mm, address, pmd, entry);
@@ -1371,7 +1372,8 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
         * Note that the page can not be free in this function as call of
         * try_to_unmap() must hold a reference on the page.
         */
-       mmu_notifier_range_init(&range, vma->vm_mm, address,
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, vma->vm_mm,
+                               address,
                                min(vma->vm_end, address +
                                    (PAGE_SIZE << compound_order(page))));
        if (PageHuge(page)) {
index f4dce9c..1bb3b8d 100644 (file)
@@ -614,7 +614,7 @@ static int shmem_add_to_page_cache(struct page *page,
                if (xas_error(&xas))
                        goto unlock;
 next:
-               xas_store(&xas, page + i);
+               xas_store(&xas, page);
                if (++i < nr) {
                        xas_next(&xas);
                        goto next;
diff --git a/mm/shuffle.c b/mm/shuffle.c
new file mode 100644 (file)
index 0000000..3ce1248
--- /dev/null
@@ -0,0 +1,207 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright(c) 2018 Intel Corporation. All rights reserved.
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/mmzone.h>
+#include <linux/random.h>
+#include <linux/moduleparam.h>
+#include "internal.h"
+#include "shuffle.h"
+
+DEFINE_STATIC_KEY_FALSE(page_alloc_shuffle_key);
+static unsigned long shuffle_state __ro_after_init;
+
+/*
+ * Depending on the architecture, module parameter parsing may run
+ * before, or after the cache detection. SHUFFLE_FORCE_DISABLE prevents,
+ * or reverts the enabling of the shuffle implementation. SHUFFLE_ENABLE
+ * attempts to turn on the implementation, but aborts if it finds
+ * SHUFFLE_FORCE_DISABLE already set.
+ */
+__meminit void page_alloc_shuffle(enum mm_shuffle_ctl ctl)
+{
+       if (ctl == SHUFFLE_FORCE_DISABLE)
+               set_bit(SHUFFLE_FORCE_DISABLE, &shuffle_state);
+
+       if (test_bit(SHUFFLE_FORCE_DISABLE, &shuffle_state)) {
+               if (test_and_clear_bit(SHUFFLE_ENABLE, &shuffle_state))
+                       static_branch_disable(&page_alloc_shuffle_key);
+       } else if (ctl == SHUFFLE_ENABLE
+                       && !test_and_set_bit(SHUFFLE_ENABLE, &shuffle_state))
+               static_branch_enable(&page_alloc_shuffle_key);
+}
+
+static bool shuffle_param;
+extern int shuffle_show(char *buffer, const struct kernel_param *kp)
+{
+       return sprintf(buffer, "%c\n", test_bit(SHUFFLE_ENABLE, &shuffle_state)
+                       ? 'Y' : 'N');
+}
+
+static __meminit int shuffle_store(const char *val,
+               const struct kernel_param *kp)
+{
+       int rc = param_set_bool(val, kp);
+
+       if (rc < 0)
+               return rc;
+       if (shuffle_param)
+               page_alloc_shuffle(SHUFFLE_ENABLE);
+       else
+               page_alloc_shuffle(SHUFFLE_FORCE_DISABLE);
+       return 0;
+}
+module_param_call(shuffle, shuffle_store, shuffle_show, &shuffle_param, 0400);
+
+/*
+ * For two pages to be swapped in the shuffle, they must be free (on a
+ * 'free_area' lru), have the same order, and have the same migratetype.
+ */
+static struct page * __meminit shuffle_valid_page(unsigned long pfn, int order)
+{
+       struct page *page;
+
+       /*
+        * Given we're dealing with randomly selected pfns in a zone we
+        * need to ask questions like...
+        */
+
+       /* ...is the pfn even in the memmap? */
+       if (!pfn_valid_within(pfn))
+               return NULL;
+
+       /* ...is the pfn in a present section or a hole? */
+       if (!pfn_present(pfn))
+               return NULL;
+
+       /* ...is the page free and currently on a free_area list? */
+       page = pfn_to_page(pfn);
+       if (!PageBuddy(page))
+               return NULL;
+
+       /*
+        * ...is the page on the same list as the page we will
+        * shuffle it with?
+        */
+       if (page_order(page) != order)
+               return NULL;
+
+       return page;
+}
+
+/*
+ * Fisher-Yates shuffle the freelist which prescribes iterating through an
+ * array, pfns in this case, and randomly swapping each entry with another in
+ * the span, end_pfn - start_pfn.
+ *
+ * To keep the implementation simple it does not attempt to correct for sources
+ * of bias in the distribution, like modulo bias or pseudo-random number
+ * generator bias. I.e. the expectation is that this shuffling raises the bar
+ * for attacks that exploit the predictability of page allocations, but need not
+ * be a perfect shuffle.
+ */
+#define SHUFFLE_RETRY 10
+void __meminit __shuffle_zone(struct zone *z)
+{
+       unsigned long i, flags;
+       unsigned long start_pfn = z->zone_start_pfn;
+       unsigned long end_pfn = zone_end_pfn(z);
+       const int order = SHUFFLE_ORDER;
+       const int order_pages = 1 << order;
+
+       spin_lock_irqsave(&z->lock, flags);
+       start_pfn = ALIGN(start_pfn, order_pages);
+       for (i = start_pfn; i < end_pfn; i += order_pages) {
+               unsigned long j;
+               int migratetype, retry;
+               struct page *page_i, *page_j;
+
+               /*
+                * We expect page_i, in the sub-range of a zone being added
+                * (@start_pfn to @end_pfn), to more likely be valid compared to
+                * page_j randomly selected in the span @zone_start_pfn to
+                * @spanned_pages.
+                */
+               page_i = shuffle_valid_page(i, order);
+               if (!page_i)
+                       continue;
+
+               for (retry = 0; retry < SHUFFLE_RETRY; retry++) {
+                       /*
+                        * Pick a random order aligned page in the zone span as
+                        * a swap target. If the selected pfn is a hole, retry
+                        * up to SHUFFLE_RETRY attempts find a random valid pfn
+                        * in the zone.
+                        */
+                       j = z->zone_start_pfn +
+                               ALIGN_DOWN(get_random_long() % z->spanned_pages,
+                                               order_pages);
+                       page_j = shuffle_valid_page(j, order);
+                       if (page_j && page_j != page_i)
+                               break;
+               }
+               if (retry >= SHUFFLE_RETRY) {
+                       pr_debug("%s: failed to swap %#lx\n", __func__, i);
+                       continue;
+               }
+
+               /*
+                * Each migratetype corresponds to its own list, make sure the
+                * types match otherwise we're moving pages to lists where they
+                * do not belong.
+                */
+               migratetype = get_pageblock_migratetype(page_i);
+               if (get_pageblock_migratetype(page_j) != migratetype) {
+                       pr_debug("%s: migratetype mismatch %#lx\n", __func__, i);
+                       continue;
+               }
+
+               list_swap(&page_i->lru, &page_j->lru);
+
+               pr_debug("%s: swap: %#lx -> %#lx\n", __func__, i, j);
+
+               /* take it easy on the zone lock */
+               if ((i % (100 * order_pages)) == 0) {
+                       spin_unlock_irqrestore(&z->lock, flags);
+                       cond_resched();
+                       spin_lock_irqsave(&z->lock, flags);
+               }
+       }
+       spin_unlock_irqrestore(&z->lock, flags);
+}
+
+/**
+ * shuffle_free_memory - reduce the predictability of the page allocator
+ * @pgdat: node page data
+ */
+void __meminit __shuffle_free_memory(pg_data_t *pgdat)
+{
+       struct zone *z;
+
+       for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
+               shuffle_zone(z);
+}
+
+void add_to_free_area_random(struct page *page, struct free_area *area,
+               int migratetype)
+{
+       static u64 rand;
+       static u8 rand_bits;
+
+       /*
+        * The lack of locking is deliberate. If 2 threads race to
+        * update the rand state it just adds to the entropy.
+        */
+       if (rand_bits == 0) {
+               rand_bits = 64;
+               rand = get_random_u64();
+       }
+
+       if (rand & 1)
+               add_to_free_area(page, area, migratetype);
+       else
+               add_to_free_area_tail(page, area, migratetype);
+       rand_bits--;
+       rand >>= 1;
+}
diff --git a/mm/shuffle.h b/mm/shuffle.h
new file mode 100644 (file)
index 0000000..777a257
--- /dev/null
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright(c) 2018 Intel Corporation. All rights reserved.
+#ifndef _MM_SHUFFLE_H
+#define _MM_SHUFFLE_H
+#include <linux/jump_label.h>
+
+/*
+ * SHUFFLE_ENABLE is called from the command line enabling path, or by
+ * platform-firmware enabling that indicates the presence of a
+ * direct-mapped memory-side-cache. SHUFFLE_FORCE_DISABLE is called from
+ * the command line path and overrides any previous or future
+ * SHUFFLE_ENABLE.
+ */
+enum mm_shuffle_ctl {
+       SHUFFLE_ENABLE,
+       SHUFFLE_FORCE_DISABLE,
+};
+
+#define SHUFFLE_ORDER (MAX_ORDER-1)
+
+#ifdef CONFIG_SHUFFLE_PAGE_ALLOCATOR
+DECLARE_STATIC_KEY_FALSE(page_alloc_shuffle_key);
+extern void page_alloc_shuffle(enum mm_shuffle_ctl ctl);
+extern void __shuffle_free_memory(pg_data_t *pgdat);
+static inline void shuffle_free_memory(pg_data_t *pgdat)
+{
+       if (!static_branch_unlikely(&page_alloc_shuffle_key))
+               return;
+       __shuffle_free_memory(pgdat);
+}
+
+extern void __shuffle_zone(struct zone *z);
+static inline void shuffle_zone(struct zone *z)
+{
+       if (!static_branch_unlikely(&page_alloc_shuffle_key))
+               return;
+       __shuffle_zone(z);
+}
+
+static inline bool is_shuffle_order(int order)
+{
+       if (!static_branch_unlikely(&page_alloc_shuffle_key))
+               return false;
+       return order >= SHUFFLE_ORDER;
+}
+#else
+static inline void shuffle_free_memory(pg_data_t *pgdat)
+{
+}
+
+static inline void shuffle_zone(struct zone *z)
+{
+}
+
+static inline void page_alloc_shuffle(enum mm_shuffle_ctl ctl)
+{
+}
+
+static inline bool is_shuffle_order(int order)
+{
+       return false;
+}
+#endif
+#endif /* _MM_SHUFFLE_H */
index 284ab73..f7117ad 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -362,29 +362,6 @@ static void **dbg_userword(struct kmem_cache *cachep, void *objp)
 
 #endif
 
-#ifdef CONFIG_DEBUG_SLAB_LEAK
-
-static inline bool is_store_user_clean(struct kmem_cache *cachep)
-{
-       return atomic_read(&cachep->store_user_clean) == 1;
-}
-
-static inline void set_store_user_clean(struct kmem_cache *cachep)
-{
-       atomic_set(&cachep->store_user_clean, 1);
-}
-
-static inline void set_store_user_dirty(struct kmem_cache *cachep)
-{
-       if (is_store_user_clean(cachep))
-               atomic_set(&cachep->store_user_clean, 0);
-}
-
-#else
-static inline void set_store_user_dirty(struct kmem_cache *cachep) {}
-
-#endif
-
 /*
  * Do not go above this order unless 0 objects fit into the slab or
  * overridden on the command line.
@@ -990,10 +967,8 @@ static void cpuup_canceled(long cpu)
 
                /* cpu is dead; no one can alloc from it. */
                nc = per_cpu_ptr(cachep->cpu_cache, cpu);
-               if (nc) {
-                       free_block(cachep, nc->entry, nc->avail, node, &list);
-                       nc->avail = 0;
-               }
+               free_block(cachep, nc->entry, nc->avail, node, &list);
+               nc->avail = 0;
 
                if (!cpumask_empty(mask)) {
                        spin_unlock_irq(&n->list_lock);
@@ -1674,8 +1649,8 @@ static void slabs_destroy(struct kmem_cache *cachep, struct list_head *list)
 {
        struct page *page, *n;
 
-       list_for_each_entry_safe(page, n, list, lru) {
-               list_del(&page->lru);
+       list_for_each_entry_safe(page, n, list, slab_list) {
+               list_del(&page->slab_list);
                slab_destroy(cachep, page);
        }
 }
@@ -2231,8 +2206,8 @@ static int drain_freelist(struct kmem_cache *cache,
                        goto out;
                }
 
-               page = list_entry(p, struct page, lru);
-               list_del(&page->lru);
+               page = list_entry(p, struct page, slab_list);
+               list_del(&page->slab_list);
                n->free_slabs--;
                n->total_slabs--;
                /*
@@ -2554,11 +2529,6 @@ static void *slab_get_obj(struct kmem_cache *cachep, struct page *page)
        objp = index_to_obj(cachep, page, get_free_obj(page, page->active));
        page->active++;
 
-#if DEBUG
-       if (cachep->flags & SLAB_STORE_USER)
-               set_store_user_dirty(cachep);
-#endif
-
        return objp;
 }
 
@@ -2691,13 +2661,13 @@ static void cache_grow_end(struct kmem_cache *cachep, struct page *page)
        if (!page)
                return;
 
-       INIT_LIST_HEAD(&page->lru);
+       INIT_LIST_HEAD(&page->slab_list);
        n = get_node(cachep, page_to_nid(page));
 
        spin_lock(&n->list_lock);
        n->total_slabs++;
        if (!page->active) {
-               list_add_tail(&page->lru, &(n->slabs_free));
+               list_add_tail(&page->slab_list, &n->slabs_free);
                n->free_slabs++;
        } else
                fixup_slab_list(cachep, n, page, &list);
@@ -2764,10 +2734,8 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
                *dbg_redzone1(cachep, objp) = RED_INACTIVE;
                *dbg_redzone2(cachep, objp) = RED_INACTIVE;
        }
-       if (cachep->flags & SLAB_STORE_USER) {
-               set_store_user_dirty(cachep);
+       if (cachep->flags & SLAB_STORE_USER)
                *dbg_userword(cachep, objp) = (void *)caller;
-       }
 
        objnr = obj_to_index(cachep, page, objp);
 
@@ -2806,9 +2774,9 @@ static inline void fixup_slab_list(struct kmem_cache *cachep,
                                void **list)
 {
        /* move slabp to correct slabp list: */
-       list_del(&page->lru);
+       list_del(&page->slab_list);
        if (page->active == cachep->num) {
-               list_add(&page->lru, &n->slabs_full);
+               list_add(&page->slab_list, &n->slabs_full);
                if (OBJFREELIST_SLAB(cachep)) {
 #if DEBUG
                        /* Poisoning will be done without holding the lock */
@@ -2822,7 +2790,7 @@ static inline void fixup_slab_list(struct kmem_cache *cachep,
                        page->freelist = NULL;
                }
        } else
-               list_add(&page->lru, &n->slabs_partial);
+               list_add(&page->slab_list, &n->slabs_partial);
 }
 
 /* Try to find non-pfmemalloc slab if needed */
@@ -2845,20 +2813,20 @@ static noinline struct page *get_valid_first_slab(struct kmem_cache_node *n,
        }
 
        /* Move pfmemalloc slab to the end of list to speed up next search */
-       list_del(&page->lru);
+       list_del(&page->slab_list);
        if (!page->active) {
-               list_add_tail(&page->lru, &n->slabs_free);
+               list_add_tail(&page->slab_list, &n->slabs_free);
                n->free_slabs++;
        } else
-               list_add_tail(&page->lru, &n->slabs_partial);
+               list_add_tail(&page->slab_list, &n->slabs_partial);
 
-       list_for_each_entry(page, &n->slabs_partial, lru) {
+       list_for_each_entry(page, &n->slabs_partial, slab_list) {
                if (!PageSlabPfmemalloc(page))
                        return page;
        }
 
        n->free_touched = 1;
-       list_for_each_entry(page, &n->slabs_free, lru) {
+       list_for_each_entry(page, &n->slabs_free, slab_list) {
                if (!PageSlabPfmemalloc(page)) {
                        n->free_slabs--;
                        return page;
@@ -2873,11 +2841,12 @@ static struct page *get_first_slab(struct kmem_cache_node *n, bool pfmemalloc)
        struct page *page;
 
        assert_spin_locked(&n->list_lock);
-       page = list_first_entry_or_null(&n->slabs_partial, struct page, lru);
+       page = list_first_entry_or_null(&n->slabs_partial, struct page,
+                                       slab_list);
        if (!page) {
                n->free_touched = 1;
                page = list_first_entry_or_null(&n->slabs_free, struct page,
-                                               lru);
+                                               slab_list);
                if (page)
                        n->free_slabs--;
        }
@@ -3378,29 +3347,29 @@ static void free_block(struct kmem_cache *cachep, void **objpp,
                objp = objpp[i];
 
                page = virt_to_head_page(objp);
-               list_del(&page->lru);
+               list_del(&page->slab_list);
                check_spinlock_acquired_node(cachep, node);
                slab_put_obj(cachep, page, objp);
                STATS_DEC_ACTIVE(cachep);
 
                /* fixup slab chains */
                if (page->active == 0) {
-                       list_add(&page->lru, &n->slabs_free);
+                       list_add(&page->slab_list, &n->slabs_free);
                        n->free_slabs++;
                } else {
                        /* Unconditionally move a slab to the end of the
                         * partial list on free - maximum time for the
                         * other objects to be freed, too.
                         */
-                       list_add_tail(&page->lru, &n->slabs_partial);
+                       list_add_tail(&page->slab_list, &n->slabs_partial);
                }
        }
 
        while (n->free_objects > n->free_limit && !list_empty(&n->slabs_free)) {
                n->free_objects -= cachep->num;
 
-               page = list_last_entry(&n->slabs_free, struct page, lru);
-               list_move(&page->lru, list);
+               page = list_last_entry(&n->slabs_free, struct page, slab_list);
+               list_move(&page->slab_list, list);
                n->free_slabs--;
                n->total_slabs--;
        }
@@ -3438,7 +3407,7 @@ free_done:
                int i = 0;
                struct page *page;
 
-               list_for_each_entry(page, &n->slabs_free, lru) {
+               list_for_each_entry(page, &n->slabs_free, slab_list) {
                        BUG_ON(page->active);
 
                        i++;
@@ -4185,196 +4154,6 @@ ssize_t slabinfo_write(struct file *file, const char __user *buffer,
        return res;
 }
 
-#ifdef CONFIG_DEBUG_SLAB_LEAK
-
-static inline int add_caller(unsigned long *n, unsigned long v)
-{
-       unsigned long *p;
-       int l;
-       if (!v)
-               return 1;
-       l = n[1];
-       p = n + 2;
-       while (l) {
-               int i = l/2;
-               unsigned long *q = p + 2 * i;
-               if (*q == v) {
-                       q[1]++;
-                       return 1;
-               }
-               if (*q > v) {
-                       l = i;
-               } else {
-                       p = q + 2;
-                       l -= i + 1;
-               }
-       }
-       if (++n[1] == n[0])
-               return 0;
-       memmove(p + 2, p, n[1] * 2 * sizeof(unsigned long) - ((void *)p - (void *)n));
-       p[0] = v;
-       p[1] = 1;
-       return 1;
-}
-
-static void handle_slab(unsigned long *n, struct kmem_cache *c,
-                                               struct page *page)
-{
-       void *p;
-       int i, j;
-       unsigned long v;
-
-       if (n[0] == n[1])
-               return;
-       for (i = 0, p = page->s_mem; i < c->num; i++, p += c->size) {
-               bool active = true;
-
-               for (j = page->active; j < c->num; j++) {
-                       if (get_free_obj(page, j) == i) {
-                               active = false;
-                               break;
-                       }
-               }
-
-               if (!active)
-                       continue;
-
-               /*
-                * probe_kernel_read() is used for DEBUG_PAGEALLOC. page table
-                * mapping is established when actual object allocation and
-                * we could mistakenly access the unmapped object in the cpu
-                * cache.
-                */
-               if (probe_kernel_read(&v, dbg_userword(c, p), sizeof(v)))
-                       continue;
-
-               if (!add_caller(n, v))
-                       return;
-       }
-}
-
-static void show_symbol(struct seq_file *m, unsigned long address)
-{
-#ifdef CONFIG_KALLSYMS
-       unsigned long offset, size;
-       char modname[MODULE_NAME_LEN], name[KSYM_NAME_LEN];
-
-       if (lookup_symbol_attrs(address, &size, &offset, modname, name) == 0) {
-               seq_printf(m, "%s+%#lx/%#lx", name, offset, size);
-               if (modname[0])
-                       seq_printf(m, " [%s]", modname);
-               return;
-       }
-#endif
-       seq_printf(m, "%px", (void *)address);
-}
-
-static int leaks_show(struct seq_file *m, void *p)
-{
-       struct kmem_cache *cachep = list_entry(p, struct kmem_cache,
-                                              root_caches_node);
-       struct page *page;
-       struct kmem_cache_node *n;
-       const char *name;
-       unsigned long *x = m->private;
-       int node;
-       int i;
-
-       if (!(cachep->flags & SLAB_STORE_USER))
-               return 0;
-       if (!(cachep->flags & SLAB_RED_ZONE))
-               return 0;
-
-       /*
-        * Set store_user_clean and start to grab stored user information
-        * for all objects on this cache. If some alloc/free requests comes
-        * during the processing, information would be wrong so restart
-        * whole processing.
-        */
-       do {
-               set_store_user_clean(cachep);
-               drain_cpu_caches(cachep);
-
-               x[1] = 0;
-
-               for_each_kmem_cache_node(cachep, node, n) {
-
-                       check_irq_on();
-                       spin_lock_irq(&n->list_lock);
-
-                       list_for_each_entry(page, &n->slabs_full, lru)
-                               handle_slab(x, cachep, page);
-                       list_for_each_entry(page, &n->slabs_partial, lru)
-                               handle_slab(x, cachep, page);
-                       spin_unlock_irq(&n->list_lock);
-               }
-       } while (!is_store_user_clean(cachep));
-
-       name = cachep->name;
-       if (x[0] == x[1]) {
-               /* Increase the buffer size */
-               mutex_unlock(&slab_mutex);
-               m->private = kcalloc(x[0] * 4, sizeof(unsigned long),
-                                    GFP_KERNEL);
-               if (!m->private) {
-                       /* Too bad, we are really out */
-                       m->private = x;
-                       mutex_lock(&slab_mutex);
-                       return -ENOMEM;
-               }
-               *(unsigned long *)m->private = x[0] * 2;
-               kfree(x);
-               mutex_lock(&slab_mutex);
-               /* Now make sure this entry will be retried */
-               m->count = m->size;
-               return 0;
-       }
-       for (i = 0; i < x[1]; i++) {
-               seq_printf(m, "%s: %lu ", name, x[2*i+3]);
-               show_symbol(m, x[2*i+2]);
-               seq_putc(m, '\n');
-       }
-
-       return 0;
-}
-
-static const struct seq_operations slabstats_op = {
-       .start = slab_start,
-       .next = slab_next,
-       .stop = slab_stop,
-       .show = leaks_show,
-};
-
-static int slabstats_open(struct inode *inode, struct file *file)
-{
-       unsigned long *n;
-
-       n = __seq_open_private(file, &slabstats_op, PAGE_SIZE);
-       if (!n)
-               return -ENOMEM;
-
-       *n = PAGE_SIZE / (2 * sizeof(unsigned long));
-
-       return 0;
-}
-
-static const struct file_operations proc_slabstats_operations = {
-       .open           = slabstats_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release_private,
-};
-#endif
-
-static int __init slab_proc_init(void)
-{
-#ifdef CONFIG_DEBUG_SLAB_LEAK
-       proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations);
-#endif
-       return 0;
-}
-module_init(slab_proc_init);
-
 #ifdef CONFIG_HARDENED_USERCOPY
 /*
  * Rejects incorrectly sized objects and objects that are to be copied
index 307c2c9..84aefd9 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -112,13 +112,13 @@ static inline int slob_page_free(struct page *sp)
 
 static void set_slob_page_free(struct page *sp, struct list_head *list)
 {
-       list_add(&sp->lru, list);
+       list_add(&sp->slab_list, list);
        __SetPageSlobFree(sp);
 }
 
 static inline void clear_slob_page_free(struct page *sp)
 {
-       list_del(&sp->lru);
+       list_del(&sp->slab_list);
        __ClearPageSlobFree(sp);
 }
 
@@ -213,13 +213,26 @@ static void slob_free_pages(void *b, int order)
 }
 
 /*
- * Allocate a slob block within a given slob_page sp.
+ * slob_page_alloc() - Allocate a slob block within a given slob_page sp.
+ * @sp: Page to look in.
+ * @size: Size of the allocation.
+ * @align: Allocation alignment.
+ * @page_removed_from_list: Return parameter.
+ *
+ * Tries to find a chunk of memory at least @size bytes big within @page.
+ *
+ * Return: Pointer to memory if allocated, %NULL otherwise.  If the
+ *         allocation fills up @page then the page is removed from the
+ *         freelist, in this case @page_removed_from_list will be set to
+ *         true (set to false otherwise).
  */
-static void *slob_page_alloc(struct page *sp, size_t size, int align)
+static void *slob_page_alloc(struct page *sp, size_t size, int align,
+                            bool *page_removed_from_list)
 {
        slob_t *prev, *cur, *aligned = NULL;
        int delta = 0, units = SLOB_UNITS(size);
 
+       *page_removed_from_list = false;
        for (prev = NULL, cur = sp->freelist; ; prev = cur, cur = slob_next(cur)) {
                slobidx_t avail = slob_units(cur);
 
@@ -254,8 +267,10 @@ static void *slob_page_alloc(struct page *sp, size_t size, int align)
                        }
 
                        sp->units -= units;
-                       if (!sp->units)
+                       if (!sp->units) {
                                clear_slob_page_free(sp);
+                               *page_removed_from_list = true;
+                       }
                        return cur;
                }
                if (slob_last(cur))
@@ -269,10 +284,10 @@ static void *slob_page_alloc(struct page *sp, size_t size, int align)
 static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
 {
        struct page *sp;
-       struct list_head *prev;
        struct list_head *slob_list;
        slob_t *b = NULL;
        unsigned long flags;
+       bool _unused;
 
        if (size < SLOB_BREAK1)
                slob_list = &free_slob_small;
@@ -283,7 +298,8 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
 
        spin_lock_irqsave(&slob_lock, flags);
        /* Iterate through each partially free page, try to find room */
-       list_for_each_entry(sp, slob_list, lru) {
+       list_for_each_entry(sp, slob_list, slab_list) {
+               bool page_removed_from_list = false;
 #ifdef CONFIG_NUMA
                /*
                 * If there's a node specification, search for a partial
@@ -296,18 +312,25 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
                if (sp->units < SLOB_UNITS(size))
                        continue;
 
-               /* Attempt to alloc */
-               prev = sp->lru.prev;
-               b = slob_page_alloc(sp, size, align);
+               b = slob_page_alloc(sp, size, align, &page_removed_from_list);
                if (!b)
                        continue;
 
-               /* Improve fragment distribution and reduce our average
-                * search time by starting our next search here. (see
-                * Knuth vol 1, sec 2.5, pg 449) */
-               if (prev != slob_list->prev &&
-                               slob_list->next != prev->next)
-                       list_move_tail(slob_list, prev->next);
+               /*
+                * If slob_page_alloc() removed sp from the list then we
+                * cannot call list functions on sp.  If so allocation
+                * did not fragment the page anyway so optimisation is
+                * unnecessary.
+                */
+               if (!page_removed_from_list) {
+                       /*
+                        * Improve fragment distribution and reduce our average
+                        * search time by starting our next search here. (see
+                        * Knuth vol 1, sec 2.5, pg 449)
+                        */
+                       if (!list_is_first(&sp->slab_list, slob_list))
+                               list_rotate_to_front(&sp->slab_list, slob_list);
+               }
                break;
        }
        spin_unlock_irqrestore(&slob_lock, flags);
@@ -323,10 +346,10 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
                spin_lock_irqsave(&slob_lock, flags);
                sp->units = SLOB_UNITS(PAGE_SIZE);
                sp->freelist = b;
-               INIT_LIST_HEAD(&sp->lru);
+               INIT_LIST_HEAD(&sp->slab_list);
                set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE));
                set_slob_page_free(sp, slob_list);
-               b = slob_page_alloc(sp, size, align);
+               b = slob_page_alloc(sp, size, align, &_unused);
                BUG_ON(!b);
                spin_unlock_irqrestore(&slob_lock, flags);
        }
index 6b28cd2..cd04dbd 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
  *     D. page->frozen         -> frozen state
  *
  *   If a slab is frozen then it is exempt from list management. It is not
- *   on any list. The processor that froze the slab is the one who can
- *   perform list operations on the page. Other processors may put objects
- *   onto the freelist but the processor that froze the slab is the only
- *   one that can retrieve the objects from the page's freelist.
+ *   on any list except per cpu partial list. The processor that froze the
+ *   slab is the one who can perform list operations on the page. Other
+ *   processors may put objects onto the freelist but the processor that
+ *   froze the slab is the only one that can retrieve the objects from the
+ *   page's freelist.
  *
  *   The list_lock protects the partial and full list on each node and
  *   the partial slab counter. If taken then no new slabs may be added or
@@ -1014,7 +1015,7 @@ static void add_full(struct kmem_cache *s,
                return;
 
        lockdep_assert_held(&n->list_lock);
-       list_add(&page->lru, &n->full);
+       list_add(&page->slab_list, &n->full);
 }
 
 static void remove_full(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page)
@@ -1023,7 +1024,7 @@ static void remove_full(struct kmem_cache *s, struct kmem_cache_node *n, struct
                return;
 
        lockdep_assert_held(&n->list_lock);
-       list_del(&page->lru);
+       list_del(&page->slab_list);
 }
 
 /* Tracking of the number of slabs for debugging purposes */
@@ -1764,9 +1765,9 @@ __add_partial(struct kmem_cache_node *n, struct page *page, int tail)
 {
        n->nr_partial++;
        if (tail == DEACTIVATE_TO_TAIL)
-               list_add_tail(&page->lru, &n->partial);
+               list_add_tail(&page->slab_list, &n->partial);
        else
-               list_add(&page->lru, &n->partial);
+               list_add(&page->slab_list, &n->partial);
 }
 
 static inline void add_partial(struct kmem_cache_node *n,
@@ -1780,7 +1781,7 @@ static inline void remove_partial(struct kmem_cache_node *n,
                                        struct page *page)
 {
        lockdep_assert_held(&n->list_lock);
-       list_del(&page->lru);
+       list_del(&page->slab_list);
        n->nr_partial--;
 }
 
@@ -1854,7 +1855,7 @@ static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n,
                return NULL;
 
        spin_lock(&n->list_lock);
-       list_for_each_entry_safe(page, page2, &n->partial, lru) {
+       list_for_each_entry_safe(page, page2, &n->partial, slab_list) {
                void *t;
 
                if (!pfmemalloc_match(page, flags))
@@ -1942,7 +1943,7 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags,
                        }
                }
        } while (read_mems_allowed_retry(cpuset_mems_cookie));
-#endif
+#endif /* CONFIG_NUMA */
        return NULL;
 }
 
@@ -2240,7 +2241,7 @@ static void unfreeze_partials(struct kmem_cache *s,
                discard_slab(s, page);
                stat(s, FREE_SLAB);
        }
-#endif
+#endif /* CONFIG_SLUB_CPU_PARTIAL */
 }
 
 /*
@@ -2299,7 +2300,7 @@ static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
                local_irq_restore(flags);
        }
        preempt_enable();
-#endif
+#endif /* CONFIG_SLUB_CPU_PARTIAL */
 }
 
 static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
@@ -2398,7 +2399,7 @@ static unsigned long count_partial(struct kmem_cache_node *n,
        struct page *page;
 
        spin_lock_irqsave(&n->list_lock, flags);
-       list_for_each_entry(page, &n->partial, lru)
+       list_for_each_entry(page, &n->partial, slab_list)
                x += get_count(page);
        spin_unlock_irqrestore(&n->list_lock, flags);
        return x;
@@ -2804,7 +2805,7 @@ void *kmem_cache_alloc_node_trace(struct kmem_cache *s,
 }
 EXPORT_SYMBOL(kmem_cache_alloc_node_trace);
 #endif
-#endif
+#endif /* CONFIG_NUMA */
 
 /*
  * Slow path handling. This may still be called frequently since objects
@@ -2903,8 +2904,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
         * then add it.
         */
        if (!kmem_cache_has_cpu_partial(s) && unlikely(!prior)) {
-               if (kmem_cache_debug(s))
-                       remove_full(s, n, page);
+               remove_full(s, n, page);
                add_partial(n, page, DEACTIVATE_TO_TAIL);
                stat(s, FREE_ADD_PARTIAL);
        }
@@ -3696,10 +3696,10 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
 
        BUG_ON(irqs_disabled());
        spin_lock_irq(&n->list_lock);
-       list_for_each_entry_safe(page, h, &n->partial, lru) {
+       list_for_each_entry_safe(page, h, &n->partial, slab_list) {
                if (!page->inuse) {
                        remove_partial(n, page);
-                       list_add(&page->lru, &discard);
+                       list_add(&page->slab_list, &discard);
                } else {
                        list_slab_objects(s, page,
                        "Objects remaining in %s on __kmem_cache_shutdown()");
@@ -3707,7 +3707,7 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
        }
        spin_unlock_irq(&n->list_lock);
 
-       list_for_each_entry_safe(page, h, &discard, lru)
+       list_for_each_entry_safe(page, h, &discard, slab_list)
                discard_slab(s, page);
 }
 
@@ -3839,7 +3839,7 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node)
        return ret;
 }
 EXPORT_SYMBOL(__kmalloc_node);
-#endif
+#endif /* CONFIG_NUMA */
 
 #ifdef CONFIG_HARDENED_USERCOPY
 /*
@@ -3987,7 +3987,7 @@ int __kmem_cache_shrink(struct kmem_cache *s)
                 * Note that concurrent frees may occur while we hold the
                 * list_lock. page->inuse here is the upper limit.
                 */
-               list_for_each_entry_safe(page, t, &n->partial, lru) {
+               list_for_each_entry_safe(page, t, &n->partial, slab_list) {
                        int free = page->objects - page->inuse;
 
                        /* Do not reread page->inuse */
@@ -3997,10 +3997,10 @@ int __kmem_cache_shrink(struct kmem_cache *s)
                        BUG_ON(free <= 0);
 
                        if (free == page->objects) {
-                               list_move(&page->lru, &discard);
+                               list_move(&page->slab_list, &discard);
                                n->nr_partial--;
                        } else if (free <= SHRINK_PROMOTE_MAX)
-                               list_move(&page->lru, promote + free - 1);
+                               list_move(&page->slab_list, promote + free - 1);
                }
 
                /*
@@ -4013,7 +4013,7 @@ int __kmem_cache_shrink(struct kmem_cache *s)
                spin_unlock_irqrestore(&n->list_lock, flags);
 
                /* Release empty slabs */
-               list_for_each_entry_safe(page, t, &discard, lru)
+               list_for_each_entry_safe(page, t, &discard, slab_list)
                        discard_slab(s, page);
 
                if (slabs_node(s, node))
@@ -4057,7 +4057,7 @@ void __kmemcg_cache_deactivate(struct kmem_cache *s)
         */
        slab_deactivate_memcg_cache_rcu_sched(s, kmemcg_cache_deact_after_rcu);
 }
-#endif
+#endif /* CONFIG_MEMCG */
 
 static int slab_mem_going_offline_callback(void *arg)
 {
@@ -4205,11 +4205,11 @@ static struct kmem_cache * __init bootstrap(struct kmem_cache *static_cache)
        for_each_kmem_cache_node(s, node, n) {
                struct page *p;
 
-               list_for_each_entry(p, &n->partial, lru)
+               list_for_each_entry(p, &n->partial, slab_list)
                        p->slab_cache = s;
 
 #ifdef CONFIG_SLUB_DEBUG
-               list_for_each_entry(p, &n->full, lru)
+               list_for_each_entry(p, &n->full, slab_list)
                        p->slab_cache = s;
 #endif
        }
@@ -4426,7 +4426,7 @@ static int validate_slab_node(struct kmem_cache *s,
 
        spin_lock_irqsave(&n->list_lock, flags);
 
-       list_for_each_entry(page, &n->partial, lru) {
+       list_for_each_entry(page, &n->partial, slab_list) {
                validate_slab_slab(s, page, map);
                count++;
        }
@@ -4437,7 +4437,7 @@ static int validate_slab_node(struct kmem_cache *s,
        if (!(s->flags & SLAB_STORE_USER))
                goto out;
 
-       list_for_each_entry(page, &n->full, lru) {
+       list_for_each_entry(page, &n->full, slab_list) {
                validate_slab_slab(s, page, map);
                count++;
        }
@@ -4633,9 +4633,9 @@ static int list_locations(struct kmem_cache *s, char *buf,
                        continue;
 
                spin_lock_irqsave(&n->list_lock, flags);
-               list_for_each_entry(page, &n->partial, lru)
+               list_for_each_entry(page, &n->partial, slab_list)
                        process_slab(&t, s, page, alloc, map);
-               list_for_each_entry(page, &n->full, lru)
+               list_for_each_entry(page, &n->full, slab_list)
                        process_slab(&t, s, page, alloc, map);
                spin_unlock_irqrestore(&n->list_lock, flags);
        }
@@ -4690,7 +4690,7 @@ static int list_locations(struct kmem_cache *s, char *buf,
                len += sprintf(buf, "No data\n");
        return len;
 }
-#endif
+#endif /* CONFIG_SLUB_DEBUG */
 
 #ifdef SLUB_RESILIENCY_TEST
 static void __init resiliency_test(void)
@@ -4750,7 +4750,7 @@ static void __init resiliency_test(void)
 #ifdef CONFIG_SYSFS
 static void resiliency_test(void) {};
 #endif
-#endif
+#endif /* SLUB_RESILIENCY_TEST */
 
 #ifdef CONFIG_SYSFS
 enum slab_stat_type {
@@ -5407,7 +5407,7 @@ STAT_ATTR(CPU_PARTIAL_ALLOC, cpu_partial_alloc);
 STAT_ATTR(CPU_PARTIAL_FREE, cpu_partial_free);
 STAT_ATTR(CPU_PARTIAL_NODE, cpu_partial_node);
 STAT_ATTR(CPU_PARTIAL_DRAIN, cpu_partial_drain);
-#endif
+#endif /* CONFIG_SLUB_STATS */
 
 static struct attribute *slab_attrs[] = {
        &slab_size_attr.attr,
@@ -5608,7 +5608,7 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s)
 
        if (buffer)
                free_page((unsigned long)buffer);
-#endif
+#endif /* CONFIG_MEMCG */
 }
 
 static void kmem_cache_release(struct kobject *k)
index 56e057c..fd13166 100644 (file)
@@ -684,10 +684,18 @@ static void free_map_bootmem(struct page *memmap)
 #endif /* CONFIG_MEMORY_HOTREMOVE */
 #endif /* CONFIG_SPARSEMEM_VMEMMAP */
 
-/*
- * returns the number of sections whose mem_maps were properly
- * set.  If this is <=0, then that means that the passed-in
- * map was not consumed and must be freed.
+/**
+ * sparse_add_one_section - add a memory section
+ * @nid: The node to add section on
+ * @start_pfn: start pfn of the memory range
+ * @altmap: device page map
+ *
+ * This is only intended for hotplug.
+ *
+ * Return:
+ * * 0         - On success.
+ * * -EEXIST   - Section has been present.
+ * * -ENOMEM   - Out of memory.
  */
 int __meminit sparse_add_one_section(int nid, unsigned long start_pfn,
                                     struct vmem_altmap *altmap)
index 301ed4e..3a75722 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -867,7 +867,7 @@ static void __pagevec_lru_add_fn(struct page *page, struct lruvec *lruvec,
        SetPageLRU(page);
        /*
         * Page becomes evictable in two ways:
-        * 1) Within LRU lock [munlock_vma_pages() and __munlock_pagevec()].
+        * 1) Within LRU lock [munlock_vma_page() and __munlock_pagevec()].
         * 2) Before acquiring LRU lock to put the page to correct LRU and then
         *   a) do PageLRU check with lock [check_move_unevictable_pages]
         *   b) do PageLRU check before lock [clear_page_mlock]
index 85245fd..eb71416 100644 (file)
@@ -132,7 +132,7 @@ int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t gfp)
                for (i = 0; i < nr; i++) {
                        VM_BUG_ON_PAGE(xas.xa_index != idx + i, page);
                        set_page_private(page + i, entry.val + i);
-                       xas_store(&xas, page + i);
+                       xas_store(&xas, page);
                        xas_next(&xas);
                }
                address_space->nrpages += nr;
@@ -167,7 +167,7 @@ void __delete_from_swap_cache(struct page *page, swp_entry_t entry)
 
        for (i = 0; i < nr; i++) {
                void *entry = xas_store(&xas, NULL);
-               VM_BUG_ON_PAGE(entry != page + i, entry);
+               VM_BUG_ON_PAGE(entry != page, entry);
                set_page_private(page + i, 0);
                xas_next(&xas);
        }
index d59b5a7..9932d57 100644 (file)
@@ -271,8 +271,7 @@ retry:
                 */
                idx = linear_page_index(dst_vma, dst_addr);
                mapping = dst_vma->vm_file->f_mapping;
-               hash = hugetlb_fault_mutex_hash(h, dst_mm, dst_vma, mapping,
-                                                               idx, dst_addr);
+               hash = hugetlb_fault_mutex_hash(h, mapping, idx, dst_addr);
                mutex_lock(&hugetlb_fault_mutex_table[hash]);
 
                err = -ENOMEM;
index 43a2984..e2e4f8c 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -318,7 +318,7 @@ EXPORT_SYMBOL_GPL(__get_user_pages_fast);
  * get_user_pages_fast() - pin user pages in memory
  * @start:     starting user address
  * @nr_pages:  number of pages from start to pin
- * @write:     whether pages will be written to
+ * @gup_flags: flags modifying pin behaviour
  * @pages:     array that receives pointers to the pages pinned.
  *             Should be at least nr_pages long.
  *
@@ -339,10 +339,10 @@ EXPORT_SYMBOL_GPL(__get_user_pages_fast);
  * were pinned, returns -errno.
  */
 int __weak get_user_pages_fast(unsigned long start,
-                               int nr_pages, int write, struct page **pages)
+                               int nr_pages, unsigned int gup_flags,
+                               struct page **pages)
 {
-       return get_user_pages_unlocked(start, nr_pages, pages,
-                                      write ? FOLL_WRITE : 0);
+       return get_user_pages_unlocked(start, nr_pages, pages, gup_flags);
 }
 EXPORT_SYMBOL_GPL(get_user_pages_fast);
 
@@ -652,7 +652,7 @@ EXPORT_SYMBOL_GPL(vm_memory_committed);
  */
 int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
 {
-       long free, allowed, reserve;
+       long allowed;
 
        VM_WARN_ONCE(percpu_counter_read(&vm_committed_as) <
                        -(s64)vm_committed_as_batch * num_online_cpus(),
@@ -667,51 +667,9 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
                return 0;
 
        if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
-               free = global_zone_page_state(NR_FREE_PAGES);
-               free += global_node_page_state(NR_FILE_PAGES);
-
-               /*
-                * shmem pages shouldn't be counted as free in this
-                * case, they can't be purged, only swapped out, and
-                * that won't affect the overall amount of available
-                * memory in the system.
-                */
-               free -= global_node_page_state(NR_SHMEM);
-
-               free += get_nr_swap_pages();
-
-               /*
-                * Any slabs which are created with the
-                * SLAB_RECLAIM_ACCOUNT flag claim to have contents
-                * which are reclaimable, under pressure.  The dentry
-                * cache and most inode caches should fall into this
-                */
-               free += global_node_page_state(NR_SLAB_RECLAIMABLE);
-
-               /*
-                * Part of the kernel memory, which can be released
-                * under memory pressure.
-                */
-               free += global_node_page_state(NR_KERNEL_MISC_RECLAIMABLE);
-
-               /*
-                * Leave reserved pages. The pages are not for anonymous pages.
-                */
-               if (free <= totalreserve_pages)
+               if (pages > totalram_pages() + total_swap_pages)
                        goto error;
-               else
-                       free -= totalreserve_pages;
-
-               /*
-                * Reserve some for root
-                */
-               if (!cap_sys_admin)
-                       free -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10);
-
-               if (free > pages)
-                       return 0;
-
-               goto error;
+               return 0;
        }
 
        allowed = vm_commit_limit();
@@ -725,7 +683,8 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
         * Don't let a single process grow so big a user can't recover
         */
        if (mm) {
-               reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10);
+               long reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10);
+
                allowed -= min_t(long, mm->total_vm / 32, reserve);
        }
 
index e5e9e1f..67bbb8d 100644 (file)
@@ -633,7 +633,7 @@ static unsigned long lazy_max_pages(void)
        return log * (32UL * 1024 * 1024 / PAGE_SIZE);
 }
 
-static atomic_t vmap_lazy_nr = ATOMIC_INIT(0);
+static atomic_long_t vmap_lazy_nr = ATOMIC_LONG_INIT(0);
 
 /*
  * Serialize vmap purging.  There is no actual criticial section protected
@@ -651,7 +651,7 @@ static void purge_fragmented_blocks_allcpus(void);
  */
 void set_iounmap_nonlazy(void)
 {
-       atomic_set(&vmap_lazy_nr, lazy_max_pages()+1);
+       atomic_long_set(&vmap_lazy_nr, lazy_max_pages()+1);
 }
 
 /*
@@ -659,34 +659,40 @@ void set_iounmap_nonlazy(void)
  */
 static bool __purge_vmap_area_lazy(unsigned long start, unsigned long end)
 {
+       unsigned long resched_threshold;
        struct llist_node *valist;
        struct vmap_area *va;
        struct vmap_area *n_va;
-       bool do_free = false;
 
        lockdep_assert_held(&vmap_purge_lock);
 
        valist = llist_del_all(&vmap_purge_list);
+       if (unlikely(valist == NULL))
+               return false;
+
+       /*
+        * TODO: to calculate a flush range without looping.
+        * The list can be up to lazy_max_pages() elements.
+        */
        llist_for_each_entry(va, valist, purge_list) {
                if (va->va_start < start)
                        start = va->va_start;
                if (va->va_end > end)
                        end = va->va_end;
-               do_free = true;
        }
 
-       if (!do_free)
-               return false;
-
        flush_tlb_kernel_range(start, end);
+       resched_threshold = lazy_max_pages() << 1;
 
        spin_lock(&vmap_area_lock);
        llist_for_each_entry_safe(va, n_va, valist, purge_list) {
-               int nr = (va->va_end - va->va_start) >> PAGE_SHIFT;
+               unsigned long nr = (va->va_end - va->va_start) >> PAGE_SHIFT;
 
                __free_vmap_area(va);
-               atomic_sub(nr, &vmap_lazy_nr);
-               cond_resched_lock(&vmap_area_lock);
+               atomic_long_sub(nr, &vmap_lazy_nr);
+
+               if (atomic_long_read(&vmap_lazy_nr) < resched_threshold)
+                       cond_resched_lock(&vmap_area_lock);
        }
        spin_unlock(&vmap_area_lock);
        return true;
@@ -722,10 +728,10 @@ static void purge_vmap_area_lazy(void)
  */
 static void free_vmap_area_noflush(struct vmap_area *va)
 {
-       int nr_lazy;
+       unsigned long nr_lazy;
 
-       nr_lazy = atomic_add_return((va->va_end - va->va_start) >> PAGE_SHIFT,
-                                   &vmap_lazy_nr);
+       nr_lazy = atomic_long_add_return((va->va_end - va->va_start) >>
+                               PAGE_SHIFT, &vmap_lazy_nr);
 
        /* After this point, we may free va at any time */
        llist_add(&va->purge_list, &vmap_purge_list);
index fd9de50..7acd0af 100644 (file)
@@ -346,7 +346,7 @@ unsigned long lruvec_lru_size(struct lruvec *lruvec, enum lru_list lru, int zone
        int zid;
 
        if (!mem_cgroup_disabled())
-               lru_size = mem_cgroup_get_lru_size(lruvec, lru);
+               lru_size = lruvec_page_state_local(lruvec, NR_LRU_BASE + lru);
        else
                lru_size = node_page_state(lruvec_pgdat(lruvec), NR_LRU_BASE + lru);
 
@@ -1107,6 +1107,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,
        LIST_HEAD(ret_pages);
        LIST_HEAD(free_pages);
        unsigned nr_reclaimed = 0;
+       unsigned pgactivate = 0;
 
        memset(stat, 0, sizeof(*stat));
        cond_resched();
@@ -1466,8 +1467,10 @@ activate_locked:
                        try_to_free_swap(page);
                VM_BUG_ON_PAGE(PageActive(page), page);
                if (!PageMlocked(page)) {
+                       int type = page_is_file_cache(page);
                        SetPageActive(page);
-                       stat->nr_activate++;
+                       pgactivate++;
+                       stat->nr_activate[type] += hpage_nr_pages(page);
                        count_memcg_page_event(page, PGACTIVATE);
                }
 keep_locked:
@@ -1482,7 +1485,7 @@ keep:
        free_unref_page_list(&free_pages);
 
        list_splice(&ret_pages, page_list);
-       count_vm_events(PGACTIVATE, stat->nr_activate);
+       count_vm_events(PGACTIVATE, pgactivate);
 
        return nr_reclaimed;
 }
@@ -1804,40 +1807,54 @@ static int too_many_isolated(struct pglist_data *pgdat, int file,
        return isolated > inactive;
 }
 
-static noinline_for_stack void
-putback_inactive_pages(struct lruvec *lruvec, struct list_head *page_list)
+/*
+ * This moves pages from @list to corresponding LRU list.
+ *
+ * We move them the other way if the page is referenced by one or more
+ * processes, from rmap.
+ *
+ * If the pages are mostly unmapped, the processing is fast and it is
+ * appropriate to hold zone_lru_lock across the whole operation.  But if
+ * the pages are mapped, the processing is slow (page_referenced()) so we
+ * should drop zone_lru_lock around each page.  It's impossible to balance
+ * this, so instead we remove the pages from the LRU while processing them.
+ * It is safe to rely on PG_active against the non-LRU pages in here because
+ * nobody will play with that bit on a non-LRU page.
+ *
+ * The downside is that we have to touch page->_refcount against each page.
+ * But we had to alter page->flags anyway.
+ *
+ * Returns the number of pages moved to the given lruvec.
+ */
+
+static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec,
+                                                    struct list_head *list)
 {
-       struct zone_reclaim_stat *reclaim_stat = &lruvec->reclaim_stat;
        struct pglist_data *pgdat = lruvec_pgdat(lruvec);
+       int nr_pages, nr_moved = 0;
        LIST_HEAD(pages_to_free);
+       struct page *page;
+       enum lru_list lru;
 
-       /*
-        * Put back any unfreeable pages.
-        */
-       while (!list_empty(page_list)) {
-               struct page *page = lru_to_page(page_list);
-               int lru;
-
+       while (!list_empty(list)) {
+               page = lru_to_page(list);
                VM_BUG_ON_PAGE(PageLRU(page), page);
-               list_del(&page->lru);
                if (unlikely(!page_evictable(page))) {
+                       list_del(&page->lru);
                        spin_unlock_irq(&pgdat->lru_lock);
                        putback_lru_page(page);
                        spin_lock_irq(&pgdat->lru_lock);
                        continue;
                }
-
                lruvec = mem_cgroup_page_lruvec(page, pgdat);
 
                SetPageLRU(page);
                lru = page_lru(page);
-               add_page_to_lru_list(page, lruvec, lru);
 
-               if (is_active_lru(lru)) {
-                       int file = is_file_lru(lru);
-                       int numpages = hpage_nr_pages(page);
-                       reclaim_stat->recent_rotated[file] += numpages;
-               }
+               nr_pages = hpage_nr_pages(page);
+               update_lru_size(lruvec, lru, page_zonenum(page), nr_pages);
+               list_move(&page->lru, &lruvec->lists[lru]);
+
                if (put_page_testzero(page)) {
                        __ClearPageLRU(page);
                        __ClearPageActive(page);
@@ -1850,13 +1867,17 @@ putback_inactive_pages(struct lruvec *lruvec, struct list_head *page_list)
                                spin_lock_irq(&pgdat->lru_lock);
                        } else
                                list_add(&page->lru, &pages_to_free);
+               } else {
+                       nr_moved += nr_pages;
                }
        }
 
        /*
         * To save our caller's stack, now use input list for pages to free.
         */
-       list_splice(&pages_to_free, page_list);
+       list_splice(&pages_to_free, list);
+
+       return nr_moved;
 }
 
 /*
@@ -1886,6 +1907,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec,
        unsigned long nr_taken;
        struct reclaim_stat stat;
        int file = is_file_lru(lru);
+       enum vm_event_item item;
        struct pglist_data *pgdat = lruvec_pgdat(lruvec);
        struct zone_reclaim_stat *reclaim_stat = &lruvec->reclaim_stat;
        bool stalled = false;
@@ -1913,17 +1935,10 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec,
        __mod_node_page_state(pgdat, NR_ISOLATED_ANON + file, nr_taken);
        reclaim_stat->recent_scanned[file] += nr_taken;
 
-       if (current_is_kswapd()) {
-               if (global_reclaim(sc))
-                       __count_vm_events(PGSCAN_KSWAPD, nr_scanned);
-               count_memcg_events(lruvec_memcg(lruvec), PGSCAN_KSWAPD,
-                                  nr_scanned);
-       } else {
-               if (global_reclaim(sc))
-                       __count_vm_events(PGSCAN_DIRECT, nr_scanned);
-               count_memcg_events(lruvec_memcg(lruvec), PGSCAN_DIRECT,
-                                  nr_scanned);
-       }
+       item = current_is_kswapd() ? PGSCAN_KSWAPD : PGSCAN_DIRECT;
+       if (global_reclaim(sc))
+               __count_vm_events(item, nr_scanned);
+       __count_memcg_events(lruvec_memcg(lruvec), item, nr_scanned);
        spin_unlock_irq(&pgdat->lru_lock);
 
        if (nr_taken == 0)
@@ -1934,19 +1949,14 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec,
 
        spin_lock_irq(&pgdat->lru_lock);
 
-       if (current_is_kswapd()) {
-               if (global_reclaim(sc))
-                       __count_vm_events(PGSTEAL_KSWAPD, nr_reclaimed);
-               count_memcg_events(lruvec_memcg(lruvec), PGSTEAL_KSWAPD,
-                                  nr_reclaimed);
-       } else {
-               if (global_reclaim(sc))
-                       __count_vm_events(PGSTEAL_DIRECT, nr_reclaimed);
-               count_memcg_events(lruvec_memcg(lruvec), PGSTEAL_DIRECT,
-                                  nr_reclaimed);
-       }
+       item = current_is_kswapd() ? PGSTEAL_KSWAPD : PGSTEAL_DIRECT;
+       if (global_reclaim(sc))
+               __count_vm_events(item, nr_reclaimed);
+       __count_memcg_events(lruvec_memcg(lruvec), item, nr_reclaimed);
+       reclaim_stat->recent_rotated[0] = stat.nr_activate[0];
+       reclaim_stat->recent_rotated[1] = stat.nr_activate[1];
 
-       putback_inactive_pages(lruvec, &page_list);
+       move_pages_to_lru(lruvec, &page_list);
 
        __mod_node_page_state(pgdat, NR_ISOLATED_ANON + file, -nr_taken);
 
@@ -1983,73 +1993,6 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec,
        return nr_reclaimed;
 }
 
-/*
- * This moves pages from the active list to the inactive list.
- *
- * We move them the other way if the page is referenced by one or more
- * processes, from rmap.
- *
- * If the pages are mostly unmapped, the processing is fast and it is
- * appropriate to hold pgdat->lru_lock across the whole operation.  But if
- * the pages are mapped, the processing is slow (page_referenced()) so we
- * should drop pgdat->lru_lock around each page.  It's impossible to balance
- * this, so instead we remove the pages from the LRU while processing them.
- * It is safe to rely on PG_active against the non-LRU pages in here because
- * nobody will play with that bit on a non-LRU page.
- *
- * The downside is that we have to touch page->_refcount against each page.
- * But we had to alter page->flags anyway.
- *
- * Returns the number of pages moved to the given lru.
- */
-
-static unsigned move_active_pages_to_lru(struct lruvec *lruvec,
-                                    struct list_head *list,
-                                    struct list_head *pages_to_free,
-                                    enum lru_list lru)
-{
-       struct pglist_data *pgdat = lruvec_pgdat(lruvec);
-       struct page *page;
-       int nr_pages;
-       int nr_moved = 0;
-
-       while (!list_empty(list)) {
-               page = lru_to_page(list);
-               lruvec = mem_cgroup_page_lruvec(page, pgdat);
-
-               VM_BUG_ON_PAGE(PageLRU(page), page);
-               SetPageLRU(page);
-
-               nr_pages = hpage_nr_pages(page);
-               update_lru_size(lruvec, lru, page_zonenum(page), nr_pages);
-               list_move(&page->lru, &lruvec->lists[lru]);
-
-               if (put_page_testzero(page)) {
-                       __ClearPageLRU(page);
-                       __ClearPageActive(page);
-                       del_page_from_lru_list(page, lruvec, lru);
-
-                       if (unlikely(PageCompound(page))) {
-                               spin_unlock_irq(&pgdat->lru_lock);
-                               mem_cgroup_uncharge(page);
-                               (*get_compound_page_dtor(page))(page);
-                               spin_lock_irq(&pgdat->lru_lock);
-                       } else
-                               list_add(&page->lru, pages_to_free);
-               } else {
-                       nr_moved += nr_pages;
-               }
-       }
-
-       if (!is_active_lru(lru)) {
-               __count_vm_events(PGDEACTIVATE, nr_moved);
-               count_memcg_events(lruvec_memcg(lruvec), PGDEACTIVATE,
-                                  nr_moved);
-       }
-
-       return nr_moved;
-}
-
 static void shrink_active_list(unsigned long nr_to_scan,
                               struct lruvec *lruvec,
                               struct scan_control *sc,
@@ -2079,7 +2022,7 @@ static void shrink_active_list(unsigned long nr_to_scan,
        reclaim_stat->recent_scanned[file] += nr_taken;
 
        __count_vm_events(PGREFILL, nr_scanned);
-       count_memcg_events(lruvec_memcg(lruvec), PGREFILL, nr_scanned);
+       __count_memcg_events(lruvec_memcg(lruvec), PGREFILL, nr_scanned);
 
        spin_unlock_irq(&pgdat->lru_lock);
 
@@ -2136,13 +2079,19 @@ static void shrink_active_list(unsigned long nr_to_scan,
         */
        reclaim_stat->recent_rotated[file] += nr_rotated;
 
-       nr_activate = move_active_pages_to_lru(lruvec, &l_active, &l_hold, lru);
-       nr_deactivate = move_active_pages_to_lru(lruvec, &l_inactive, &l_hold, lru - LRU_ACTIVE);
+       nr_activate = move_pages_to_lru(lruvec, &l_active);
+       nr_deactivate = move_pages_to_lru(lruvec, &l_inactive);
+       /* Keep all free pages in l_active list */
+       list_splice(&l_inactive, &l_active);
+
+       __count_vm_events(PGDEACTIVATE, nr_deactivate);
+       __count_memcg_events(lruvec_memcg(lruvec), PGDEACTIVATE, nr_deactivate);
+
        __mod_node_page_state(pgdat, NR_ISOLATED_ANON + file, -nr_taken);
        spin_unlock_irq(&pgdat->lru_lock);
 
-       mem_cgroup_uncharge_list(&l_hold);
-       free_unref_page_list(&l_hold);
+       mem_cgroup_uncharge_list(&l_active);
+       free_unref_page_list(&l_active);
        trace_mm_vmscan_lru_shrink_active(pgdat->node_id, nr_taken, nr_activate,
                        nr_deactivate, nr_rotated, sc->priority, file);
 }
@@ -2201,7 +2150,7 @@ static bool inactive_list_is_low(struct lruvec *lruvec, bool file,
         * is being established. Disable active list protection to get
         * rid of the stale workingset quickly.
         */
-       refaults = lruvec_page_state(lruvec, WORKINGSET_ACTIVATE);
+       refaults = lruvec_page_state_local(lruvec, WORKINGSET_ACTIVATE);
        if (file && actual_reclaim && lruvec->refaults != refaults) {
                inactive_ratio = 0;
        } else {
@@ -2963,7 +2912,7 @@ static void snapshot_refaults(struct mem_cgroup *root_memcg, pg_data_t *pgdat)
                struct lruvec *lruvec;
 
                lruvec = mem_cgroup_lruvec(pgdat, memcg);
-               refaults = lruvec_page_state(lruvec, WORKINGSET_ACTIVATE);
+               refaults = lruvec_page_state_local(lruvec, WORKINGSET_ACTIVATE);
                lruvec->refaults = refaults;
        } while ((memcg = mem_cgroup_iter(root_memcg, memcg, NULL)));
 }
@@ -3212,10 +3161,7 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
        if (throttle_direct_reclaim(sc.gfp_mask, zonelist, nodemask))
                return 1;
 
-       trace_mm_vmscan_direct_reclaim_begin(order,
-                               sc.may_writepage,
-                               sc.gfp_mask,
-                               sc.reclaim_idx);
+       trace_mm_vmscan_direct_reclaim_begin(order, sc.gfp_mask);
 
        nr_reclaimed = do_try_to_free_pages(zonelist, &sc);
 
@@ -3246,9 +3192,7 @@ unsigned long mem_cgroup_shrink_node(struct mem_cgroup *memcg,
                        (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK);
 
        trace_mm_vmscan_memcg_softlimit_reclaim_begin(sc.order,
-                                                     sc.may_writepage,
-                                                     sc.gfp_mask,
-                                                     sc.reclaim_idx);
+                                                     sc.gfp_mask);
 
        /*
         * NOTE: Although we can get the priority field, using it
@@ -3297,10 +3241,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
 
        zonelist = &NODE_DATA(nid)->node_zonelists[ZONELIST_FALLBACK];
 
-       trace_mm_vmscan_memcg_reclaim_begin(0,
-                                           sc.may_writepage,
-                                           sc.gfp_mask,
-                                           sc.reclaim_idx);
+       trace_mm_vmscan_memcg_reclaim_begin(0, sc.gfp_mask);
 
        psi_memstall_enter(&pflags);
        noreclaim_flag = memalloc_noreclaim_save();
@@ -4149,6 +4090,9 @@ static int __node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned in
                .reclaim_idx = gfp_zone(gfp_mask),
        };
 
+       trace_mm_vmscan_node_reclaim_begin(pgdat->node_id, order,
+                                          sc.gfp_mask);
+
        cond_resched();
        fs_reclaim_acquire(sc.gfp_mask);
        /*
@@ -4175,6 +4119,9 @@ static int __node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned in
        current->flags &= ~PF_SWAPWRITE;
        memalloc_noreclaim_restore(noreclaim_flag);
        fs_reclaim_release(sc.gfp_mask);
+
+       trace_mm_vmscan_node_reclaim_end(sc.nr_reclaimed);
+
        return sc.nr_reclaimed >= nr_pages;
 }
 
index 0bedf67..e0b4edc 100644 (file)
@@ -426,12 +426,14 @@ static unsigned long count_shadow_nodes(struct shrinker *shrinker,
 #ifdef CONFIG_MEMCG
        if (sc->memcg) {
                struct lruvec *lruvec;
+               int i;
 
-               pages = mem_cgroup_node_nr_lru_pages(sc->memcg, sc->nid,
-                                                    LRU_ALL);
                lruvec = mem_cgroup_lruvec(NODE_DATA(sc->nid), sc->memcg);
-               pages += lruvec_page_state(lruvec, NR_SLAB_RECLAIMABLE);
-               pages += lruvec_page_state(lruvec, NR_SLAB_UNRECLAIMABLE);
+               for (pages = 0, i = 0; i < NR_LRU_LISTS; i++)
+                       pages += lruvec_page_state_local(lruvec,
+                                                        NR_LRU_BASE + i);
+               pages += lruvec_page_state_local(lruvec, NR_SLAB_RECLAIMABLE);
+               pages += lruvec_page_state_local(lruvec, NR_SLAB_UNRECLAIMABLE);
        } else
 #endif
                pages = node_present_pages(sc->nid);
index aee9b0b..1ffecd6 100644 (file)
 
 #include <linux/atomic.h>
 #include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/dcache.h>
 #include <linux/list.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/page-flags.h>
+#include <linux/migrate.h>
+#include <linux/node.h>
+#include <linux/compaction.h>
 #include <linux/percpu.h>
+#include <linux/mount.h>
+#include <linux/fs.h>
 #include <linux/preempt.h>
 #include <linux/workqueue.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/zpool.h>
 
+/*
+ * NCHUNKS_ORDER determines the internal allocation granularity, effectively
+ * adjusting internal fragmentation.  It also determines the number of
+ * freelists maintained in each pool. NCHUNKS_ORDER of 6 means that the
+ * allocation granularity will be in chunks of size PAGE_SIZE/64. Some chunks
+ * in the beginning of an allocated page are occupied by z3fold header, so
+ * NCHUNKS will be calculated to 63 (or 62 in case CONFIG_DEBUG_SPINLOCK=y),
+ * which shows the max number of free chunks in z3fold page, also there will
+ * be 63, or 62, respectively, freelists per pool.
+ */
+#define NCHUNKS_ORDER  6
+
+#define CHUNK_SHIFT    (PAGE_SHIFT - NCHUNKS_ORDER)
+#define CHUNK_SIZE     (1 << CHUNK_SHIFT)
+#define ZHDR_SIZE_ALIGNED round_up(sizeof(struct z3fold_header), CHUNK_SIZE)
+#define ZHDR_CHUNKS    (ZHDR_SIZE_ALIGNED >> CHUNK_SHIFT)
+#define TOTAL_CHUNKS   (PAGE_SIZE >> CHUNK_SHIFT)
+#define NCHUNKS                ((PAGE_SIZE - ZHDR_SIZE_ALIGNED) >> CHUNK_SHIFT)
+
+#define BUDDY_MASK     (0x3)
+#define BUDDY_SHIFT    2
+#define SLOTS_ALIGN    (0x40)
+
 /*****************
  * Structures
 *****************/
@@ -47,8 +78,18 @@ enum buddy {
        FIRST,
        MIDDLE,
        LAST,
-       BUDDIES_MAX
+       BUDDIES_MAX = LAST
+};
+
+struct z3fold_buddy_slots {
+       /*
+        * we are using BUDDY_MASK in handle_to_buddy etc. so there should
+        * be enough slots to hold all possible variants
+        */
+       unsigned long slot[BUDDY_MASK + 1];
+       unsigned long pool; /* back link + flags */
 };
+#define HANDLE_FLAG_MASK       (0x03)
 
 /*
  * struct z3fold_header - z3fold page metadata occupying first chunks of each
@@ -58,49 +99,29 @@ enum buddy {
  * @page_lock:         per-page lock
  * @refcount:          reference count for the z3fold page
  * @work:              work_struct for page layout optimization
- * @pool:              pointer to the pool which this page belongs to
+ * @slots:             pointer to the structure holding buddy slots
  * @cpu:               CPU which this page "belongs" to
  * @first_chunks:      the size of the first buddy in chunks, 0 if free
  * @middle_chunks:     the size of the middle buddy in chunks, 0 if free
  * @last_chunks:       the size of the last buddy in chunks, 0 if free
  * @first_num:         the starting number (for the first handle)
+ * @mapped_count:      the number of objects currently mapped
  */
 struct z3fold_header {
        struct list_head buddy;
        spinlock_t page_lock;
        struct kref refcount;
        struct work_struct work;
-       struct z3fold_pool *pool;
+       struct z3fold_buddy_slots *slots;
        short cpu;
        unsigned short first_chunks;
        unsigned short middle_chunks;
        unsigned short last_chunks;
        unsigned short start_middle;
        unsigned short first_num:2;
+       unsigned short mapped_count:2;
 };
 
-/*
- * NCHUNKS_ORDER determines the internal allocation granularity, effectively
- * adjusting internal fragmentation.  It also determines the number of
- * freelists maintained in each pool. NCHUNKS_ORDER of 6 means that the
- * allocation granularity will be in chunks of size PAGE_SIZE/64. Some chunks
- * in the beginning of an allocated page are occupied by z3fold header, so
- * NCHUNKS will be calculated to 63 (or 62 in case CONFIG_DEBUG_SPINLOCK=y),
- * which shows the max number of free chunks in z3fold page, also there will
- * be 63, or 62, respectively, freelists per pool.
- */
-#define NCHUNKS_ORDER  6
-
-#define CHUNK_SHIFT    (PAGE_SHIFT - NCHUNKS_ORDER)
-#define CHUNK_SIZE     (1 << CHUNK_SHIFT)
-#define ZHDR_SIZE_ALIGNED round_up(sizeof(struct z3fold_header), CHUNK_SIZE)
-#define ZHDR_CHUNKS    (ZHDR_SIZE_ALIGNED >> CHUNK_SHIFT)
-#define TOTAL_CHUNKS   (PAGE_SIZE >> CHUNK_SHIFT)
-#define NCHUNKS                ((PAGE_SIZE - ZHDR_SIZE_ALIGNED) >> CHUNK_SHIFT)
-
-#define BUDDY_MASK     (0x3)
-#define BUDDY_SHIFT    2
-
 /**
  * struct z3fold_pool - stores metadata for each z3fold pool
  * @name:      pool name
@@ -113,11 +134,13 @@ struct z3fold_header {
  *             added buddy.
  * @stale:     list of pages marked for freeing
  * @pages_nr:  number of z3fold pages in the pool.
+ * @c_handle:  cache for z3fold_buddy_slots allocation
  * @ops:       pointer to a structure of user defined operations specified at
  *             pool creation time.
  * @compact_wq:        workqueue for page layout background optimization
  * @release_wq:        workqueue for safe page release
  * @work:      work_struct for safe page release
+ * @inode:     inode for z3fold pseudo filesystem
  *
  * This structure is allocated at pool creation time and maintains metadata
  * pertaining to a particular z3fold pool.
@@ -130,12 +153,14 @@ struct z3fold_pool {
        struct list_head lru;
        struct list_head stale;
        atomic64_t pages_nr;
+       struct kmem_cache *c_handle;
        const struct z3fold_ops *ops;
        struct zpool *zpool;
        const struct zpool_ops *zpool_ops;
        struct workqueue_struct *compact_wq;
        struct workqueue_struct *release_wq;
        struct work_struct work;
+       struct inode *inode;
 };
 
 /*
@@ -164,11 +189,118 @@ static int size_to_chunks(size_t size)
 
 static void compact_page_work(struct work_struct *w);
 
+static inline struct z3fold_buddy_slots *alloc_slots(struct z3fold_pool *pool)
+{
+       struct z3fold_buddy_slots *slots = kmem_cache_alloc(pool->c_handle,
+                                                       GFP_KERNEL);
+
+       if (slots) {
+               memset(slots->slot, 0, sizeof(slots->slot));
+               slots->pool = (unsigned long)pool;
+       }
+
+       return slots;
+}
+
+static inline struct z3fold_pool *slots_to_pool(struct z3fold_buddy_slots *s)
+{
+       return (struct z3fold_pool *)(s->pool & ~HANDLE_FLAG_MASK);
+}
+
+static inline struct z3fold_buddy_slots *handle_to_slots(unsigned long handle)
+{
+       return (struct z3fold_buddy_slots *)(handle & ~(SLOTS_ALIGN - 1));
+}
+
+static inline void free_handle(unsigned long handle)
+{
+       struct z3fold_buddy_slots *slots;
+       int i;
+       bool is_free;
+
+       if (handle & (1 << PAGE_HEADLESS))
+               return;
+
+       WARN_ON(*(unsigned long *)handle == 0);
+       *(unsigned long *)handle = 0;
+       slots = handle_to_slots(handle);
+       is_free = true;
+       for (i = 0; i <= BUDDY_MASK; i++) {
+               if (slots->slot[i]) {
+                       is_free = false;
+                       break;
+               }
+       }
+
+       if (is_free) {
+               struct z3fold_pool *pool = slots_to_pool(slots);
+
+               kmem_cache_free(pool->c_handle, slots);
+       }
+}
+
+static struct dentry *z3fold_do_mount(struct file_system_type *fs_type,
+                               int flags, const char *dev_name, void *data)
+{
+       static const struct dentry_operations ops = {
+               .d_dname = simple_dname,
+       };
+
+       return mount_pseudo(fs_type, "z3fold:", NULL, &ops, 0x33);
+}
+
+static struct file_system_type z3fold_fs = {
+       .name           = "z3fold",
+       .mount          = z3fold_do_mount,
+       .kill_sb        = kill_anon_super,
+};
+
+static struct vfsmount *z3fold_mnt;
+static int z3fold_mount(void)
+{
+       int ret = 0;
+
+       z3fold_mnt = kern_mount(&z3fold_fs);
+       if (IS_ERR(z3fold_mnt))
+               ret = PTR_ERR(z3fold_mnt);
+
+       return ret;
+}
+
+static void z3fold_unmount(void)
+{
+       kern_unmount(z3fold_mnt);
+}
+
+static const struct address_space_operations z3fold_aops;
+static int z3fold_register_migration(struct z3fold_pool *pool)
+{
+       pool->inode = alloc_anon_inode(z3fold_mnt->mnt_sb);
+       if (IS_ERR(pool->inode)) {
+               pool->inode = NULL;
+               return 1;
+       }
+
+       pool->inode->i_mapping->private_data = pool;
+       pool->inode->i_mapping->a_ops = &z3fold_aops;
+       return 0;
+}
+
+static void z3fold_unregister_migration(struct z3fold_pool *pool)
+{
+       if (pool->inode)
+               iput(pool->inode);
+ }
+
 /* Initializes the z3fold header of a newly allocated z3fold page */
 static struct z3fold_header *init_z3fold_page(struct page *page,
                                        struct z3fold_pool *pool)
 {
        struct z3fold_header *zhdr = page_address(page);
+       struct z3fold_buddy_slots *slots = alloc_slots(pool);
+
+       if (!slots)
+               return NULL;
 
        INIT_LIST_HEAD(&page->lru);
        clear_bit(PAGE_HEADLESS, &page->private);
@@ -185,15 +317,21 @@ static struct z3fold_header *init_z3fold_page(struct page *page,
        zhdr->first_num = 0;
        zhdr->start_middle = 0;
        zhdr->cpu = -1;
-       zhdr->pool = pool;
+       zhdr->slots = slots;
        INIT_LIST_HEAD(&zhdr->buddy);
        INIT_WORK(&zhdr->work, compact_page_work);
        return zhdr;
 }
 
 /* Resets the struct page fields and frees the page */
-static void free_z3fold_page(struct page *page)
+static void free_z3fold_page(struct page *page, bool headless)
 {
+       if (!headless) {
+               lock_page(page);
+               __ClearPageMovable(page);
+               unlock_page(page);
+       }
+       ClearPagePrivate(page);
        __free_page(page);
 }
 
@@ -215,33 +353,57 @@ static inline void z3fold_page_unlock(struct z3fold_header *zhdr)
        spin_unlock(&zhdr->page_lock);
 }
 
+/* Helper function to build the index */
+static inline int __idx(struct z3fold_header *zhdr, enum buddy bud)
+{
+       return (bud + zhdr->first_num) & BUDDY_MASK;
+}
+
 /*
  * Encodes the handle of a particular buddy within a z3fold page
  * Pool lock should be held as this function accesses first_num
  */
 static unsigned long encode_handle(struct z3fold_header *zhdr, enum buddy bud)
 {
-       unsigned long handle;
+       struct z3fold_buddy_slots *slots;
+       unsigned long h = (unsigned long)zhdr;
+       int idx = 0;
 
-       handle = (unsigned long)zhdr;
-       if (bud != HEADLESS) {
-               handle |= (bud + zhdr->first_num) & BUDDY_MASK;
-               if (bud == LAST)
-                       handle |= (zhdr->last_chunks << BUDDY_SHIFT);
-       }
-       return handle;
+       /*
+        * For a headless page, its handle is its pointer with the extra
+        * PAGE_HEADLESS bit set
+        */
+       if (bud == HEADLESS)
+               return h | (1 << PAGE_HEADLESS);
+
+       /* otherwise, return pointer to encoded handle */
+       idx = __idx(zhdr, bud);
+       h += idx;
+       if (bud == LAST)
+               h |= (zhdr->last_chunks << BUDDY_SHIFT);
+
+       slots = zhdr->slots;
+       slots->slot[idx] = h;
+       return (unsigned long)&slots->slot[idx];
 }
 
 /* Returns the z3fold page where a given handle is stored */
-static struct z3fold_header *handle_to_z3fold_header(unsigned long handle)
+static inline struct z3fold_header *handle_to_z3fold_header(unsigned long h)
 {
-       return (struct z3fold_header *)(handle & PAGE_MASK);
+       unsigned long addr = h;
+
+       if (!(addr & (1 << PAGE_HEADLESS)))
+               addr = *(unsigned long *)h;
+
+       return (struct z3fold_header *)(addr & PAGE_MASK);
 }
 
 /* only for LAST bud, returns zero otherwise */
 static unsigned short handle_to_chunks(unsigned long handle)
 {
-       return (handle & ~PAGE_MASK) >> BUDDY_SHIFT;
+       unsigned long addr = *(unsigned long *)handle;
+
+       return (addr & ~PAGE_MASK) >> BUDDY_SHIFT;
 }
 
 /*
@@ -251,21 +413,31 @@ static unsigned short handle_to_chunks(unsigned long handle)
  */
 static enum buddy handle_to_buddy(unsigned long handle)
 {
-       struct z3fold_header *zhdr = handle_to_z3fold_header(handle);
-       return (handle - zhdr->first_num) & BUDDY_MASK;
+       struct z3fold_header *zhdr;
+       unsigned long addr;
+
+       WARN_ON(handle & (1 << PAGE_HEADLESS));
+       addr = *(unsigned long *)handle;
+       zhdr = (struct z3fold_header *)(addr & PAGE_MASK);
+       return (addr - zhdr->first_num) & BUDDY_MASK;
+}
+
+static inline struct z3fold_pool *zhdr_to_pool(struct z3fold_header *zhdr)
+{
+       return slots_to_pool(zhdr->slots);
 }
 
 static void __release_z3fold_page(struct z3fold_header *zhdr, bool locked)
 {
        struct page *page = virt_to_page(zhdr);
-       struct z3fold_pool *pool = zhdr->pool;
+       struct z3fold_pool *pool = zhdr_to_pool(zhdr);
 
        WARN_ON(!list_empty(&zhdr->buddy));
        set_bit(PAGE_STALE, &page->private);
        clear_bit(NEEDS_COMPACTING, &page->private);
        spin_lock(&pool->lock);
        if (!list_empty(&page->lru))
-               list_del(&page->lru);
+               list_del_init(&page->lru);
        spin_unlock(&pool->lock);
        if (locked)
                z3fold_page_unlock(zhdr);
@@ -295,9 +467,10 @@ static void release_z3fold_page_locked_list(struct kref *ref)
 {
        struct z3fold_header *zhdr = container_of(ref, struct z3fold_header,
                                               refcount);
-       spin_lock(&zhdr->pool->lock);
+       struct z3fold_pool *pool = zhdr_to_pool(zhdr);
+       spin_lock(&pool->lock);
        list_del_init(&zhdr->buddy);
-       spin_unlock(&zhdr->pool->lock);
+       spin_unlock(&pool->lock);
 
        WARN_ON(z3fold_page_trylock(zhdr));
        __release_z3fold_page(zhdr, true);
@@ -318,7 +491,7 @@ static void free_pages_work(struct work_struct *w)
                        continue;
                spin_unlock(&pool->stale_lock);
                cancel_work_sync(&zhdr->work);
-               free_z3fold_page(page);
+               free_z3fold_page(page, false);
                cond_resched();
                spin_lock(&pool->stale_lock);
        }
@@ -349,6 +522,23 @@ static int num_free_chunks(struct z3fold_header *zhdr)
        return nfree;
 }
 
+/* Add to the appropriate unbuddied list */
+static inline void add_to_unbuddied(struct z3fold_pool *pool,
+                               struct z3fold_header *zhdr)
+{
+       if (zhdr->first_chunks == 0 || zhdr->last_chunks == 0 ||
+                       zhdr->middle_chunks == 0) {
+               struct list_head *unbuddied = get_cpu_ptr(pool->unbuddied);
+
+               int freechunks = num_free_chunks(zhdr);
+               spin_lock(&pool->lock);
+               list_add(&zhdr->buddy, &unbuddied[freechunks]);
+               spin_unlock(&pool->lock);
+               zhdr->cpu = smp_processor_id();
+               put_cpu_ptr(pool->unbuddied);
+       }
+}
+
 static inline void *mchunk_memmove(struct z3fold_header *zhdr,
                                unsigned short dst_chunk)
 {
@@ -367,6 +557,9 @@ static int z3fold_compact_page(struct z3fold_header *zhdr)
        if (test_bit(MIDDLE_CHUNK_MAPPED, &page->private))
                return 0; /* can't move middle chunk, it's used */
 
+       if (unlikely(PageIsolated(page)))
+               return 0;
+
        if (zhdr->middle_chunks == 0)
                return 0; /* nothing to compact */
 
@@ -406,10 +599,8 @@ static int z3fold_compact_page(struct z3fold_header *zhdr)
 
 static void do_compact_page(struct z3fold_header *zhdr, bool locked)
 {
-       struct z3fold_pool *pool = zhdr->pool;
+       struct z3fold_pool *pool = zhdr_to_pool(zhdr);
        struct page *page;
-       struct list_head *unbuddied;
-       int fchunks;
 
        page = virt_to_page(zhdr);
        if (locked)
@@ -429,19 +620,14 @@ static void do_compact_page(struct z3fold_header *zhdr, bool locked)
                return;
        }
 
-       z3fold_compact_page(zhdr);
-       unbuddied = get_cpu_ptr(pool->unbuddied);
-       fchunks = num_free_chunks(zhdr);
-       if (fchunks < NCHUNKS &&
-           (!zhdr->first_chunks || !zhdr->middle_chunks ||
-                       !zhdr->last_chunks)) {
-               /* the page's not completely free and it's unbuddied */
-               spin_lock(&pool->lock);
-               list_add(&zhdr->buddy, &unbuddied[fchunks]);
-               spin_unlock(&pool->lock);
-               zhdr->cpu = smp_processor_id();
+       if (unlikely(PageIsolated(page) ||
+                    test_bit(PAGE_STALE, &page->private))) {
+               z3fold_page_unlock(zhdr);
+               return;
        }
-       put_cpu_ptr(pool->unbuddied);
+
+       z3fold_compact_page(zhdr);
+       add_to_unbuddied(pool, zhdr);
        z3fold_page_unlock(zhdr);
 }
 
@@ -453,6 +639,103 @@ static void compact_page_work(struct work_struct *w)
        do_compact_page(zhdr, false);
 }
 
+/* returns _locked_ z3fold page header or NULL */
+static inline struct z3fold_header *__z3fold_alloc(struct z3fold_pool *pool,
+                                               size_t size, bool can_sleep)
+{
+       struct z3fold_header *zhdr = NULL;
+       struct page *page;
+       struct list_head *unbuddied;
+       int chunks = size_to_chunks(size), i;
+
+lookup:
+       /* First, try to find an unbuddied z3fold page. */
+       unbuddied = get_cpu_ptr(pool->unbuddied);
+       for_each_unbuddied_list(i, chunks) {
+               struct list_head *l = &unbuddied[i];
+
+               zhdr = list_first_entry_or_null(READ_ONCE(l),
+                                       struct z3fold_header, buddy);
+
+               if (!zhdr)
+                       continue;
+
+               /* Re-check under lock. */
+               spin_lock(&pool->lock);
+               l = &unbuddied[i];
+               if (unlikely(zhdr != list_first_entry(READ_ONCE(l),
+                                               struct z3fold_header, buddy)) ||
+                   !z3fold_page_trylock(zhdr)) {
+                       spin_unlock(&pool->lock);
+                       zhdr = NULL;
+                       put_cpu_ptr(pool->unbuddied);
+                       if (can_sleep)
+                               cond_resched();
+                       goto lookup;
+               }
+               list_del_init(&zhdr->buddy);
+               zhdr->cpu = -1;
+               spin_unlock(&pool->lock);
+
+               page = virt_to_page(zhdr);
+               if (test_bit(NEEDS_COMPACTING, &page->private)) {
+                       z3fold_page_unlock(zhdr);
+                       zhdr = NULL;
+                       put_cpu_ptr(pool->unbuddied);
+                       if (can_sleep)
+                               cond_resched();
+                       goto lookup;
+               }
+
+               /*
+                * this page could not be removed from its unbuddied
+                * list while pool lock was held, and then we've taken
+                * page lock so kref_put could not be called before
+                * we got here, so it's safe to just call kref_get()
+                */
+               kref_get(&zhdr->refcount);
+               break;
+       }
+       put_cpu_ptr(pool->unbuddied);
+
+       if (!zhdr) {
+               int cpu;
+
+               /* look for _exact_ match on other cpus' lists */
+               for_each_online_cpu(cpu) {
+                       struct list_head *l;
+
+                       unbuddied = per_cpu_ptr(pool->unbuddied, cpu);
+                       spin_lock(&pool->lock);
+                       l = &unbuddied[chunks];
+
+                       zhdr = list_first_entry_or_null(READ_ONCE(l),
+                                               struct z3fold_header, buddy);
+
+                       if (!zhdr || !z3fold_page_trylock(zhdr)) {
+                               spin_unlock(&pool->lock);
+                               zhdr = NULL;
+                               continue;
+                       }
+                       list_del_init(&zhdr->buddy);
+                       zhdr->cpu = -1;
+                       spin_unlock(&pool->lock);
+
+                       page = virt_to_page(zhdr);
+                       if (test_bit(NEEDS_COMPACTING, &page->private)) {
+                               z3fold_page_unlock(zhdr);
+                               zhdr = NULL;
+                               if (can_sleep)
+                                       cond_resched();
+                               continue;
+                       }
+                       kref_get(&zhdr->refcount);
+                       break;
+               }
+       }
+
+       return zhdr;
+}
 
 /*
  * API Functions
@@ -476,6 +759,11 @@ static struct z3fold_pool *z3fold_create_pool(const char *name, gfp_t gfp,
        pool = kzalloc(sizeof(struct z3fold_pool), gfp);
        if (!pool)
                goto out;
+       pool->c_handle = kmem_cache_create("z3fold_handle",
+                               sizeof(struct z3fold_buddy_slots),
+                               SLOTS_ALIGN, 0, NULL);
+       if (!pool->c_handle)
+               goto out_c;
        spin_lock_init(&pool->lock);
        spin_lock_init(&pool->stale_lock);
        pool->unbuddied = __alloc_percpu(sizeof(struct list_head)*NCHUNKS, 2);
@@ -497,15 +785,21 @@ static struct z3fold_pool *z3fold_create_pool(const char *name, gfp_t gfp,
        pool->release_wq = create_singlethread_workqueue(pool->name);
        if (!pool->release_wq)
                goto out_wq;
+       if (z3fold_register_migration(pool))
+               goto out_rwq;
        INIT_WORK(&pool->work, free_pages_work);
        pool->ops = ops;
        return pool;
 
+out_rwq:
+       destroy_workqueue(pool->release_wq);
 out_wq:
        destroy_workqueue(pool->compact_wq);
 out_unbuddied:
        free_percpu(pool->unbuddied);
 out_pool:
+       kmem_cache_destroy(pool->c_handle);
+out_c:
        kfree(pool);
 out:
        return NULL;
@@ -519,6 +813,8 @@ out:
  */
 static void z3fold_destroy_pool(struct z3fold_pool *pool)
 {
+       kmem_cache_destroy(pool->c_handle);
+       z3fold_unregister_migration(pool);
        destroy_workqueue(pool->release_wq);
        destroy_workqueue(pool->compact_wq);
        kfree(pool);
@@ -546,7 +842,7 @@ static void z3fold_destroy_pool(struct z3fold_pool *pool)
 static int z3fold_alloc(struct z3fold_pool *pool, size_t size, gfp_t gfp,
                        unsigned long *handle)
 {
-       int chunks = 0, i, freechunks;
+       int chunks = size_to_chunks(size);
        struct z3fold_header *zhdr = NULL;
        struct page *page = NULL;
        enum buddy bud;
@@ -561,56 +857,8 @@ static int z3fold_alloc(struct z3fold_pool *pool, size_t size, gfp_t gfp,
        if (size > PAGE_SIZE - ZHDR_SIZE_ALIGNED - CHUNK_SIZE)
                bud = HEADLESS;
        else {
-               struct list_head *unbuddied;
-               chunks = size_to_chunks(size);
-
-lookup:
-               /* First, try to find an unbuddied z3fold page. */
-               unbuddied = get_cpu_ptr(pool->unbuddied);
-               for_each_unbuddied_list(i, chunks) {
-                       struct list_head *l = &unbuddied[i];
-
-                       zhdr = list_first_entry_or_null(READ_ONCE(l),
-                                               struct z3fold_header, buddy);
-
-                       if (!zhdr)
-                               continue;
-
-                       /* Re-check under lock. */
-                       spin_lock(&pool->lock);
-                       l = &unbuddied[i];
-                       if (unlikely(zhdr != list_first_entry(READ_ONCE(l),
-                                       struct z3fold_header, buddy)) ||
-                           !z3fold_page_trylock(zhdr)) {
-                               spin_unlock(&pool->lock);
-                               put_cpu_ptr(pool->unbuddied);
-                               goto lookup;
-                       }
-                       list_del_init(&zhdr->buddy);
-                       zhdr->cpu = -1;
-                       spin_unlock(&pool->lock);
-
-                       page = virt_to_page(zhdr);
-                       if (test_bit(NEEDS_COMPACTING, &page->private)) {
-                               z3fold_page_unlock(zhdr);
-                               zhdr = NULL;
-                               put_cpu_ptr(pool->unbuddied);
-                               if (can_sleep)
-                                       cond_resched();
-                               goto lookup;
-                       }
-
-                       /*
-                        * this page could not be removed from its unbuddied
-                        * list while pool lock was held, and then we've taken
-                        * page lock so kref_put could not be called before
-                        * we got here, so it's safe to just call kref_get()
-                        */
-                       kref_get(&zhdr->refcount);
-                       break;
-               }
-               put_cpu_ptr(pool->unbuddied);
-
+retry:
+               zhdr = __z3fold_alloc(pool, size, can_sleep);
                if (zhdr) {
                        if (zhdr->first_chunks == 0) {
                                if (zhdr->middle_chunks != 0 &&
@@ -630,8 +878,9 @@ lookup:
                                        z3fold_page_unlock(zhdr);
                                pr_err("No free chunks in unbuddied\n");
                                WARN_ON(1);
-                               goto lookup;
+                               goto retry;
                        }
+                       page = virt_to_page(zhdr);
                        goto found;
                }
                bud = FIRST;
@@ -662,13 +911,18 @@ lookup:
        if (!page)
                return -ENOMEM;
 
-       atomic64_inc(&pool->pages_nr);
        zhdr = init_z3fold_page(page, pool);
+       if (!zhdr) {
+               __free_page(page);
+               return -ENOMEM;
+       }
+       atomic64_inc(&pool->pages_nr);
 
        if (bud == HEADLESS) {
                set_bit(PAGE_HEADLESS, &page->private);
                goto headless;
        }
+       __SetPageMovable(page, pool->inode->i_mapping);
        z3fold_page_lock(zhdr);
 
 found:
@@ -680,19 +934,7 @@ found:
                zhdr->middle_chunks = chunks;
                zhdr->start_middle = zhdr->first_chunks + ZHDR_CHUNKS;
        }
-
-       if (zhdr->first_chunks == 0 || zhdr->last_chunks == 0 ||
-                       zhdr->middle_chunks == 0) {
-               struct list_head *unbuddied = get_cpu_ptr(pool->unbuddied);
-
-               /* Add to unbuddied list */
-               freechunks = num_free_chunks(zhdr);
-               spin_lock(&pool->lock);
-               list_add(&zhdr->buddy, &unbuddied[freechunks]);
-               spin_unlock(&pool->lock);
-               zhdr->cpu = smp_processor_id();
-               put_cpu_ptr(pool->unbuddied);
-       }
+       add_to_unbuddied(pool, zhdr);
 
 headless:
        spin_lock(&pool->lock);
@@ -739,7 +981,7 @@ static void z3fold_free(struct z3fold_pool *pool, unsigned long handle)
                        spin_lock(&pool->lock);
                        list_del(&page->lru);
                        spin_unlock(&pool->lock);
-                       free_z3fold_page(page);
+                       free_z3fold_page(page, true);
                        atomic64_dec(&pool->pages_nr);
                }
                return;
@@ -766,6 +1008,7 @@ static void z3fold_free(struct z3fold_pool *pool, unsigned long handle)
                return;
        }
 
+       free_handle(handle);
        if (kref_put(&zhdr->refcount, release_z3fold_page_locked_list)) {
                atomic64_dec(&pool->pages_nr);
                return;
@@ -774,7 +1017,8 @@ static void z3fold_free(struct z3fold_pool *pool, unsigned long handle)
                z3fold_page_unlock(zhdr);
                return;
        }
-       if (test_and_set_bit(NEEDS_COMPACTING, &page->private)) {
+       if (unlikely(PageIsolated(page)) ||
+           test_and_set_bit(NEEDS_COMPACTING, &page->private)) {
                z3fold_page_unlock(zhdr);
                return;
        }
@@ -855,10 +1099,12 @@ static int z3fold_reclaim_page(struct z3fold_pool *pool, unsigned int retries)
                        if (test_and_set_bit(PAGE_CLAIMED, &page->private))
                                continue;
 
-                       zhdr = page_address(page);
+                       if (unlikely(PageIsolated(page)))
+                               continue;
                        if (test_bit(PAGE_HEADLESS, &page->private))
                                break;
 
+                       zhdr = page_address(page);
                        if (!z3fold_page_trylock(zhdr)) {
                                zhdr = NULL;
                                continue; /* can't evict at this point */
@@ -919,7 +1165,7 @@ static int z3fold_reclaim_page(struct z3fold_pool *pool, unsigned int retries)
 next:
                if (test_bit(PAGE_HEADLESS, &page->private)) {
                        if (ret == 0) {
-                               free_z3fold_page(page);
+                               free_z3fold_page(page, true);
                                atomic64_dec(&pool->pages_nr);
                                return 0;
                        }
@@ -996,6 +1242,8 @@ static void *z3fold_map(struct z3fold_pool *pool, unsigned long handle)
                break;
        }
 
+       if (addr)
+               zhdr->mapped_count++;
        z3fold_page_unlock(zhdr);
 out:
        return addr;
@@ -1022,6 +1270,7 @@ static void z3fold_unmap(struct z3fold_pool *pool, unsigned long handle)
        buddy = handle_to_buddy(handle);
        if (buddy == MIDDLE)
                clear_bit(MIDDLE_CHUNK_MAPPED, &page->private);
+       zhdr->mapped_count--;
        z3fold_page_unlock(zhdr);
 }
 
@@ -1036,6 +1285,128 @@ static u64 z3fold_get_pool_size(struct z3fold_pool *pool)
        return atomic64_read(&pool->pages_nr);
 }
 
+static bool z3fold_page_isolate(struct page *page, isolate_mode_t mode)
+{
+       struct z3fold_header *zhdr;
+       struct z3fold_pool *pool;
+
+       VM_BUG_ON_PAGE(!PageMovable(page), page);
+       VM_BUG_ON_PAGE(PageIsolated(page), page);
+
+       if (test_bit(PAGE_HEADLESS, &page->private))
+               return false;
+
+       zhdr = page_address(page);
+       z3fold_page_lock(zhdr);
+       if (test_bit(NEEDS_COMPACTING, &page->private) ||
+           test_bit(PAGE_STALE, &page->private))
+               goto out;
+
+       pool = zhdr_to_pool(zhdr);
+
+       if (zhdr->mapped_count == 0) {
+               kref_get(&zhdr->refcount);
+               if (!list_empty(&zhdr->buddy))
+                       list_del_init(&zhdr->buddy);
+               spin_lock(&pool->lock);
+               if (!list_empty(&page->lru))
+                       list_del(&page->lru);
+               spin_unlock(&pool->lock);
+               z3fold_page_unlock(zhdr);
+               return true;
+       }
+out:
+       z3fold_page_unlock(zhdr);
+       return false;
+}
+
+static int z3fold_page_migrate(struct address_space *mapping, struct page *newpage,
+                              struct page *page, enum migrate_mode mode)
+{
+       struct z3fold_header *zhdr, *new_zhdr;
+       struct z3fold_pool *pool;
+       struct address_space *new_mapping;
+
+       VM_BUG_ON_PAGE(!PageMovable(page), page);
+       VM_BUG_ON_PAGE(!PageIsolated(page), page);
+
+       zhdr = page_address(page);
+       pool = zhdr_to_pool(zhdr);
+
+       if (!trylock_page(page))
+               return -EAGAIN;
+
+       if (!z3fold_page_trylock(zhdr)) {
+               unlock_page(page);
+               return -EAGAIN;
+       }
+       if (zhdr->mapped_count != 0) {
+               z3fold_page_unlock(zhdr);
+               unlock_page(page);
+               return -EBUSY;
+       }
+       new_zhdr = page_address(newpage);
+       memcpy(new_zhdr, zhdr, PAGE_SIZE);
+       newpage->private = page->private;
+       page->private = 0;
+       z3fold_page_unlock(zhdr);
+       spin_lock_init(&new_zhdr->page_lock);
+       new_mapping = page_mapping(page);
+       __ClearPageMovable(page);
+       ClearPagePrivate(page);
+
+       get_page(newpage);
+       z3fold_page_lock(new_zhdr);
+       if (new_zhdr->first_chunks)
+               encode_handle(new_zhdr, FIRST);
+       if (new_zhdr->last_chunks)
+               encode_handle(new_zhdr, LAST);
+       if (new_zhdr->middle_chunks)
+               encode_handle(new_zhdr, MIDDLE);
+       set_bit(NEEDS_COMPACTING, &newpage->private);
+       new_zhdr->cpu = smp_processor_id();
+       spin_lock(&pool->lock);
+       list_add(&newpage->lru, &pool->lru);
+       spin_unlock(&pool->lock);
+       __SetPageMovable(newpage, new_mapping);
+       z3fold_page_unlock(new_zhdr);
+
+       queue_work_on(new_zhdr->cpu, pool->compact_wq, &new_zhdr->work);
+
+       page_mapcount_reset(page);
+       unlock_page(page);
+       put_page(page);
+       return 0;
+}
+
+static void z3fold_page_putback(struct page *page)
+{
+       struct z3fold_header *zhdr;
+       struct z3fold_pool *pool;
+
+       zhdr = page_address(page);
+       pool = zhdr_to_pool(zhdr);
+
+       z3fold_page_lock(zhdr);
+       if (!list_empty(&zhdr->buddy))
+               list_del_init(&zhdr->buddy);
+       INIT_LIST_HEAD(&page->lru);
+       if (kref_put(&zhdr->refcount, release_z3fold_page_locked)) {
+               atomic64_dec(&pool->pages_nr);
+               return;
+       }
+       spin_lock(&pool->lock);
+       list_add(&page->lru, &pool->lru);
+       spin_unlock(&pool->lock);
+       z3fold_page_unlock(zhdr);
+}
+
+static const struct address_space_operations z3fold_aops = {
+       .isolate_page = z3fold_page_isolate,
+       .migratepage = z3fold_page_migrate,
+       .putback_page = z3fold_page_putback,
+};
+
 /*****************
  * zpool
  ****************/
@@ -1133,8 +1504,14 @@ MODULE_ALIAS("zpool-z3fold");
 
 static int __init init_z3fold(void)
 {
+       int ret;
+
        /* Make sure the z3fold header is not larger than the page size */
        BUILD_BUG_ON(ZHDR_SIZE_ALIGNED > PAGE_SIZE);
+       ret = z3fold_mount();
+       if (ret)
+               return ret;
+
        zpool_register_driver(&z3fold_zpool_driver);
 
        return 0;
@@ -1142,6 +1519,7 @@ static int __init init_z3fold(void)
 
 static void __exit exit_z3fold(void)
 {
+       z3fold_unmount();
        zpool_unregister_driver(&z3fold_zpool_driver);
 }
 
index 4a9aaa3..6d4a24a 100644 (file)
@@ -602,13 +602,15 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
        call_netdevice_notifiers(NETDEV_JOIN, dev);
 
        err = dev_set_allmulti(dev, 1);
-       if (err)
-               goto put_back;
+       if (err) {
+               kfree(p);       /* kobject not yet init'd, manually free */
+               goto err1;
+       }
 
        err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj),
                                   SYSFS_BRIDGE_PORT_ATTR);
        if (err)
-               goto err1;
+               goto err2;
 
        err = br_sysfs_addif(p);
        if (err)
@@ -700,12 +702,9 @@ err3:
        sysfs_remove_link(br->ifobj, p->dev->name);
 err2:
        kobject_put(&p->kobj);
-       p = NULL; /* kobject_put frees */
-err1:
        dev_set_allmulti(dev, -1);
-put_back:
+err1:
        dev_put(dev);
-       kfree(p);
        return err;
 }
 
index 4e00913..6b07e49 100644 (file)
@@ -2153,7 +2153,9 @@ static int compat_copy_entries(unsigned char *data, unsigned int size_user,
        if (ret < 0)
                return ret;
 
-       WARN_ON(size_remaining);
+       if (size_remaining)
+               return -EINVAL;
+
        return state->buf_kern_offset;
 }
 
index 2105a6e..4cc2854 100644 (file)
@@ -271,7 +271,7 @@ static int decode_locker(void **p, void *end, struct ceph_locker *locker)
 
        dout("%s %s%llu cookie %s addr %s\n", __func__,
             ENTITY_NAME(locker->id.name), locker->id.cookie,
-            ceph_pr_addr(&locker->info.addr.in_addr));
+            ceph_pr_addr(&locker->info.addr));
        return 0;
 }
 
index 46f6570..63aef99 100644 (file)
@@ -46,7 +46,7 @@ static int monmap_show(struct seq_file *s, void *p)
 
                seq_printf(s, "\t%s%lld\t%s\n",
                           ENTITY_NAME(inst->name),
-                          ceph_pr_addr(&inst->addr.in_addr));
+                          ceph_pr_addr(&inst->addr));
        }
        return 0;
 }
@@ -82,7 +82,7 @@ static int osdmap_show(struct seq_file *s, void *p)
                char sb[64];
 
                seq_printf(s, "osd%d\t%s\t%3d%%\t(%s)\t%3d%%\n",
-                          i, ceph_pr_addr(&addr->in_addr),
+                          i, ceph_pr_addr(addr),
                           ((map->osd_weight[i]*100) >> 16),
                           ceph_osdmap_state_str(sb, sizeof(sb), state),
                           ((ceph_get_primary_affinity(map, i)*100) >> 16));
index 3083988..cd0b094 100644 (file)
@@ -186,17 +186,18 @@ static atomic_t addr_str_seq = ATOMIC_INIT(0);
 
 static struct page *zero_page;         /* used in certain error cases */
 
-const char *ceph_pr_addr(const struct sockaddr_storage *ss)
+const char *ceph_pr_addr(const struct ceph_entity_addr *addr)
 {
        int i;
        char *s;
-       struct sockaddr_in *in4 = (struct sockaddr_in *) ss;
-       struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) ss;
+       struct sockaddr_storage ss = addr->in_addr; /* align */
+       struct sockaddr_in *in4 = (struct sockaddr_in *)&ss;
+       struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&ss;
 
        i = atomic_inc_return(&addr_str_seq) & ADDR_STR_COUNT_MASK;
        s = addr_str[i];
 
-       switch (ss->ss_family) {
+       switch (ss.ss_family) {
        case AF_INET:
                snprintf(s, MAX_ADDR_STR_LEN, "%pI4:%hu", &in4->sin_addr,
                         ntohs(in4->sin_port));
@@ -209,7 +210,7 @@ const char *ceph_pr_addr(const struct sockaddr_storage *ss)
 
        default:
                snprintf(s, MAX_ADDR_STR_LEN, "(unknown sockaddr family %hu)",
-                        ss->ss_family);
+                        ss.ss_family);
        }
 
        return s;
@@ -449,7 +450,7 @@ static void set_sock_callbacks(struct socket *sock,
  */
 static int ceph_tcp_connect(struct ceph_connection *con)
 {
-       struct sockaddr_storage *paddr = &con->peer_addr.in_addr;
+       struct sockaddr_storage ss = con->peer_addr.in_addr; /* align */
        struct socket *sock;
        unsigned int noio_flag;
        int ret;
@@ -458,7 +459,7 @@ static int ceph_tcp_connect(struct ceph_connection *con)
 
        /* sock_create_kern() allocates with GFP_KERNEL */
        noio_flag = memalloc_noio_save();
-       ret = sock_create_kern(read_pnet(&con->msgr->net), paddr->ss_family,
+       ret = sock_create_kern(read_pnet(&con->msgr->net), ss.ss_family,
                               SOCK_STREAM, IPPROTO_TCP, &sock);
        memalloc_noio_restore(noio_flag);
        if (ret)
@@ -471,18 +472,18 @@ static int ceph_tcp_connect(struct ceph_connection *con)
 
        set_sock_callbacks(sock, con);
 
-       dout("connect %s\n", ceph_pr_addr(&con->peer_addr.in_addr));
+       dout("connect %s\n", ceph_pr_addr(&con->peer_addr));
 
        con_sock_state_connecting(con);
-       ret = sock->ops->connect(sock, (struct sockaddr *)paddr, sizeof(*paddr),
+       ret = sock->ops->connect(sock, (struct sockaddr *)&ss, sizeof(ss),
                                 O_NONBLOCK);
        if (ret == -EINPROGRESS) {
                dout("connect %s EINPROGRESS sk_state = %u\n",
-                    ceph_pr_addr(&con->peer_addr.in_addr),
+                    ceph_pr_addr(&con->peer_addr),
                     sock->sk->sk_state);
        } else if (ret < 0) {
                pr_err("connect %s error %d\n",
-                      ceph_pr_addr(&con->peer_addr.in_addr), ret);
+                      ceph_pr_addr(&con->peer_addr), ret);
                sock_release(sock);
                return ret;
        }
@@ -669,8 +670,7 @@ static void reset_connection(struct ceph_connection *con)
 void ceph_con_close(struct ceph_connection *con)
 {
        mutex_lock(&con->mutex);
-       dout("con_close %p peer %s\n", con,
-            ceph_pr_addr(&con->peer_addr.in_addr));
+       dout("con_close %p peer %s\n", con, ceph_pr_addr(&con->peer_addr));
        con->state = CON_STATE_CLOSED;
 
        con_flag_clear(con, CON_FLAG_LOSSYTX);  /* so we retry next connect */
@@ -694,7 +694,7 @@ void ceph_con_open(struct ceph_connection *con,
                   struct ceph_entity_addr *addr)
 {
        mutex_lock(&con->mutex);
-       dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr));
+       dout("con_open %p %s\n", con, ceph_pr_addr(addr));
 
        WARN_ON(con->state != CON_STATE_CLOSED);
        con->state = CON_STATE_PREOPEN;
@@ -1788,21 +1788,22 @@ static int verify_hello(struct ceph_connection *con)
 {
        if (memcmp(con->in_banner, CEPH_BANNER, strlen(CEPH_BANNER))) {
                pr_err("connect to %s got bad banner\n",
-                      ceph_pr_addr(&con->peer_addr.in_addr));
+                      ceph_pr_addr(&con->peer_addr));
                con->error_msg = "protocol error, bad banner";
                return -1;
        }
        return 0;
 }
 
-static bool addr_is_blank(struct sockaddr_storage *ss)
+static bool addr_is_blank(struct ceph_entity_addr *addr)
 {
-       struct in_addr *addr = &((struct sockaddr_in *)ss)->sin_addr;
-       struct in6_addr *addr6 = &((struct sockaddr_in6 *)ss)->sin6_addr;
+       struct sockaddr_storage ss = addr->in_addr; /* align */
+       struct in_addr *addr4 = &((struct sockaddr_in *)&ss)->sin_addr;
+       struct in6_addr *addr6 = &((struct sockaddr_in6 *)&ss)->sin6_addr;
 
-       switch (ss->ss_family) {
+       switch (ss.ss_family) {
        case AF_INET:
-               return addr->s_addr == htonl(INADDR_ANY);
+               return addr4->s_addr == htonl(INADDR_ANY);
        case AF_INET6:
                return ipv6_addr_any(addr6);
        default:
@@ -1810,25 +1811,25 @@ static bool addr_is_blank(struct sockaddr_storage *ss)
        }
 }
 
-static int addr_port(struct sockaddr_storage *ss)
+static int addr_port(struct ceph_entity_addr *addr)
 {
-       switch (ss->ss_family) {
+       switch (get_unaligned(&addr->in_addr.ss_family)) {
        case AF_INET:
-               return ntohs(((struct sockaddr_in *)ss)->sin_port);
+               return ntohs(get_unaligned(&((struct sockaddr_in *)&addr->in_addr)->sin_port));
        case AF_INET6:
-               return ntohs(((struct sockaddr_in6 *)ss)->sin6_port);
+               return ntohs(get_unaligned(&((struct sockaddr_in6 *)&addr->in_addr)->sin6_port));
        }
        return 0;
 }
 
-static void addr_set_port(struct sockaddr_storage *ss, int p)
+static void addr_set_port(struct ceph_entity_addr *addr, int p)
 {
-       switch (ss->ss_family) {
+       switch (get_unaligned(&addr->in_addr.ss_family)) {
        case AF_INET:
-               ((struct sockaddr_in *)ss)->sin_port = htons(p);
+               put_unaligned(htons(p), &((struct sockaddr_in *)&addr->in_addr)->sin_port);
                break;
        case AF_INET6:
-               ((struct sockaddr_in6 *)ss)->sin6_port = htons(p);
+               put_unaligned(htons(p), &((struct sockaddr_in6 *)&addr->in_addr)->sin6_port);
                break;
        }
 }
@@ -1836,21 +1837,18 @@ static void addr_set_port(struct sockaddr_storage *ss, int p)
 /*
  * Unlike other *_pton function semantics, zero indicates success.
  */
-static int ceph_pton(const char *str, size_t len, struct sockaddr_storage *ss,
+static int ceph_pton(const char *str, size_t len, struct ceph_entity_addr *addr,
                char delim, const char **ipend)
 {
-       struct sockaddr_in *in4 = (struct sockaddr_in *) ss;
-       struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) ss;
+       memset(&addr->in_addr, 0, sizeof(addr->in_addr));
 
-       memset(ss, 0, sizeof(*ss));
-
-       if (in4_pton(str, len, (u8 *)&in4->sin_addr.s_addr, delim, ipend)) {
-               ss->ss_family = AF_INET;
+       if (in4_pton(str, len, (u8 *)&((struct sockaddr_in *)&addr->in_addr)->sin_addr.s_addr, delim, ipend)) {
+               put_unaligned(AF_INET, &addr->in_addr.ss_family);
                return 0;
        }
 
-       if (in6_pton(str, len, (u8 *)&in6->sin6_addr.s6_addr, delim, ipend)) {
-               ss->ss_family = AF_INET6;
+       if (in6_pton(str, len, (u8 *)&((struct sockaddr_in6 *)&addr->in_addr)->sin6_addr.s6_addr, delim, ipend)) {
+               put_unaligned(AF_INET6, &addr->in_addr.ss_family);
                return 0;
        }
 
@@ -1862,7 +1860,7 @@ static int ceph_pton(const char *str, size_t len, struct sockaddr_storage *ss,
  */
 #ifdef CONFIG_CEPH_LIB_USE_DNS_RESOLVER
 static int ceph_dns_resolve_name(const char *name, size_t namelen,
-               struct sockaddr_storage *ss, char delim, const char **ipend)
+               struct ceph_entity_addr *addr, char delim, const char **ipend)
 {
        const char *end, *delim_p;
        char *colon_p, *ip_addr = NULL;
@@ -1889,9 +1887,9 @@ static int ceph_dns_resolve_name(const char *name, size_t namelen,
                return -EINVAL;
 
        /* do dns_resolve upcall */
-       ip_len = dns_query(NULL, name, end - name, NULL, &ip_addr, NULL);
+       ip_len = dns_query(NULL, name, end - name, NULL, &ip_addr, NULL, false);
        if (ip_len > 0)
-               ret = ceph_pton(ip_addr, ip_len, ss, -1, NULL);
+               ret = ceph_pton(ip_addr, ip_len, addr, -1, NULL);
        else
                ret = -ESRCH;
 
@@ -1900,13 +1898,13 @@ static int ceph_dns_resolve_name(const char *name, size_t namelen,
        *ipend = end;
 
        pr_info("resolve '%.*s' (ret=%d): %s\n", (int)(end - name), name,
-                       ret, ret ? "failed" : ceph_pr_addr(ss));
+                       ret, ret ? "failed" : ceph_pr_addr(addr));
 
        return ret;
 }
 #else
 static inline int ceph_dns_resolve_name(const char *name, size_t namelen,
-               struct sockaddr_storage *ss, char delim, const char **ipend)
+               struct ceph_entity_addr *addr, char delim, const char **ipend)
 {
        return -EINVAL;
 }
@@ -1917,13 +1915,13 @@ static inline int ceph_dns_resolve_name(const char *name, size_t namelen,
  * then try to extract a hostname to resolve using userspace DNS upcall.
  */
 static int ceph_parse_server_name(const char *name, size_t namelen,
-                       struct sockaddr_storage *ss, char delim, const char **ipend)
+               struct ceph_entity_addr *addr, char delim, const char **ipend)
 {
        int ret;
 
-       ret = ceph_pton(name, namelen, ss, delim, ipend);
+       ret = ceph_pton(name, namelen, addr, delim, ipend);
        if (ret)
-               ret = ceph_dns_resolve_name(name, namelen, ss, delim, ipend);
+               ret = ceph_dns_resolve_name(name, namelen, addr, delim, ipend);
 
        return ret;
 }
@@ -1942,7 +1940,6 @@ int ceph_parse_ips(const char *c, const char *end,
        dout("parse_ips on '%.*s'\n", (int)(end-c), c);
        for (i = 0; i < max_count; i++) {
                const char *ipend;
-               struct sockaddr_storage *ss = &addr[i].in_addr;
                int port;
                char delim = ',';
 
@@ -1951,7 +1948,7 @@ int ceph_parse_ips(const char *c, const char *end,
                        p++;
                }
 
-               ret = ceph_parse_server_name(p, end - p, ss, delim, &ipend);
+               ret = ceph_parse_server_name(p, end - p, &addr[i], delim, &ipend);
                if (ret)
                        goto bad;
                ret = -EINVAL;
@@ -1982,9 +1979,9 @@ int ceph_parse_ips(const char *c, const char *end,
                        port = CEPH_MON_PORT;
                }
 
-               addr_set_port(ss, port);
+               addr_set_port(&addr[i], port);
 
-               dout("parse_ips got %s\n", ceph_pr_addr(ss));
+               dout("parse_ips got %s\n", ceph_pr_addr(&addr[i]));
 
                if (p == end)
                        break;
@@ -2023,12 +2020,12 @@ static int process_banner(struct ceph_connection *con)
         */
        if (memcmp(&con->peer_addr, &con->actual_peer_addr,
                   sizeof(con->peer_addr)) != 0 &&
-           !(addr_is_blank(&con->actual_peer_addr.in_addr) &&
+           !(addr_is_blank(&con->actual_peer_addr) &&
              con->actual_peer_addr.nonce == con->peer_addr.nonce)) {
                pr_warn("wrong peer, want %s/%d, got %s/%d\n",
-                       ceph_pr_addr(&con->peer_addr.in_addr),
+                       ceph_pr_addr(&con->peer_addr),
                        (int)le32_to_cpu(con->peer_addr.nonce),
-                       ceph_pr_addr(&con->actual_peer_addr.in_addr),
+                       ceph_pr_addr(&con->actual_peer_addr),
                        (int)le32_to_cpu(con->actual_peer_addr.nonce));
                con->error_msg = "wrong peer at address";
                return -1;
@@ -2037,16 +2034,16 @@ static int process_banner(struct ceph_connection *con)
        /*
         * did we learn our address?
         */
-       if (addr_is_blank(&con->msgr->inst.addr.in_addr)) {
-               int port = addr_port(&con->msgr->inst.addr.in_addr);
+       if (addr_is_blank(&con->msgr->inst.addr)) {
+               int port = addr_port(&con->msgr->inst.addr);
 
                memcpy(&con->msgr->inst.addr.in_addr,
                       &con->peer_addr_for_me.in_addr,
                       sizeof(con->peer_addr_for_me.in_addr));
-               addr_set_port(&con->msgr->inst.addr.in_addr, port);
+               addr_set_port(&con->msgr->inst.addr, port);
                encode_my_addr(con->msgr);
                dout("process_banner learned my addr is %s\n",
-                    ceph_pr_addr(&con->msgr->inst.addr.in_addr));
+                    ceph_pr_addr(&con->msgr->inst.addr));
        }
 
        return 0;
@@ -2097,7 +2094,7 @@ static int process_connect(struct ceph_connection *con)
                pr_err("%s%lld %s feature set mismatch,"
                       " my %llx < server's %llx, missing %llx\n",
                       ENTITY_NAME(con->peer_name),
-                      ceph_pr_addr(&con->peer_addr.in_addr),
+                      ceph_pr_addr(&con->peer_addr),
                       sup_feat, server_feat, server_feat & ~sup_feat);
                con->error_msg = "missing required protocol features";
                reset_connection(con);
@@ -2107,7 +2104,7 @@ static int process_connect(struct ceph_connection *con)
                pr_err("%s%lld %s protocol version mismatch,"
                       " my %d != server's %d\n",
                       ENTITY_NAME(con->peer_name),
-                      ceph_pr_addr(&con->peer_addr.in_addr),
+                      ceph_pr_addr(&con->peer_addr),
                       le32_to_cpu(con->out_connect.protocol_version),
                       le32_to_cpu(con->in_reply.protocol_version));
                con->error_msg = "protocol version mismatch";
@@ -2141,7 +2138,7 @@ static int process_connect(struct ceph_connection *con)
                     le32_to_cpu(con->in_reply.connect_seq));
                pr_err("%s%lld %s connection reset\n",
                       ENTITY_NAME(con->peer_name),
-                      ceph_pr_addr(&con->peer_addr.in_addr));
+                      ceph_pr_addr(&con->peer_addr));
                reset_connection(con);
                con_out_kvec_reset(con);
                ret = prepare_write_connect(con);
@@ -2198,7 +2195,7 @@ static int process_connect(struct ceph_connection *con)
                        pr_err("%s%lld %s protocol feature mismatch,"
                               " my required %llx > server's %llx, need %llx\n",
                               ENTITY_NAME(con->peer_name),
-                              ceph_pr_addr(&con->peer_addr.in_addr),
+                              ceph_pr_addr(&con->peer_addr),
                               req_feat, server_feat, req_feat & ~server_feat);
                        con->error_msg = "missing required protocol features";
                        reset_connection(con);
@@ -2405,7 +2402,7 @@ static int read_partial_message(struct ceph_connection *con)
        if ((s64)seq - (s64)con->in_seq < 1) {
                pr_info("skipping %s%lld %s seq %lld expected %lld\n",
                        ENTITY_NAME(con->peer_name),
-                       ceph_pr_addr(&con->peer_addr.in_addr),
+                       ceph_pr_addr(&con->peer_addr),
                        seq, con->in_seq + 1);
                con->in_base_pos = -front_len - middle_len - data_len -
                        sizeof_footer(con);
@@ -2984,10 +2981,10 @@ static void ceph_con_workfn(struct work_struct *work)
 static void con_fault(struct ceph_connection *con)
 {
        dout("fault %p state %lu to peer %s\n",
-            con, con->state, ceph_pr_addr(&con->peer_addr.in_addr));
+            con, con->state, ceph_pr_addr(&con->peer_addr));
 
        pr_warn("%s%lld %s %s\n", ENTITY_NAME(con->peer_name),
-               ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg);
+               ceph_pr_addr(&con->peer_addr), con->error_msg);
        con->error_msg = NULL;
 
        WARN_ON(con->state != CON_STATE_CONNECTING &&
index a53e4fb..895679d 100644 (file)
@@ -76,7 +76,7 @@ struct ceph_monmap *ceph_monmap_decode(void *p, void *end)
             m->num_mon);
        for (i = 0; i < m->num_mon; i++)
                dout("monmap_decode  mon%d is %s\n", i,
-                    ceph_pr_addr(&m->mon_inst[i].addr.in_addr));
+                    ceph_pr_addr(&m->mon_inst[i].addr));
        return m;
 
 bad:
@@ -203,7 +203,7 @@ static void reopen_session(struct ceph_mon_client *monc)
 {
        if (!monc->hunting)
                pr_info("mon%d %s session lost, hunting for new mon\n",
-                   monc->cur_mon, ceph_pr_addr(&monc->con.peer_addr.in_addr));
+                   monc->cur_mon, ceph_pr_addr(&monc->con.peer_addr));
 
        __close_session(monc);
        __open_session(monc);
@@ -1178,7 +1178,7 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
                __resend_generic_request(monc);
 
                pr_info("mon%d %s session established\n", monc->cur_mon,
-                       ceph_pr_addr(&monc->con.peer_addr.in_addr));
+                       ceph_pr_addr(&monc->con.peer_addr));
        }
 
 out:
index 6f739de..9a8eca5 100644 (file)
@@ -4926,7 +4926,7 @@ static int decode_watcher(void **p, void *end, struct ceph_watch_item *item)
 
        dout("%s %s%llu cookie %llu addr %s\n", __func__,
             ENTITY_NAME(item->name), item->cookie,
-            ceph_pr_addr(&item->addr.in_addr));
+            ceph_pr_addr(&item->addr));
        return 0;
 }
 
index d3736f5..74cafc0 100644 (file)
@@ -27,7 +27,7 @@ struct page **ceph_get_direct_page_vector(const void __user *data,
        while (got < num_pages) {
                rc = get_user_pages_fast(
                    (unsigned long)data + ((unsigned long)got * PAGE_SIZE),
-                   num_pages - got, write_page, pages + got);
+                   num_pages - got, write_page ? FOLL_WRITE : 0, pages + got);
                if (rc < 0)
                        break;
                BUG_ON(rc == 0);
index 9ca784c..548f39d 100644 (file)
@@ -734,7 +734,9 @@ bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx,
        flow_keys->nhoff = nhoff;
        flow_keys->thoff = flow_keys->nhoff;
 
+       preempt_disable();
        result = BPF_PROG_RUN(prog, ctx);
+       preempt_enable();
 
        flow_keys->nhoff = clamp_t(u16, flow_keys->nhoff, nhoff, hlen);
        flow_keys->thoff = clamp_t(u16, flow_keys->thoff,
index 0e2f71a..5dd85ec 100644 (file)
@@ -263,7 +263,6 @@ int dccp_disconnect(struct sock *sk, int flags)
        struct inet_connection_sock *icsk = inet_csk(sk);
        struct inet_sock *inet = inet_sk(sk);
        struct dccp_sock *dp = dccp_sk(sk);
-       int err = 0;
        const int old_state = sk->sk_state;
 
        if (old_state != DCCP_CLOSED)
@@ -307,7 +306,7 @@ int dccp_disconnect(struct sock *sk, int flags)
        WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);
 
        sk->sk_error_report(sk);
-       return err;
+       return 0;
 }
 
 EXPORT_SYMBOL_GPL(dccp_disconnect);
index 19aa32f..2d26043 100644 (file)
@@ -54,6 +54,7 @@
  * @options: Request options (or NULL if no options)
  * @_result: Where to place the returned data (or NULL)
  * @_expiry: Where to store the result expiry time (or NULL)
+ * @invalidate: Always invalidate the key after use
  *
  * The data will be returned in the pointer at *result, if provided, and the
  * caller is responsible for freeing it.
@@ -69,7 +70,8 @@
  * Returns the size of the result on success, -ve error code otherwise.
  */
 int dns_query(const char *type, const char *name, size_t namelen,
-             const char *options, char **_result, time64_t *_expiry)
+             const char *options, char **_result, time64_t *_expiry,
+             bool invalidate)
 {
        struct key *rkey;
        struct user_key_payload *upayload;
@@ -157,6 +159,8 @@ int dns_query(const char *type, const char *name, size_t namelen,
        ret = len;
 put:
        up_read(&rkey->sem);
+       if (invalidate)
+               key_invalidate(rkey);
        key_put(rkey);
 out:
        kleave(" = %d", ret);
index fe7b6a6..9892ca1 100644 (file)
@@ -463,6 +463,8 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
        s->tx_bytes += skb->len;
        u64_stats_update_end(&s->syncp);
 
+       DSA_SKB_CB(skb)->deferred_xmit = false;
+
        /* Identify PTP protocol packets, clone them, and pass them to the
         * switch driver
         */
index d52db5f..9c31141 100644 (file)
@@ -206,10 +206,10 @@ static const struct dsa_device_ops brcm_prepend_netdev_ops = {
        .rcv    = brcm_tag_rcv_prepend,
        .overhead = BRCM_TAG_LEN,
 };
-#endif
 
 DSA_TAG_DRIVER(brcm_prepend_netdev_ops);
 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_PREPEND);
+#endif
 
 static struct dsa_tag_driver *dsa_tag_driver_array[] = {
 #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM)
index 71f0690..b96fd3f 100644 (file)
@@ -163,7 +163,7 @@ nf_hook_entries_grow(const struct nf_hook_entries *old,
 
 static void hooks_validate(const struct nf_hook_entries *hooks)
 {
-#ifdef CONFIG_DEBUG_KERNEL
+#ifdef CONFIG_DEBUG_MISC
        struct nf_hook_ops **orig_ops;
        int prio = INT_MIN;
        size_t i = 0;
index 1601275..4c2ef42 100644 (file)
@@ -172,7 +172,7 @@ static int nf_h323_error_boundary(struct bitstr *bs, size_t bytes, size_t bits)
        if (bits % BITS_PER_BYTE > 0)
                bytes++;
 
-       if (*bs->cur + bytes > *bs->end)
+       if (bs->cur + bytes > bs->end)
                return 1;
 
        return 0;
index 005589c..12de403 100644 (file)
@@ -748,24 +748,19 @@ static int callforward_do_filter(struct net *net,
                }
                break;
        }
-#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6)
+#if IS_ENABLED(CONFIG_IPV6)
        case AF_INET6: {
-               const struct nf_ipv6_ops *v6ops;
                struct rt6_info *rt1, *rt2;
                struct flowi6 fl1, fl2;
 
-               v6ops = nf_get_ipv6_ops();
-               if (!v6ops)
-                       return 0;
-
                memset(&fl1, 0, sizeof(fl1));
                fl1.daddr = src->in6;
 
                memset(&fl2, 0, sizeof(fl2));
                fl2.daddr = dst->in6;
-               if (!v6ops->route(net, (struct dst_entry **)&rt1,
+               if (!nf_ip6_route(net, (struct dst_entry **)&rt1,
                                  flowi6_to_flowi(&fl1), false)) {
-                       if (!v6ops->route(net, (struct dst_entry **)&rt2,
+                       if (!nf_ip6_route(net, (struct dst_entry **)&rt2,
                                          flowi6_to_flowi(&fl2), false)) {
                                if (ipv6_addr_equal(rt6_nexthop(rt1, &fl1.daddr),
                                                    rt6_nexthop(rt2, &fl2.daddr)) &&
index 8dcc064..7db79c1 100644 (file)
@@ -1256,7 +1256,7 @@ static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl,
        struct nf_conntrack_tuple tuple;
        struct nf_conn *ct;
        struct nfgenmsg *nfmsg = nlmsg_data(nlh);
-       u_int8_t u3 = nfmsg->nfgen_family;
+       u_int8_t u3 = nfmsg->version ? nfmsg->nfgen_family : AF_UNSPEC;
        struct nf_conntrack_zone zone;
        int err;
 
index 7aabfd4..4469519 100644 (file)
@@ -185,14 +185,25 @@ static const struct rhashtable_params nf_flow_offload_rhash_params = {
 
 int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
 {
-       flow->timeout = (u32)jiffies;
+       int err;
 
-       rhashtable_insert_fast(&flow_table->rhashtable,
-                              &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node,
-                              nf_flow_offload_rhash_params);
-       rhashtable_insert_fast(&flow_table->rhashtable,
-                              &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node,
-                              nf_flow_offload_rhash_params);
+       err = rhashtable_insert_fast(&flow_table->rhashtable,
+                                    &flow->tuplehash[0].node,
+                                    nf_flow_offload_rhash_params);
+       if (err < 0)
+               return err;
+
+       err = rhashtable_insert_fast(&flow_table->rhashtable,
+                                    &flow->tuplehash[1].node,
+                                    nf_flow_offload_rhash_params);
+       if (err < 0) {
+               rhashtable_remove_fast(&flow_table->rhashtable,
+                                      &flow->tuplehash[0].node,
+                                      nf_flow_offload_rhash_params);
+               return err;
+       }
+
+       flow->timeout = (u32)jiffies;
        return 0;
 }
 EXPORT_SYMBOL_GPL(flow_offload_add);
@@ -232,6 +243,7 @@ flow_offload_lookup(struct nf_flowtable *flow_table,
 {
        struct flow_offload_tuple_rhash *tuplehash;
        struct flow_offload *flow;
+       struct flow_offload_entry *e;
        int dir;
 
        tuplehash = rhashtable_lookup(&flow_table->rhashtable, tuple,
@@ -244,6 +256,10 @@ flow_offload_lookup(struct nf_flowtable *flow_table,
        if (flow->flags & (FLOW_OFFLOAD_DYING | FLOW_OFFLOAD_TEARDOWN))
                return NULL;
 
+       e = container_of(flow, struct flow_offload_entry, flow);
+       if (unlikely(nf_ct_is_dying(e->ct)))
+               return NULL;
+
        return tuplehash;
 }
 EXPORT_SYMBOL_GPL(flow_offload_lookup);
@@ -290,8 +306,10 @@ static inline bool nf_flow_has_expired(const struct flow_offload *flow)
 static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data)
 {
        struct nf_flowtable *flow_table = data;
+       struct flow_offload_entry *e;
 
-       if (nf_flow_has_expired(flow) ||
+       e = container_of(flow, struct flow_offload_entry, flow);
+       if (nf_flow_has_expired(flow) || nf_ct_is_dying(e->ct) ||
            (flow->flags & (FLOW_OFFLOAD_DYING | FLOW_OFFLOAD_TEARDOWN)))
                flow_offload_del(flow_table, flow);
 }
index 6452550..0d603e2 100644 (file)
@@ -181,6 +181,9 @@ static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev,
            iph->protocol != IPPROTO_UDP)
                return -1;
 
+       if (iph->ttl <= 1)
+               return -1;
+
        thoff = iph->ihl * 4;
        if (!pskb_may_pull(skb, thoff + sizeof(*ports)))
                return -1;
@@ -408,6 +411,9 @@ static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev,
            ip6h->nexthdr != IPPROTO_UDP)
                return -1;
 
+       if (ip6h->hop_limit <= 1)
+               return -1;
+
        thoff = sizeof(*ip6h);
        if (!pskb_may_pull(skb, thoff + sizeof(*ports)))
                return -1;
index d98416e..28241e8 100644 (file)
@@ -213,33 +213,33 @@ static int nft_deltable(struct nft_ctx *ctx)
        return err;
 }
 
-static int nft_trans_chain_add(struct nft_ctx *ctx, int msg_type)
+static struct nft_trans *nft_trans_chain_add(struct nft_ctx *ctx, int msg_type)
 {
        struct nft_trans *trans;
 
        trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_chain));
        if (trans == NULL)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        if (msg_type == NFT_MSG_NEWCHAIN)
                nft_activate_next(ctx->net, ctx->chain);
 
        list_add_tail(&trans->list, &ctx->net->nft.commit_list);
-       return 0;
+       return trans;
 }
 
 static int nft_delchain(struct nft_ctx *ctx)
 {
-       int err;
+       struct nft_trans *trans;
 
-       err = nft_trans_chain_add(ctx, NFT_MSG_DELCHAIN);
-       if (err < 0)
-               return err;
+       trans = nft_trans_chain_add(ctx, NFT_MSG_DELCHAIN);
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
 
        ctx->table->use--;
        nft_deactivate_next(ctx->net, ctx->chain);
 
-       return err;
+       return 0;
 }
 
 static void nft_rule_expr_activate(const struct nft_ctx *ctx,
@@ -1189,6 +1189,9 @@ static int nft_dump_stats(struct sk_buff *skb, struct nft_stats __percpu *stats)
        u64 pkts, bytes;
        int cpu;
 
+       if (!stats)
+               return 0;
+
        memset(&total, 0, sizeof(total));
        for_each_possible_cpu(cpu) {
                cpu_stats = per_cpu_ptr(stats, cpu);
@@ -1246,6 +1249,7 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
        if (nft_is_base_chain(chain)) {
                const struct nft_base_chain *basechain = nft_base_chain(chain);
                const struct nf_hook_ops *ops = &basechain->ops;
+               struct nft_stats __percpu *stats;
                struct nlattr *nest;
 
                nest = nla_nest_start_noflag(skb, NFTA_CHAIN_HOOK);
@@ -1267,8 +1271,9 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
                if (nla_put_string(skb, NFTA_CHAIN_TYPE, basechain->type->name))
                        goto nla_put_failure;
 
-               if (rcu_access_pointer(basechain->stats) &&
-                   nft_dump_stats(skb, rcu_dereference(basechain->stats)))
+               stats = rcu_dereference_check(basechain->stats,
+                                             lockdep_commit_lock_is_held(net));
+               if (nft_dump_stats(skb, stats))
                        goto nla_put_failure;
        }
 
@@ -1615,6 +1620,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
        struct nft_base_chain *basechain;
        struct nft_stats __percpu *stats;
        struct net *net = ctx->net;
+       struct nft_trans *trans;
        struct nft_chain *chain;
        struct nft_rule **rules;
        int err;
@@ -1662,7 +1668,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
                ops->dev        = hook.dev;
 
                chain->flags |= NFT_BASE_CHAIN;
-               basechain->policy = policy;
+               basechain->policy = NF_ACCEPT;
        } else {
                chain = kzalloc(sizeof(*chain), GFP_KERNEL);
                if (chain == NULL)
@@ -1698,13 +1704,18 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
        if (err)
                goto err2;
 
-       err = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN);
-       if (err < 0) {
+       trans = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN);
+       if (IS_ERR(trans)) {
+               err = PTR_ERR(trans);
                rhltable_remove(&table->chains_ht, &chain->rhlhead,
                                nft_chain_ht_params);
                goto err2;
        }
 
+       nft_trans_chain_policy(trans) = -1;
+       if (nft_is_base_chain(chain))
+               nft_trans_chain_policy(trans) = policy;
+
        table->use++;
        list_add_tail_rcu(&chain->list, &table->chains);
 
@@ -6310,6 +6321,27 @@ static int nf_tables_validate(struct net *net)
        return 0;
 }
 
+/* a drop policy has to be deferred until all rules have been activated,
+ * otherwise a large ruleset that contains a drop-policy base chain will
+ * cause all packets to get dropped until the full transaction has been
+ * processed.
+ *
+ * We defer the drop policy until the transaction has been finalized.
+ */
+static void nft_chain_commit_drop_policy(struct nft_trans *trans)
+{
+       struct nft_base_chain *basechain;
+
+       if (nft_trans_chain_policy(trans) != NF_DROP)
+               return;
+
+       if (!nft_is_base_chain(trans->ctx.chain))
+               return;
+
+       basechain = nft_base_chain(trans->ctx.chain);
+       basechain->policy = NF_DROP;
+}
+
 static void nft_chain_commit_update(struct nft_trans *trans)
 {
        struct nft_base_chain *basechain;
@@ -6631,6 +6663,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
                                nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN);
                                /* trans destroyed after rcu grace period */
                        } else {
+                               nft_chain_commit_drop_policy(trans);
                                nft_clear(net, trans->ctx.chain);
                                nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN);
                                nft_trans_destroy(trans);
index 6e6b9ad..69d7a84 100644 (file)
@@ -94,8 +94,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
        if (help)
                goto out;
 
-       if (ctinfo == IP_CT_NEW ||
-           ctinfo == IP_CT_RELATED)
+       if (!nf_ct_is_confirmed(ct))
                goto out;
 
        if (test_and_set_bit(IPS_OFFLOAD_BIT, &ct->status))
@@ -113,6 +112,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
        if (ret < 0)
                goto err_flow_add;
 
+       dst_release(route.tuple[!dir].dst);
        return;
 
 err_flow_add:
index dd0e97f..801872a 100644 (file)
@@ -728,12 +728,13 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
        DECLARE_SOCKADDR(struct sockaddr_qrtr *, addr, msg->msg_name);
        int (*enqueue_fn)(struct qrtr_node *, struct sk_buff *, int,
                          struct sockaddr_qrtr *, struct sockaddr_qrtr *);
+       __le32 qrtr_type = cpu_to_le32(QRTR_TYPE_DATA);
        struct qrtr_sock *ipc = qrtr_sk(sock->sk);
        struct sock *sk = sock->sk;
        struct qrtr_node *node;
        struct sk_buff *skb;
+       u32 type = 0;
        size_t plen;
-       u32 type = QRTR_TYPE_DATA;
        int rc;
 
        if (msg->msg_flags & ~(MSG_DONTWAIT))
@@ -807,8 +808,8 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
                }
 
                /* control messages already require the type as 'command' */
-               skb_copy_bits(skb, 0, &type, 4);
-               type = le32_to_cpu(type);
+               skb_copy_bits(skb, 0, &qrtr_type, 4);
+               type = le32_to_cpu(qrtr_type);
        }
 
        rc = enqueue_fn(node, skb, type, &ipc->us, addr);
index e367a97..03f6fd5 100644 (file)
@@ -193,7 +193,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval,
                ret = -ENOMEM;
                goto out;
        }
-       ret = get_user_pages_fast(start, nr_pages, 1, pages);
+       ret = get_user_pages_fast(start, nr_pages, FOLL_WRITE, pages);
        if (ret != nr_pages) {
                if (ret > 0)
                        nr_pages = ret;
index 182ab84..b340ed4 100644 (file)
@@ -158,7 +158,8 @@ static int rds_pin_pages(unsigned long user_addr, unsigned int nr_pages,
 {
        int ret;
 
-       ret = get_user_pages_fast(user_addr, nr_pages, write, pages);
+       ret = get_user_pages_fast(user_addr, nr_pages, write ? FOLL_WRITE : 0,
+                                 pages);
 
        if (ret >= 0 && ret < nr_pages) {
                while (ret--)
index ae8c5d7..ffde5b1 100644 (file)
@@ -270,6 +270,7 @@ static int rxrpc_listen(struct socket *sock, int backlog)
  * @gfp: The allocation constraints
  * @notify_rx: Where to send notifications instead of socket queue
  * @upgrade: Request service upgrade for call
+ * @intr: The call is interruptible
  * @debug_id: The debug ID for tracing to be assigned to the call
  *
  * Allow a kernel service to begin a call on the nominated socket.  This just
@@ -287,6 +288,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
                                           gfp_t gfp,
                                           rxrpc_notify_rx_t notify_rx,
                                           bool upgrade,
+                                          bool intr,
                                           unsigned int debug_id)
 {
        struct rxrpc_conn_parameters cp;
@@ -311,6 +313,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
        memset(&p, 0, sizeof(p));
        p.user_call_ID = user_call_ID;
        p.tx_total_len = tx_total_len;
+       p.intr = intr;
 
        memset(&cp, 0, sizeof(cp));
        cp.local                = rx->local;
@@ -443,6 +446,31 @@ void rxrpc_kernel_new_call_notification(
 }
 EXPORT_SYMBOL(rxrpc_kernel_new_call_notification);
 
+/**
+ * rxrpc_kernel_set_max_life - Set maximum lifespan on a call
+ * @sock: The socket the call is on
+ * @call: The call to configure
+ * @hard_timeout: The maximum lifespan of the call in jiffies
+ *
+ * Set the maximum lifespan of a call.  The call will end with ETIME or
+ * ETIMEDOUT if it takes longer than this.
+ */
+void rxrpc_kernel_set_max_life(struct socket *sock, struct rxrpc_call *call,
+                              unsigned long hard_timeout)
+{
+       unsigned long now;
+
+       mutex_lock(&call->user_mutex);
+
+       now = jiffies;
+       hard_timeout += now;
+       WRITE_ONCE(call->expect_term_by, hard_timeout);
+       rxrpc_reduce_call_timer(call, hard_timeout, now, rxrpc_timer_set_for_hard);
+
+       mutex_unlock(&call->user_mutex);
+}
+EXPORT_SYMBOL(rxrpc_kernel_set_max_life);
+
 /*
  * connect an RxRPC socket
  * - this just targets it at a specific destination; no actual connection
index 062ca9d..07fc1df 100644 (file)
@@ -482,6 +482,7 @@ enum rxrpc_call_flag {
        RXRPC_CALL_BEGAN_RX_TIMER,      /* We began the expect_rx_by timer */
        RXRPC_CALL_RX_HEARD,            /* The peer responded at least once to this call */
        RXRPC_CALL_RX_UNDERRUN,         /* Got data underrun */
+       RXRPC_CALL_IS_INTR,             /* The call is interruptible */
 };
 
 /*
@@ -711,6 +712,7 @@ struct rxrpc_call_params {
                u32             normal;         /* Max time since last call packet (msec) */
        } timeouts;
        u8                      nr_timeouts;    /* Number of timeouts specified */
+       bool                    intr;           /* The call is interruptible */
 };
 
 struct rxrpc_send_params {
index fe96881..d0ca98d 100644 (file)
@@ -241,6 +241,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
                return call;
        }
 
+       if (p->intr)
+               __set_bit(RXRPC_CALL_IS_INTR, &call->flags);
        call->tx_total_len = p->tx_total_len;
        trace_rxrpc_call(call, rxrpc_call_new_client, atomic_read(&call->usage),
                         here, (const void *)p->user_call_ID);
index 83797b3..5cf5595 100644 (file)
@@ -656,10 +656,14 @@ static int rxrpc_wait_for_channel(struct rxrpc_call *call, gfp_t gfp)
 
                add_wait_queue_exclusive(&call->waitq, &myself);
                for (;;) {
-                       set_current_state(TASK_INTERRUPTIBLE);
+                       if (test_bit(RXRPC_CALL_IS_INTR, &call->flags))
+                               set_current_state(TASK_INTERRUPTIBLE);
+                       else
+                               set_current_state(TASK_UNINTERRUPTIBLE);
                        if (call->call_id)
                                break;
-                       if (signal_pending(current)) {
+                       if (test_bit(RXRPC_CALL_IS_INTR, &call->flags) &&
+                           signal_pending(current)) {
                                ret = -ERESTARTSYS;
                                break;
                        }
index bec64de..45a05d9 100644 (file)
@@ -80,7 +80,8 @@ static int rxrpc_wait_for_tx_window_nonintr(struct rxrpc_sock *rx,
                if (call->state >= RXRPC_CALL_COMPLETE)
                        return call->error;
 
-               if (timeout == 0 &&
+               if (test_bit(RXRPC_CALL_IS_INTR, &call->flags) &&
+                   timeout == 0 &&
                    tx_win == tx_start && signal_pending(current))
                        return -EINTR;
 
@@ -620,6 +621,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
                .call.tx_total_len      = -1,
                .call.user_call_ID      = 0,
                .call.nr_timeouts       = 0,
+               .call.intr              = true,
                .abort_code             = 0,
                .command                = RXRPC_CMD_SEND_DATA,
                .exclusive              = false,
index 0c5d789..8be2f20 100644 (file)
@@ -474,12 +474,12 @@ static int rsc_parse(struct cache_detail *cd,
                 * treatment so are checked for validity here.)
                 */
                /* uid */
-               rsci.cred.cr_uid = make_kuid(&init_user_ns, id);
+               rsci.cred.cr_uid = make_kuid(current_user_ns(), id);
 
                /* gid */
                if (get_int(&mesg, &id))
                        goto out;
-               rsci.cred.cr_gid = make_kgid(&init_user_ns, id);
+               rsci.cred.cr_gid = make_kgid(current_user_ns(), id);
 
                /* number of additional gid's */
                if (get_int(&mesg, &N))
@@ -497,7 +497,7 @@ static int rsc_parse(struct cache_detail *cd,
                        kgid_t kgid;
                        if (get_int(&mesg, &id))
                                goto out;
-                       kgid = make_kgid(&init_user_ns, id);
+                       kgid = make_kgid(current_user_ns(), id);
                        if (!gid_valid(kgid))
                                goto out;
                        rsci.cred.cr_group_info->gid[i] = kgid;
index 261131d..d223289 100644 (file)
@@ -40,6 +40,7 @@
 
 static bool cache_defer_req(struct cache_req *req, struct cache_head *item);
 static void cache_revisit_request(struct cache_head *item);
+static bool cache_listeners_exist(struct cache_detail *detail);
 
 static void cache_init(struct cache_head *h, struct cache_detail *detail)
 {
@@ -306,7 +307,8 @@ int cache_check(struct cache_detail *detail,
                                cache_fresh_unlocked(h, detail);
                                break;
                        }
-               }
+               } else if (!cache_listeners_exist(detail))
+                       rv = try_to_negate_entry(detail, h);
        }
 
        if (rv == -EAGAIN) {
index dbd1969..2be8278 100644 (file)
@@ -993,6 +993,58 @@ static int __svc_register(struct net *net, const char *progname,
        return error;
 }
 
+int svc_rpcbind_set_version(struct net *net,
+                           const struct svc_program *progp,
+                           u32 version, int family,
+                           unsigned short proto,
+                           unsigned short port)
+{
+       dprintk("svc: svc_register(%sv%d, %s, %u, %u)\n",
+               progp->pg_name, version,
+               proto == IPPROTO_UDP?  "udp" : "tcp",
+               port, family);
+
+       return __svc_register(net, progp->pg_name, progp->pg_prog,
+                               version, family, proto, port);
+
+}
+EXPORT_SYMBOL_GPL(svc_rpcbind_set_version);
+
+int svc_generic_rpcbind_set(struct net *net,
+                           const struct svc_program *progp,
+                           u32 version, int family,
+                           unsigned short proto,
+                           unsigned short port)
+{
+       const struct svc_version *vers = progp->pg_vers[version];
+       int error;
+
+       if (vers == NULL)
+               return 0;
+
+       if (vers->vs_hidden) {
+               dprintk("svc: svc_register(%sv%d, %s, %u, %u)"
+                       " (but not telling portmap)\n",
+                       progp->pg_name, version,
+                       proto == IPPROTO_UDP?  "udp" : "tcp",
+                       port, family);
+               return 0;
+       }
+
+       /*
+        * Don't register a UDP port if we need congestion
+        * control.
+        */
+       if (vers->vs_need_cong_ctrl && proto == IPPROTO_UDP)
+               return 0;
+
+       error = svc_rpcbind_set_version(net, progp, version,
+                                       family, proto, port);
+
+       return (vers->vs_rpcb_optnl) ? 0 : error;
+}
+EXPORT_SYMBOL_GPL(svc_generic_rpcbind_set);
+
 /**
  * svc_register - register an RPC service with the local portmapper
  * @serv: svc_serv struct for the service to register
@@ -1008,7 +1060,6 @@ int svc_register(const struct svc_serv *serv, struct net *net,
                 const unsigned short port)
 {
        struct svc_program      *progp;
-       const struct svc_version *vers;
        unsigned int            i;
        int                     error = 0;
 
@@ -1018,37 +1069,9 @@ int svc_register(const struct svc_serv *serv, struct net *net,
 
        for (progp = serv->sv_program; progp; progp = progp->pg_next) {
                for (i = 0; i < progp->pg_nvers; i++) {
-                       vers = progp->pg_vers[i];
-                       if (vers == NULL)
-                               continue;
-
-                       dprintk("svc: svc_register(%sv%d, %s, %u, %u)%s\n",
-                                       progp->pg_name,
-                                       i,
-                                       proto == IPPROTO_UDP?  "udp" : "tcp",
-                                       port,
-                                       family,
-                                       vers->vs_hidden ?
-                                       " (but not telling portmap)" : "");
-
-                       if (vers->vs_hidden)
-                               continue;
-
-                       /*
-                        * Don't register a UDP port if we need congestion
-                        * control.
-                        */
-                       if (vers->vs_need_cong_ctrl && proto == IPPROTO_UDP)
-                               continue;
-
-                       error = __svc_register(net, progp->pg_name, progp->pg_prog,
-                                               i, family, proto, port);
-
-                       if (vers->vs_rpcb_optnl) {
-                               error = 0;
-                               continue;
-                       }
 
+                       error = progp->pg_rpcbind_set(net, progp, i,
+                                       family, proto, port);
                        if (error < 0) {
                                printk(KERN_WARNING "svc: failed to register "
                                        "%sv%u RPC service (errno %d).\n",
@@ -1144,6 +1167,114 @@ void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
 static __printf(2,3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) {}
 #endif
 
+__be32
+svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err)
+{
+       set_bit(RQ_AUTHERR, &rqstp->rq_flags);
+       return auth_err;
+}
+EXPORT_SYMBOL_GPL(svc_return_autherr);
+
+static __be32
+svc_get_autherr(struct svc_rqst *rqstp, __be32 *statp)
+{
+       if (test_and_clear_bit(RQ_AUTHERR, &rqstp->rq_flags))
+               return *statp;
+       return rpc_auth_ok;
+}
+
+static int
+svc_generic_dispatch(struct svc_rqst *rqstp, __be32 *statp)
+{
+       struct kvec *argv = &rqstp->rq_arg.head[0];
+       struct kvec *resv = &rqstp->rq_res.head[0];
+       const struct svc_procedure *procp = rqstp->rq_procinfo;
+
+       /*
+        * Decode arguments
+        * XXX: why do we ignore the return value?
+        */
+       if (procp->pc_decode &&
+           !procp->pc_decode(rqstp, argv->iov_base)) {
+               *statp = rpc_garbage_args;
+               return 1;
+       }
+
+       *statp = procp->pc_func(rqstp);
+
+       if (*statp == rpc_drop_reply ||
+           test_bit(RQ_DROPME, &rqstp->rq_flags))
+               return 0;
+
+       if (test_bit(RQ_AUTHERR, &rqstp->rq_flags))
+               return 1;
+
+       if (*statp != rpc_success)
+               return 1;
+
+       /* Encode reply */
+       if (procp->pc_encode &&
+           !procp->pc_encode(rqstp, resv->iov_base + resv->iov_len)) {
+               dprintk("svc: failed to encode reply\n");
+               /* serv->sv_stats->rpcsystemerr++; */
+               *statp = rpc_system_err;
+       }
+       return 1;
+}
+
+__be32
+svc_generic_init_request(struct svc_rqst *rqstp,
+               const struct svc_program *progp,
+               struct svc_process_info *ret)
+{
+       const struct svc_version *versp = NULL; /* compiler food */
+       const struct svc_procedure *procp = NULL;
+
+       if (rqstp->rq_vers >= progp->pg_nvers )
+               goto err_bad_vers;
+         versp = progp->pg_vers[rqstp->rq_vers];
+         if (!versp)
+               goto err_bad_vers;
+
+       /*
+        * Some protocol versions (namely NFSv4) require some form of
+        * congestion control.  (See RFC 7530 section 3.1 paragraph 2)
+        * In other words, UDP is not allowed. We mark those when setting
+        * up the svc_xprt, and verify that here.
+        *
+        * The spec is not very clear about what error should be returned
+        * when someone tries to access a server that is listening on UDP
+        * for lower versions. RPC_PROG_MISMATCH seems to be the closest
+        * fit.
+        */
+       if (versp->vs_need_cong_ctrl && rqstp->rq_xprt &&
+           !test_bit(XPT_CONG_CTRL, &rqstp->rq_xprt->xpt_flags))
+               goto err_bad_vers;
+
+       if (rqstp->rq_proc >= versp->vs_nproc)
+               goto err_bad_proc;
+       rqstp->rq_procinfo = procp = &versp->vs_proc[rqstp->rq_proc];
+       if (!procp)
+               goto err_bad_proc;
+
+       /* Initialize storage for argp and resp */
+       memset(rqstp->rq_argp, 0, procp->pc_argsize);
+       memset(rqstp->rq_resp, 0, procp->pc_ressize);
+
+       /* Bump per-procedure stats counter */
+       versp->vs_count[rqstp->rq_proc]++;
+
+       ret->dispatch = versp->vs_dispatch;
+       return rpc_success;
+err_bad_vers:
+       ret->mismatch.lovers = progp->pg_lovers;
+       ret->mismatch.hivers = progp->pg_hivers;
+       return rpc_prog_mismatch;
+err_bad_proc:
+       return rpc_proc_unavail;
+}
+EXPORT_SYMBOL_GPL(svc_generic_init_request);
+
 /*
  * Common routine for processing the RPC request.
  */
@@ -1151,11 +1282,11 @@ static int
 svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
 {
        struct svc_program      *progp;
-       const struct svc_version *versp = NULL; /* compiler food */
        const struct svc_procedure *procp = NULL;
        struct svc_serv         *serv = rqstp->rq_server;
+       struct svc_process_info process;
        __be32                  *statp;
-       u32                     prog, vers, proc;
+       u32                     prog, vers;
        __be32                  auth_stat, rpc_stat;
        int                     auth_res;
        __be32                  *reply_statp;
@@ -1187,8 +1318,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
        svc_putnl(resv, 0);             /* ACCEPT */
 
        rqstp->rq_prog = prog = svc_getnl(argv);        /* program number */
-       rqstp->rq_vers = vers = svc_getnl(argv);        /* version number */
-       rqstp->rq_proc = proc = svc_getnl(argv);        /* procedure number */
+       rqstp->rq_vers = svc_getnl(argv);       /* version number */
+       rqstp->rq_proc = svc_getnl(argv);       /* procedure number */
 
        for (progp = serv->sv_program; progp; progp = progp->pg_next)
                if (prog == progp->pg_prog)
@@ -1226,29 +1357,22 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
        if (progp == NULL)
                goto err_bad_prog;
 
-       if (vers >= progp->pg_nvers ||
-         !(versp = progp->pg_vers[vers]))
-               goto err_bad_vers;
-
-       /*
-        * Some protocol versions (namely NFSv4) require some form of
-        * congestion control.  (See RFC 7530 section 3.1 paragraph 2)
-        * In other words, UDP is not allowed. We mark those when setting
-        * up the svc_xprt, and verify that here.
-        *
-        * The spec is not very clear about what error should be returned
-        * when someone tries to access a server that is listening on UDP
-        * for lower versions. RPC_PROG_MISMATCH seems to be the closest
-        * fit.
-        */
-       if (versp->vs_need_cong_ctrl && rqstp->rq_xprt &&
-           !test_bit(XPT_CONG_CTRL, &rqstp->rq_xprt->xpt_flags))
+       rpc_stat = progp->pg_init_request(rqstp, progp, &process);
+       switch (rpc_stat) {
+       case rpc_success:
+               break;
+       case rpc_prog_unavail:
+               goto err_bad_prog;
+       case rpc_prog_mismatch:
                goto err_bad_vers;
+       case rpc_proc_unavail:
+               goto err_bad_proc;
+       }
 
-       procp = versp->vs_proc + proc;
-       if (proc >= versp->vs_nproc || !procp->pc_func)
+       procp = rqstp->rq_procinfo;
+       /* Should this check go into the dispatcher? */
+       if (!procp || !procp->pc_func)
                goto err_bad_proc;
-       rqstp->rq_procinfo = procp;
 
        /* Syntactic check complete */
        serv->sv_stats->rpccnt++;
@@ -1258,13 +1382,6 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
        statp = resv->iov_base +resv->iov_len;
        svc_putnl(resv, RPC_SUCCESS);
 
-       /* Bump per-procedure stats counter */
-       versp->vs_count[proc]++;
-
-       /* Initialize storage for argp and resp */
-       memset(rqstp->rq_argp, 0, procp->pc_argsize);
-       memset(rqstp->rq_resp, 0, procp->pc_ressize);
-
        /* un-reserve some of the out-queue now that we have a
         * better idea of reply size
         */
@@ -1272,43 +1389,18 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
                svc_reserve_auth(rqstp, procp->pc_xdrressize<<2);
 
        /* Call the function that processes the request. */
-       if (!versp->vs_dispatch) {
-               /*
-                * Decode arguments
-                * XXX: why do we ignore the return value?
-                */
-               if (procp->pc_decode &&
-                   !procp->pc_decode(rqstp, argv->iov_base))
+       if (!process.dispatch) {
+               if (!svc_generic_dispatch(rqstp, statp))
+                       goto release_dropit;
+               if (*statp == rpc_garbage_args)
                        goto err_garbage;
-
-               *statp = procp->pc_func(rqstp);
-
-               /* Encode reply */
-               if (*statp == rpc_drop_reply ||
-                   test_bit(RQ_DROPME, &rqstp->rq_flags)) {
-                       if (procp->pc_release)
-                               procp->pc_release(rqstp);
-                       goto dropit;
-               }
-               if (*statp == rpc_autherr_badcred) {
-                       if (procp->pc_release)
-                               procp->pc_release(rqstp);
-                       goto err_bad_auth;
-               }
-               if (*statp == rpc_success && procp->pc_encode &&
-                   !procp->pc_encode(rqstp, resv->iov_base + resv->iov_len)) {
-                       dprintk("svc: failed to encode reply\n");
-                       /* serv->sv_stats->rpcsystemerr++; */
-                       *statp = rpc_system_err;
-               }
+               auth_stat = svc_get_autherr(rqstp, statp);
+               if (auth_stat != rpc_auth_ok)
+                       goto err_release_bad_auth;
        } else {
                dprintk("svc: calling dispatcher\n");
-               if (!versp->vs_dispatch(rqstp, statp)) {
-                       /* Release reply info */
-                       if (procp->pc_release)
-                               procp->pc_release(rqstp);
-                       goto dropit;
-               }
+               if (!process.dispatch(rqstp, statp))
+                       goto release_dropit; /* Release reply info */
        }
 
        /* Check RPC status result */
@@ -1327,6 +1419,9 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
                goto close;
        return 1;               /* Caller can now send it */
 
+release_dropit:
+       if (procp->pc_release)
+               procp->pc_release(rqstp);
  dropit:
        svc_authorise(rqstp);   /* doesn't hurt to call this twice */
        dprintk("svc: svc_process dropit\n");
@@ -1351,6 +1446,9 @@ err_bad_rpc:
        svc_putnl(resv, 2);
        goto sendit;
 
+err_release_bad_auth:
+       if (procp->pc_release)
+               procp->pc_release(rqstp);
 err_bad_auth:
        dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat));
        serv->sv_stats->rpcbadauth++;
@@ -1369,16 +1467,16 @@ err_bad_prog:
 
 err_bad_vers:
        svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n",
-                      vers, prog, progp->pg_name);
+                      rqstp->rq_vers, rqstp->rq_prog, progp->pg_name);
 
        serv->sv_stats->rpcbadfmt++;
        svc_putnl(resv, RPC_PROG_MISMATCH);
-       svc_putnl(resv, progp->pg_lovers);
-       svc_putnl(resv, progp->pg_hivers);
+       svc_putnl(resv, process.mismatch.lovers);
+       svc_putnl(resv, process.mismatch.hivers);
        goto sendit;
 
 err_bad_proc:
-       svc_printk(rqstp, "unknown procedure (%d)\n", proc);
+       svc_printk(rqstp, "unknown procedure (%d)\n", rqstp->rq_proc);
 
        serv->sv_stats->rpcbadfmt++;
        svc_putnl(resv, RPC_PROC_UNAVAIL);
index 61530b1..9429b28 100644 (file)
@@ -136,6 +136,7 @@ static void svc_xprt_free(struct kref *kref)
        struct module *owner = xprt->xpt_class->xcl_owner;
        if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags))
                svcauth_unix_info_release(xprt);
+       put_cred(xprt->xpt_cred);
        put_net(xprt->xpt_net);
        /* See comment on corresponding get in xs_setup_bc_tcp(): */
        if (xprt->xpt_bc_xprt)
@@ -252,7 +253,8 @@ void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *new)
 
 static int _svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
                            struct net *net, const int family,
-                           const unsigned short port, int flags)
+                           const unsigned short port, int flags,
+                           const struct cred *cred)
 {
        struct svc_xprt_class *xcl;
 
@@ -273,6 +275,7 @@ static int _svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
                        module_put(xcl->xcl_owner);
                        return PTR_ERR(newxprt);
                }
+               newxprt->xpt_cred = get_cred(cred);
                svc_add_new_perm_xprt(serv, newxprt);
                newport = svc_xprt_local_port(newxprt);
                return newport;
@@ -286,15 +289,16 @@ static int _svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
 
 int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
                    struct net *net, const int family,
-                   const unsigned short port, int flags)
+                   const unsigned short port, int flags,
+                   const struct cred *cred)
 {
        int err;
 
        dprintk("svc: creating transport %s[%d]\n", xprt_name, port);
-       err = _svc_create_xprt(serv, xprt_name, net, family, port, flags);
+       err = _svc_create_xprt(serv, xprt_name, net, family, port, flags, cred);
        if (err == -EPROTONOSUPPORT) {
                request_module("svc%s", xprt_name);
-               err = _svc_create_xprt(serv, xprt_name, net, family, port, flags);
+               err = _svc_create_xprt(serv, xprt_name, net, family, port, flags, cred);
        }
        if (err < 0)
                dprintk("svc: transport %s not found, err %d\n",
@@ -782,9 +786,10 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt)
                __module_get(xprt->xpt_class->xcl_owner);
                svc_check_conn_limits(xprt->xpt_server);
                newxpt = xprt->xpt_ops->xpo_accept(xprt);
-               if (newxpt)
+               if (newxpt) {
+                       newxpt->xpt_cred = get_cred(xprt->xpt_cred);
                        svc_add_new_temp_xprt(serv, newxpt);
-               else
+               else
                        module_put(xprt->xpt_class->xcl_owner);
        } else if (svc_xprt_reserve_slot(rqstp, xprt)) {
                /* XPT_DATA|XPT_DEFERRED case: */
index fb9041b..f92ef79 100644 (file)
@@ -500,7 +500,7 @@ static int unix_gid_parse(struct cache_detail *cd,
        rv = get_int(&mesg, &id);
        if (rv)
                return -EINVAL;
-       uid = make_kuid(&init_user_ns, id);
+       uid = make_kuid(current_user_ns(), id);
        ug.uid = uid;
 
        expiry = get_expiry(&mesg);
@@ -522,7 +522,7 @@ static int unix_gid_parse(struct cache_detail *cd,
                err = -EINVAL;
                if (rv)
                        goto out;
-               kgid = make_kgid(&init_user_ns, gid);
+               kgid = make_kgid(current_user_ns(), gid);
                if (!gid_valid(kgid))
                        goto out;
                ug.gi->gid[i] = kgid;
@@ -555,7 +555,7 @@ static int unix_gid_show(struct seq_file *m,
                         struct cache_detail *cd,
                         struct cache_head *h)
 {
-       struct user_namespace *user_ns = &init_user_ns;
+       struct user_namespace *user_ns = m->file->f_cred->user_ns;
        struct unix_gid *ug;
        int i;
        int glen;
@@ -796,6 +796,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
        struct kvec     *argv = &rqstp->rq_arg.head[0];
        struct kvec     *resv = &rqstp->rq_res.head[0];
        struct svc_cred *cred = &rqstp->rq_cred;
+       struct user_namespace *userns;
        u32             slen, i;
        int             len   = argv->iov_len;
 
@@ -816,8 +817,10 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
         * (export-specific) anonymous id by nfsd_setuser.
         * Supplementary gid's will be left alone.
         */
-       cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */
-       cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */
+       userns = (rqstp->rq_xprt && rqstp->rq_xprt->xpt_cred) ?
+               rqstp->rq_xprt->xpt_cred->user_ns : &init_user_ns;
+       cred->cr_uid = make_kuid(userns, svc_getnl(argv)); /* uid */
+       cred->cr_gid = make_kgid(userns, svc_getnl(argv)); /* gid */
        slen = svc_getnl(argv);                 /* gids length */
        if (slen > UNX_NGROUPS || (len -= (slen + 2)*4) < 0)
                goto badcred;
@@ -825,7 +828,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
        if (cred->cr_group_info == NULL)
                return SVC_CLOSE;
        for (i = 0; i < slen; i++) {
-               kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv));
+               kgid_t kgid = make_kgid(userns, svc_getnl(argv));
                cred->cr_group_info->gid[i] = kgid;
        }
        groups_sort(cred->cr_group_info);
index 43590a9..540fde2 100644 (file)
@@ -1332,13 +1332,14 @@ EXPORT_SYMBOL_GPL(svc_alien_sock);
  * @fd: file descriptor of the new listener
  * @name_return: pointer to buffer to fill in with name of listener
  * @len: size of the buffer
+ * @cred: credential
  *
  * Fills in socket name and returns positive length of name if successful.
  * Name is terminated with '\n'.  On error, returns a negative errno
  * value.
  */
 int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,
-               const size_t len)
+               const size_t len, const struct cred *cred)
 {
        int err = 0;
        struct socket *so = sockfd_lookup(fd, &err);
@@ -1371,6 +1372,7 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,
        salen = kernel_getsockname(svsk->sk_sock, sin);
        if (salen >= 0)
                svc_xprt_set_local(&svsk->sk_xprt, sin, salen);
+       svsk->sk_xprt.xpt_cred = get_cred(cred);
        svc_add_new_perm_xprt(serv, &svsk->sk_xprt);
        return svc_one_sock_name(svsk, name_return, len);
 out:
index 989e523..2b18223 100644 (file)
@@ -253,8 +253,8 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem)
                return -ENOMEM;
 
        down_read(&current->mm->mmap_sem);
-       npgs = get_user_pages_longterm(umem->address, umem->npgs,
-                                      gup_flags, &umem->pgs[0], NULL);
+       npgs = get_user_pages(umem->address, umem->npgs,
+                             gup_flags | FOLL_LONGTERM, &umem->pgs[0], NULL);
        up_read(&current->mm->mmap_sem);
 
        if (npgs != umem->npgs) {
diff --git a/samples/vfs/.gitignore b/samples/vfs/.gitignore
new file mode 100644 (file)
index 0000000..0806eb0
--- /dev/null
@@ -0,0 +1,2 @@
+test-fsmount
+test-statx
index 5010a4d..894cc58 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/python3
 # SPDX-License-Identifier: GPL-2.0-only
 #
-# Copyright (C) 2018 Netronome Systems, Inc.
+# Copyright (C) 2018-2019 Netronome Systems, Inc.
 
 # In case user attempts to run with Python 2.
 from __future__ import print_function
@@ -39,7 +39,7 @@ class Helper(object):
         Break down helper function protocol into smaller chunks: return type,
         name, distincts arguments.
         """
-        arg_re = re.compile('((const )?(struct )?(\w+|...))( (\**)(\w+))?$')
+        arg_re = re.compile('((\w+ )*?(\w+|...))( (\**)(\w+))?$')
         res = {}
         proto_re = re.compile('(.+) (\**)(\w+)\(((([^,]+)(, )?){1,5})\)$')
 
@@ -54,8 +54,8 @@ class Helper(object):
             capture = arg_re.match(a)
             res['args'].append({
                 'type' : capture.group(1),
-                'star' : capture.group(6),
-                'name' : capture.group(7)
+                'star' : capture.group(5),
+                'name' : capture.group(6)
             })
 
         return res
index 89c47f5..8c1af9b 100644 (file)
@@ -36,7 +36,7 @@ static unsigned int arm_pertask_ssp_rtl_execute(void)
                mask = GEN_INT(sext_hwi(sp_mask, GET_MODE_PRECISION(Pmode)));
                masked_sp = gen_reg_rtx(Pmode);
 
-               emit_insn_before(gen_rtx_SET(masked_sp,
+               emit_insn_before(gen_rtx_set(masked_sp,
                                             gen_rtx_AND(Pmode,
                                                         stack_pointer_rtx,
                                                         mask)),
diff --git a/scripts/gdb/linux/clk.py b/scripts/gdb/linux/clk.py
new file mode 100644 (file)
index 0000000..061aecf
--- /dev/null
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) NXP 2019
+
+import gdb
+import sys
+
+from linux import utils, lists, constants
+
+clk_core_type = utils.CachedType("struct clk_core")
+
+
+def clk_core_for_each_child(hlist_head):
+    return lists.hlist_for_each_entry(hlist_head,
+            clk_core_type.get_type().pointer(), "child_node")
+
+
+class LxClkSummary(gdb.Command):
+    """Print clk tree summary
+
+Output is a subset of /sys/kernel/debug/clk/clk_summary
+
+No calls are made during printing, instead a (c) if printed after values which
+are cached and potentially out of date"""
+
+    def __init__(self):
+        super(LxClkSummary, self).__init__("lx-clk-summary", gdb.COMMAND_DATA)
+
+    def show_subtree(self, clk, level):
+        gdb.write("%*s%-*s %7d %8d %8d %11lu%s\n" % (
+                level * 3 + 1, "",
+                30 - level * 3,
+                clk['name'].string(),
+                clk['enable_count'],
+                clk['prepare_count'],
+                clk['protect_count'],
+                clk['rate'],
+                '(c)' if clk['flags'] & constants.LX_CLK_GET_RATE_NOCACHE else '   '))
+
+        for child in clk_core_for_each_child(clk['children']):
+            self.show_subtree(child, level + 1)
+
+    def invoke(self, arg, from_tty):
+        gdb.write("                                 enable  prepare  protect               \n")
+        gdb.write("   clock                          count    count    count        rate   \n")
+        gdb.write("------------------------------------------------------------------------\n")
+        for clk in clk_core_for_each_child(gdb.parse_and_eval("clk_root_list")):
+            self.show_subtree(clk, 0)
+        for clk in clk_core_for_each_child(gdb.parse_and_eval("clk_orphan_list")):
+            self.show_subtree(clk, 0)
+
+
+LxClkSummary()
+
+
+class LxClkCoreLookup(gdb.Function):
+    """Find struct clk_core by name"""
+
+    def __init__(self):
+        super(LxClkCoreLookup, self).__init__("lx_clk_core_lookup")
+
+    def lookup_hlist(self, hlist_head, name):
+        for child in clk_core_for_each_child(hlist_head):
+            if child['name'].string() == name:
+                return child
+            result = self.lookup_hlist(child['children'], name)
+            if result:
+                return result
+
+    def invoke(self, name):
+        name = name.string()
+        return (self.lookup_hlist(gdb.parse_and_eval("clk_root_list"), name) or
+                self.lookup_hlist(gdb.parse_and_eval("clk_orphan_list"), name))
+
+
+LxClkCoreLookup()
diff --git a/scripts/gdb/linux/config.py b/scripts/gdb/linux/config.py
new file mode 100644 (file)
index 0000000..90e1565
--- /dev/null
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright 2019 Google LLC.
+
+import gdb
+import zlib
+
+from linux import utils
+
+
+class LxConfigDump(gdb.Command):
+    """Output kernel config to the filename specified as the command
+       argument. Equivalent to 'zcat /proc/config.gz > config.txt' on
+       a running target"""
+
+    def __init__(self):
+        super(LxConfigDump, self).__init__("lx-configdump", gdb.COMMAND_DATA,
+                                           gdb.COMPLETE_FILENAME)
+
+    def invoke(self, arg, from_tty):
+        if len(arg) == 0:
+            filename = "config.txt"
+        else:
+            filename = arg
+
+        try:
+            py_config_ptr = gdb.parse_and_eval("kernel_config_data + 8")
+            py_config_size = gdb.parse_and_eval(
+                    "sizeof(kernel_config_data) - 1 - 8 * 2")
+        except gdb.error as e:
+            raise gdb.GdbError("Can't find config, enable CONFIG_IKCONFIG?")
+
+        inf = gdb.inferiors()[0]
+        zconfig_buf = utils.read_memoryview(inf, py_config_ptr,
+                                            py_config_size).tobytes()
+
+        config_buf = zlib.decompress(zconfig_buf, 16)
+        with open(filename, 'wb') as f:
+            f.write(config_buf)
+
+        gdb.write("Dumped config to " + filename + "\n")
+
+
+LxConfigDump()
index d3319a8..1d73083 100644 (file)
  *
  */
 
+#include <linux/clk-provider.h>
 #include <linux/fs.h>
+#include <linux/hrtimer.h>
 #include <linux/mount.h>
 #include <linux/of_fdt.h>
+#include <linux/threads.h>
 
 /* We need to stringify expanded macros so that they can be parsed */
 
@@ -36,6 +39,9 @@
 
 import gdb
 
+/* linux/clk-provider.h */
+LX_GDBPARSED(CLK_GET_RATE_NOCACHE)
+
 /* linux/fs.h */
 LX_VALUE(SB_RDONLY)
 LX_VALUE(SB_SYNCHRONOUS)
@@ -44,6 +50,9 @@ LX_VALUE(SB_DIRSYNC)
 LX_VALUE(SB_NOATIME)
 LX_VALUE(SB_NODIRATIME)
 
+/* linux/htimer.h */
+LX_GDBPARSED(hrtimer_resolution)
+
 /* linux/mount.h */
 LX_VALUE(MNT_NOSUID)
 LX_VALUE(MNT_NODEV)
@@ -52,8 +61,16 @@ LX_VALUE(MNT_NOATIME)
 LX_VALUE(MNT_NODIRATIME)
 LX_VALUE(MNT_RELATIME)
 
+/* linux/threads.h */
+LX_VALUE(NR_CPUS)
+
 /* linux/of_fdt.h> */
 LX_VALUE(OF_DT_HEADER)
 
 /* Kernel Configs */
+LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS)
+LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
+LX_CONFIG(CONFIG_HIGH_RES_TIMERS)
+LX_CONFIG(CONFIG_NR_CPUS)
 LX_CONFIG(CONFIG_OF)
+LX_CONFIG(CONFIG_TICK_ONESHOT)
index ca11e8d..008e62f 100644 (file)
@@ -135,6 +135,7 @@ and can help identify the state of hotplugged CPUs"""
         gdb.write("Online CPUs   : {}\n".format(list(each_online_cpu())))
         gdb.write("Active CPUs   : {}\n".format(list(each_active_cpu())))
 
+
 LxCpus()
 
 
index 2f335fb..c487ddf 100644 (file)
@@ -16,13 +16,15 @@ import gdb
 from linux import utils
 
 list_head = utils.CachedType("struct list_head")
+hlist_head = utils.CachedType("struct hlist_head")
+hlist_node = utils.CachedType("struct hlist_node")
 
 
 def list_for_each(head):
     if head.type == list_head.get_type().pointer():
         head = head.dereference()
     elif head.type != list_head.get_type():
-        raise gdb.GdbError("Must be struct list_head not {}"
+        raise TypeError("Must be struct list_head not {}"
                            .format(head.type))
 
     node = head['next'].dereference()
@@ -33,9 +35,24 @@ def list_for_each(head):
 
 def list_for_each_entry(head, gdbtype, member):
     for node in list_for_each(head):
-        if node.type != list_head.get_type().pointer():
-            raise TypeError("Type {} found. Expected struct list_head *."
-                            .format(node.type))
+        yield utils.container_of(node, gdbtype, member)
+
+
+def hlist_for_each(head):
+    if head.type == hlist_head.get_type().pointer():
+        head = head.dereference()
+    elif head.type != hlist_head.get_type():
+        raise TypeError("Must be struct hlist_head not {}"
+                           .format(head.type))
+
+    node = head['first'].dereference()
+    while node.address:
+        yield node.address
+        node = node['next'].dereference()
+
+
+def hlist_for_each_entry(head, gdbtype, member):
+    for node in hlist_for_each(head):
         yield utils.container_of(node, gdbtype, member)
 
 
@@ -110,4 +127,5 @@ class LxListChk(gdb.Command):
             raise gdb.GdbError("lx-list-check takes one argument")
         list_check(gdb.parse_and_eval(argv[0]))
 
+
 LxListChk()
index 2f01a95..6a56bba 100644 (file)
@@ -29,6 +29,7 @@ class LxCmdLine(gdb.Command):
     def invoke(self, arg, from_tty):
         gdb.write(gdb.parse_and_eval("saved_command_line").string() + "\n")
 
+
 LxCmdLine()
 
 
@@ -43,6 +44,7 @@ class LxVersion(gdb.Command):
         # linux_banner should contain a newline
         gdb.write(gdb.parse_and_eval("(char *)linux_banner").string())
 
+
 LxVersion()
 
 
@@ -86,6 +88,7 @@ Equivalent to cat /proc/iomem on a running target"""
     def invoke(self, arg, from_tty):
         return show_lx_resources("iomem_resource")
 
+
 LxIOMem()
 
 
@@ -100,6 +103,7 @@ Equivalent to cat /proc/ioports on a running target"""
     def invoke(self, arg, from_tty):
         return show_lx_resources("ioport_resource")
 
+
 LxIOPorts()
 
 
@@ -149,7 +153,7 @@ values of that process namespace"""
         if len(argv) >= 1:
             try:
                 pid = int(argv[0])
-            except:
+            except gdb.error:
                 raise gdb.GdbError("Provide a PID as integer value")
         else:
             pid = 1
@@ -195,6 +199,7 @@ values of that process namespace"""
                         info_opts(FS_INFO, s_flags),
                         info_opts(MNT_INFO, m_flags)))
 
+
 LxMounts()
 
 
@@ -259,7 +264,7 @@ class LxFdtDump(gdb.Command):
 
         try:
             f = open(filename, 'wb')
-        except:
+        except gdb.error:
             raise gdb.GdbError("Could not open file to dump fdt")
 
         f.write(fdt_buf)
@@ -267,4 +272,5 @@ class LxFdtDump(gdb.Command):
 
         gdb.write("Dumped fdt blob to " + filename + "\n")
 
+
 LxFdtDump()
diff --git a/scripts/gdb/linux/rbtree.py b/scripts/gdb/linux/rbtree.py
new file mode 100644 (file)
index 0000000..39db889
--- /dev/null
@@ -0,0 +1,177 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright 2019 Google LLC.
+
+import gdb
+
+from linux import utils
+
+rb_root_type = utils.CachedType("struct rb_root")
+rb_node_type = utils.CachedType("struct rb_node")
+
+
+def rb_first(root):
+    if root.type == rb_root_type.get_type():
+        node = node.address.cast(rb_root_type.get_type().pointer())
+    elif root.type != rb_root_type.get_type().pointer():
+        raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
+
+    node = root['rb_node']
+    if node is 0:
+        return None
+
+    while node['rb_left']:
+        node = node['rb_left']
+
+    return node
+
+
+def rb_last(root):
+    if root.type == rb_root_type.get_type():
+        node = node.address.cast(rb_root_type.get_type().pointer())
+    elif root.type != rb_root_type.get_type().pointer():
+        raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
+
+    node = root['rb_node']
+    if node is 0:
+        return None
+
+    while node['rb_right']:
+        node = node['rb_right']
+
+    return node
+
+
+def rb_parent(node):
+    parent = gdb.Value(node['__rb_parent_color'] & ~3)
+    return parent.cast(rb_node_type.get_type().pointer())
+
+
+def rb_empty_node(node):
+    return node['__rb_parent_color'] == node.address
+
+
+def rb_next(node):
+    if node.type == rb_node_type.get_type():
+        node = node.address.cast(rb_node_type.get_type().pointer())
+    elif node.type != rb_node_type.get_type().pointer():
+        raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
+
+    if rb_empty_node(node):
+        return None
+
+    if node['rb_right']:
+        node = node['rb_right']
+        while node['rb_left']:
+            node = node['rb_left']
+        return node
+
+    parent = rb_parent(node)
+    while parent and node == parent['rb_right']:
+            node = parent
+            parent = rb_parent(node)
+
+    return parent
+
+
+def rb_prev(node):
+    if node.type == rb_node_type.get_type():
+        node = node.address.cast(rb_node_type.get_type().pointer())
+    elif node.type != rb_node_type.get_type().pointer():
+        raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
+
+    if rb_empty_node(node):
+        return None
+
+    if node['rb_left']:
+        node = node['rb_left']
+        while node['rb_right']:
+            node = node['rb_right']
+        return node.dereference()
+
+    parent = rb_parent(node)
+    while parent and node == parent['rb_left'].dereference():
+            node = parent
+            parent = rb_parent(node)
+
+    return parent
+
+
+class LxRbFirst(gdb.Function):
+    """Lookup and return a node from an RBTree
+
+$lx_rb_first(root): Return the node at the given index.
+If index is omitted, the root node is dereferenced and returned."""
+
+    def __init__(self):
+        super(LxRbFirst, self).__init__("lx_rb_first")
+
+    def invoke(self, root):
+        result = rb_first(root)
+        if result is None:
+            raise gdb.GdbError("No entry in tree")
+
+        return result
+
+
+LxRbFirst()
+
+
+class LxRbLast(gdb.Function):
+    """Lookup and return a node from an RBTree.
+
+$lx_rb_last(root): Return the node at the given index.
+If index is omitted, the root node is dereferenced and returned."""
+
+    def __init__(self):
+        super(LxRbLast, self).__init__("lx_rb_last")
+
+    def invoke(self, root):
+        result = rb_last(root)
+        if result is None:
+            raise gdb.GdbError("No entry in tree")
+
+        return result
+
+
+LxRbLast()
+
+
+class LxRbNext(gdb.Function):
+    """Lookup and return a node from an RBTree.
+
+$lx_rb_next(node): Return the node at the given index.
+If index is omitted, the root node is dereferenced and returned."""
+
+    def __init__(self):
+        super(LxRbNext, self).__init__("lx_rb_next")
+
+    def invoke(self, node):
+        result = rb_next(node)
+        if result is None:
+            raise gdb.GdbError("No entry in tree")
+
+        return result
+
+
+LxRbNext()
+
+
+class LxRbPrev(gdb.Function):
+    """Lookup and return a node from an RBTree.
+
+$lx_rb_prev(node): Return the node at the given index.
+If index is omitted, the root node is dereferenced and returned."""
+
+    def __init__(self):
+        super(LxRbPrev, self).__init__("lx_rb_prev")
+
+    def invoke(self, node):
+        result = rb_prev(node)
+        if result is None:
+            raise gdb.GdbError("No entry in tree")
+
+        return result
+
+
+LxRbPrev()
index 004b0ac..2f5b95f 100644 (file)
@@ -139,8 +139,12 @@ lx-symbols command."""
                 saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})
 
         # drop all current symbols and reload vmlinux
+        orig_vmlinux = 'vmlinux'
+        for obj in gdb.objfiles():
+            if obj.filename.endswith('vmlinux'):
+                orig_vmlinux = obj.filename
         gdb.execute("symbol-file", to_string=True)
-        gdb.execute("symbol-file vmlinux")
+        gdb.execute("symbol-file {0}".format(orig_vmlinux))
 
         self.loaded_modules = []
         module_list = modules.module_list()
index f6ab3cc..0301dc1 100644 (file)
@@ -79,6 +79,7 @@ class LxPs(gdb.Command):
                 pid=task["pid"],
                 comm=task["comm"].string()))
 
+
 LxPs()
 
 
@@ -134,4 +135,5 @@ variable."""
         else:
             raise gdb.GdbError("No task of PID " + str(pid))
 
+
 LxThreadInfoByPidFunc()
diff --git a/scripts/gdb/linux/timerlist.py b/scripts/gdb/linux/timerlist.py
new file mode 100644 (file)
index 0000000..071d0dd
--- /dev/null
@@ -0,0 +1,219 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright 2019 Google LLC.
+
+import binascii
+import gdb
+
+from linux import constants
+from linux import cpus
+from linux import rbtree
+from linux import utils
+
+timerqueue_node_type = utils.CachedType("struct timerqueue_node").get_type()
+hrtimer_type = utils.CachedType("struct hrtimer").get_type()
+
+
+def ktime_get():
+    """Returns the current time, but not very accurately
+
+    We can't read the hardware timer itself to add any nanoseconds
+    that need to be added since we last stored the time in the
+    timekeeper. But this is probably good enough for debug purposes."""
+    tk_core = gdb.parse_and_eval("&tk_core")
+
+    return tk_core['timekeeper']['tkr_mono']['base']
+
+
+def print_timer(rb_node, idx):
+    timerqueue = utils.container_of(rb_node, timerqueue_node_type.pointer(),
+                                    "node")
+    timer = utils.container_of(timerqueue, hrtimer_type.pointer(), "node")
+
+    function = str(timer['function']).split(" ")[1].strip("<>")
+    softexpires = timer['_softexpires']
+    expires = timer['node']['expires']
+    now = ktime_get()
+
+    text = " #{}: <{}>, {}, ".format(idx, timer, function)
+    text += "S:{:02x}\n".format(int(timer['state']))
+    text += " # expires at {}-{} nsecs [in {} to {} nsecs]\n".format(
+            softexpires, expires, softexpires - now, expires - now)
+    return text
+
+
+def print_active_timers(base):
+    curr = base['active']['next']['node']
+    curr = curr.address.cast(rbtree.rb_node_type.get_type().pointer())
+    idx = 0
+    while curr:
+        yield print_timer(curr, idx)
+        curr = rbtree.rb_next(curr)
+        idx += 1
+
+
+def print_base(base):
+    text = " .base:       {}\n".format(base.address)
+    text += " .index:      {}\n".format(base['index'])
+
+    text += " .resolution: {} nsecs\n".format(constants.LX_hrtimer_resolution)
+
+    text += " .get_time:   {}\n".format(base['get_time'])
+    if constants.LX_CONFIG_HIGH_RES_TIMERS:
+        text += "  .offset:     {} nsecs\n".format(base['offset'])
+    text += "active timers:\n"
+    text += "".join([x for x in print_active_timers(base)])
+    return text
+
+
+def print_cpu(hrtimer_bases, cpu, max_clock_bases):
+    cpu_base = cpus.per_cpu(hrtimer_bases, cpu)
+    jiffies = gdb.parse_and_eval("jiffies_64")
+    tick_sched_ptr = gdb.parse_and_eval("&tick_cpu_sched")
+    ts = cpus.per_cpu(tick_sched_ptr, cpu)
+
+    text = "cpu: {}\n".format(cpu)
+    for i in xrange(max_clock_bases):
+        text += " clock {}:\n".format(i)
+        text += print_base(cpu_base['clock_base'][i])
+
+        if constants.LX_CONFIG_HIGH_RES_TIMERS:
+            fmts = [("  .{}   : {} nsecs", 'expires_next'),
+                    ("  .{}    : {}", 'hres_active'),
+                    ("  .{}      : {}", 'nr_events'),
+                    ("  .{}     : {}", 'nr_retries'),
+                    ("  .{}       : {}", 'nr_hangs'),
+                    ("  .{}  : {}", 'max_hang_time')]
+            text += "\n".join([s.format(f, cpu_base[f]) for s, f in fmts])
+            text += "\n"
+
+        if constants.LX_CONFIG_TICK_ONESHOT:
+            fmts = [("  .{}      : {}", 'nohz_mode'),
+                    ("  .{}      : {} nsecs", 'last_tick'),
+                    ("  .{}   : {}", 'tick_stopped'),
+                    ("  .{}   : {}", 'idle_jiffies'),
+                    ("  .{}     : {}", 'idle_calls'),
+                    ("  .{}    : {}", 'idle_sleeps'),
+                    ("  .{} : {} nsecs", 'idle_entrytime'),
+                    ("  .{}  : {} nsecs", 'idle_waketime'),
+                    ("  .{}  : {} nsecs", 'idle_exittime'),
+                    ("  .{} : {} nsecs", 'idle_sleeptime'),
+                    ("  .{}: {} nsecs", 'iowait_sleeptime'),
+                    ("  .{}   : {}", 'last_jiffies'),
+                    ("  .{}     : {}", 'next_timer'),
+                    ("  .{}   : {} nsecs", 'idle_expires')]
+            text += "\n".join([s.format(f, ts[f]) for s, f in fmts])
+            text += "\njiffies: {}\n".format(jiffies)
+
+        text += "\n"
+
+    return text
+
+
+def print_tickdevice(td, cpu):
+    dev = td['evtdev']
+    text = "Tick Device: mode:     {}\n".format(td['mode'])
+    if cpu < 0:
+            text += "Broadcast device\n"
+    else:
+            text += "Per CPU device: {}\n".format(cpu)
+
+    text += "Clock Event Device: "
+    if dev == 0:
+            text += "<NULL>\n"
+            return text
+
+    text += "{}\n".format(dev['name'])
+    text += " max_delta_ns:   {}\n".format(dev['max_delta_ns'])
+    text += " min_delta_ns:   {}\n".format(dev['min_delta_ns'])
+    text += " mult:           {}\n".format(dev['mult'])
+    text += " shift:          {}\n".format(dev['shift'])
+    text += " mode:           {}\n".format(dev['state_use_accessors'])
+    text += " next_event:     {} nsecs\n".format(dev['next_event'])
+
+    text += " set_next_event: {}\n".format(dev['set_next_event'])
+
+    members = [('set_state_shutdown', " shutdown: {}\n"),
+               ('set_state_periodic', " periodic: {}\n"),
+               ('set_state_oneshot', " oneshot:  {}\n"),
+               ('set_state_oneshot_stopped', " oneshot stopped: {}\n"),
+               ('tick_resume', " resume:   {}\n")]
+    for member, fmt in members:
+        if dev[member]:
+            text += fmt.format(dev[member])
+
+    text += " event_handler:  {}\n".format(dev['event_handler'])
+    text += " retries:        {}\n".format(dev['retries'])
+
+    return text
+
+
+def pr_cpumask(mask):
+    nr_cpu_ids = 1
+    if constants.LX_NR_CPUS > 1:
+        nr_cpu_ids = gdb.parse_and_eval("nr_cpu_ids")
+
+    inf = gdb.inferiors()[0]
+    bits = mask['bits']
+    num_bytes = (nr_cpu_ids + 7) / 8
+    buf = utils.read_memoryview(inf, bits, num_bytes).tobytes()
+    buf = binascii.b2a_hex(buf)
+
+    chunks = []
+    i = num_bytes
+    while i > 0:
+        i -= 1
+        start = i * 2
+        end = start + 2
+        chunks.append(buf[start:end])
+        if i != 0 and i % 4 == 0:
+            chunks.append(',')
+
+    extra = nr_cpu_ids % 8
+    if 0 < extra <= 4:
+        chunks[0] = chunks[0][0]  # Cut off the first 0
+
+    return "".join(chunks)
+
+
+class LxTimerList(gdb.Command):
+    """Print /proc/timer_list"""
+
+    def __init__(self):
+        super(LxTimerList, self).__init__("lx-timerlist", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        hrtimer_bases = gdb.parse_and_eval("&hrtimer_bases")
+        max_clock_bases = gdb.parse_and_eval("HRTIMER_MAX_CLOCK_BASES")
+
+        text = "Timer List Version: gdb scripts\n"
+        text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(max_clock_bases)
+        text += "now at {} nsecs\n".format(ktime_get())
+
+        for cpu in cpus.each_online_cpu():
+            text += print_cpu(hrtimer_bases, cpu, max_clock_bases)
+
+        if constants.LX_CONFIG_GENERIC_CLOCKEVENTS:
+            if constants.LX_CONFIG_GENERIC_CLOCKEVENTS_BROADCAST:
+                bc_dev = gdb.parse_and_eval("&tick_broadcast_device")
+                text += print_tickdevice(bc_dev, -1)
+                text += "\n"
+                mask = gdb.parse_and_eval("tick_broadcast_mask")
+                mask = pr_cpumask(mask)
+                text += "tick_broadcast_mask: {}\n".format(mask)
+                if constants.LX_CONFIG_TICK_ONESHOT:
+                    mask = gdb.parse_and_eval("tick_broadcast_oneshot_mask")
+                    mask = pr_cpumask(mask)
+                    text += "tick_broadcast_oneshot_mask: {}\n".format(mask)
+                text += "\n"
+
+            tick_cpu_devices = gdb.parse_and_eval("&tick_cpu_device")
+            for cpu in cpus.each_online_cpu():
+                tick_dev = cpus.per_cpu(tick_cpu_devices, cpu)
+                text += print_tickdevice(tick_dev, cpu)
+                text += "\n"
+
+        gdb.write(text)
+
+
+LxTimerList()
index 5080587..bc67126 100644 (file)
@@ -66,6 +66,7 @@ Note that TYPE and ELEMENT have to be quoted as strings."""
         return container_of(ptr, gdb.lookup_type(typename.string()).pointer(),
                             elementname.string())
 
+
 ContainerOf()
 
 
@@ -148,14 +149,14 @@ def get_gdbserver_type():
     def probe_qemu():
         try:
             return gdb.execute("monitor info version", to_string=True) != ""
-        except:
+        except gdb.error:
             return False
 
     def probe_kgdb():
         try:
             thread_info = gdb.execute("info thread 2", to_string=True)
             return "shadowCPU0" in thread_info
-        except:
+        except gdb.error:
             return False
 
     global gdbserver_type
@@ -172,7 +173,7 @@ def get_gdbserver_type():
 def gdb_eval_or_none(expresssion):
     try:
         return gdb.parse_and_eval(expresssion)
-    except:
+    except gdb.error:
         return None
 
 
index 6e0b0af..eff5a48 100644 (file)
@@ -27,7 +27,11 @@ else:
     import linux.modules
     import linux.dmesg
     import linux.tasks
+    import linux.config
     import linux.cpus
     import linux.lists
+    import linux.rbtree
     import linux.proc
     import linux.constants
+    import linux.timerlist
+    import linux.clk
index 08ba146..492ac34 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
  */
 
+#include <sys/mman.h>
 #include <sys/stat.h>
 #include <ctype.h>
 #include <errno.h>
@@ -36,6 +37,52 @@ static bool is_dir(const char *path)
        return S_ISDIR(st.st_mode);
 }
 
+/* return true if the given two files are the same, false otherwise */
+static bool is_same(const char *file1, const char *file2)
+{
+       int fd1, fd2;
+       struct stat st1, st2;
+       void *map1, *map2;
+       bool ret = false;
+
+       fd1 = open(file1, O_RDONLY);
+       if (fd1 < 0)
+               return ret;
+
+       fd2 = open(file2, O_RDONLY);
+       if (fd2 < 0)
+               goto close1;
+
+       ret = fstat(fd1, &st1);
+       if (ret)
+               goto close2;
+       ret = fstat(fd2, &st2);
+       if (ret)
+               goto close2;
+
+       if (st1.st_size != st2.st_size)
+               goto close2;
+
+       map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);
+       if (map1 == MAP_FAILED)
+               goto close2;
+
+       map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0);
+       if (map2 == MAP_FAILED)
+               goto close2;
+
+       if (bcmp(map1, map2, st1.st_size))
+               goto close2;
+
+       ret = true;
+close2:
+       close(fd2);
+close1:
+       close(fd1);
+
+       return ret;
+}
+
 /*
  * Create the parent directory of the given path.
  *
@@ -179,7 +226,7 @@ const char *conf_get_configname(void)
        return name ? name : ".config";
 }
 
-const char *conf_get_autoconfig_name(void)
+static const char *conf_get_autoconfig_name(void)
 {
        char *name = getenv("KCONFIG_AUTOCONFIG");
 
@@ -194,7 +241,7 @@ char *conf_get_default_confname(void)
        name = expand_string(conf_defname);
        env = getenv(SRCTREE);
        if (env) {
-               sprintf(fullname, "%s/%s", env, name);
+               snprintf(fullname, sizeof(fullname), "%s/%s", env, name);
                if (is_present(fullname))
                        return fullname;
        }
@@ -817,40 +864,34 @@ int conf_write(const char *name)
        FILE *out;
        struct symbol *sym;
        struct menu *menu;
-       const char *basename;
        const char *str;
-       char dirname[PATH_MAX+1], tmpname[PATH_MAX+22], newname[PATH_MAX+8];
+       char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
        char *env;
 
-       dirname[0] = 0;
-       if (name && name[0]) {
-               char *slash;
-
-               if (is_dir(name)) {
-                       strcpy(dirname, name);
-                       strcat(dirname, "/");
-                       basename = conf_get_configname();
-               } else if ((slash = strrchr(name, '/'))) {
-                       int size = slash - name + 1;
-                       memcpy(dirname, name, size);
-                       dirname[size] = 0;
-                       if (slash[1])
-                               basename = slash + 1;
-                       else
-                               basename = conf_get_configname();
-               } else
-                       basename = name;
-       } else
-               basename = conf_get_configname();
-
-       sprintf(newname, "%s%s", dirname, basename);
+       if (!name)
+               name = conf_get_configname();
+
+       if (!*name) {
+               fprintf(stderr, "config name is empty\n");
+               return -1;
+       }
+
+       if (is_dir(name)) {
+               fprintf(stderr, "%s: Is a directory\n", name);
+               return -1;
+       }
+
+       if (make_parent_dir(name))
+               return -1;
+
        env = getenv("KCONFIG_OVERWRITECONFIG");
-       if (!env || !*env) {
-               sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
-               out = fopen(tmpname, "w");
-       } else {
+       if (env && *env) {
                *tmpname = 0;
-               out = fopen(newname, "w");
+               out = fopen(name, "w");
+       } else {
+               snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp",
+                        name, (int)getpid());
+               out = fopen(tmpname, "w");
        }
        if (!out)
                return 1;
@@ -897,14 +938,20 @@ next:
        fclose(out);
 
        if (*tmpname) {
-               strcat(dirname, basename);
-               strcat(dirname, ".old");
-               rename(newname, dirname);
-               if (rename(tmpname, newname))
+               if (is_same(name, tmpname)) {
+                       conf_message("No change to %s", name);
+                       unlink(tmpname);
+                       sym_set_change_count(0);
+                       return 0;
+               }
+
+               snprintf(oldname, sizeof(oldname), "%s.old", name);
+               rename(name, oldname);
+               if (rename(tmpname, name))
                        return 1;
        }
 
-       conf_message("configuration written to %s", newname);
+       conf_message("configuration written to %s", name);
 
        sym_set_change_count(0);
 
@@ -917,8 +964,6 @@ static int conf_write_dep(const char *name)
        struct file *file;
        FILE *out;
 
-       if (!name)
-               name = ".kconfig.d";
        out = fopen("..config.tmp", "w");
        if (!out)
                return 1;
index 5d4ecf3..e36b342 100644 (file)
@@ -638,7 +638,7 @@ on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
 void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
 {
        GtkWidget *dialog;
-       const gchar *intro_text = 
+       const gchar *intro_text =
            "Welcome to gkc, the GTK+ graphical configuration tool\n"
            "For each option, a blank box indicates the feature is disabled, a\n"
            "check indicates it is enabled, and a dot indicates that it is to\n"
index c9df1c8..6354c90 100644 (file)
@@ -378,7 +378,8 @@ FILE *zconf_fopen(const char *name)
        if (!f && name != NULL && name[0] != '/') {
                env = getenv(SRCTREE);
                if (env) {
-                       sprintf(fullname, "%s/%s", env, name);
+                       snprintf(fullname, sizeof(fullname),
+                                "%s/%s", env, name);
                        f = fopen(fullname, "r");
                }
        }
index d871539..cbc7658 100644 (file)
@@ -49,7 +49,6 @@ const char *zconf_curname(void);
 
 /* confdata.c */
 const char *conf_get_configname(void);
-const char *conf_get_autoconfig_name(void);
 char *conf_get_default_confname(void);
 void sym_set_change_count(int count);
 void sym_add_change_count(int count);
index a8999d8..7cb5a7e 100644 (file)
@@ -1,4 +1,4 @@
 This is NOT the official version of dialog.  This version has been
 significantly modified from the original.  It is for use by the Linux
-kernel configuration script.  Please do not bother Savio Lam with 
+kernel configuration script.  Please do not bother Savio Lam with
 questions about this program.
index 5f8c82a..694091f 100644 (file)
@@ -936,7 +936,7 @@ static void conf_save(void)
                                set_config_filename(dialog_input_result);
                                return;
                        }
-                       show_textbox(NULL, "Can't create file!  Probably a nonexistent directory.", 5, 60);
+                       show_textbox(NULL, "Can't create file!", 5, 60);
                        break;
                case 1:
                        show_helptext("Save Alternate Configuration", save_config_help);
old mode 100644 (file)
new mode 100755 (executable)
index ac92c0d..cbafe3b 100644 (file)
@@ -1438,8 +1438,7 @@ static void conf_save(void)
                                set_config_filename(dialog_input_result);
                                return;
                        }
-                       btn_dialog(main_window, "Can't create file! "
-                               "Probably a nonexistent directory.",
+                       btn_dialog(main_window, "Can't create file!",
                                1, "<OK>");
                        break;
                case 1:
index d82b87c..c61787b 100644 (file)
@@ -4649,7 +4649,7 @@ static int selinux_socket_connect_helper(struct socket *sock,
                struct lsm_network_audit net = {0,};
                struct sockaddr_in *addr4 = NULL;
                struct sockaddr_in6 *addr6 = NULL;
-               unsigned short snum = 0;
+               unsigned short snum;
                u32 sid, perm;
 
                /* sctp_connectx(3) calls via selinux_sctp_bind_connect()
@@ -4674,12 +4674,12 @@ static int selinux_socket_connect_helper(struct socket *sock,
                        break;
                default:
                        /* Note that SCTP services expect -EINVAL, whereas
-                        * others must handle this at the protocol level:
-                        * connect(AF_UNSPEC) on a connected socket is
-                        * a documented way disconnect the socket.
+                        * others expect -EAFNOSUPPORT.
                         */
                        if (sksec->sclass == SECCLASS_SCTP_SOCKET)
                                return -EINVAL;
+                       else
+                               return -EAFNOSUPPORT;
                }
 
                err = sel_netport_sid(sk->sk_protocol, snum, &sid);
index 3d011ab..f678b4c 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/module.h>
+#include <linux/soc/cirrus/ep93xx.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <asm/mach-types.h>
-#include <mach/hardware.h>
 
 static int edb93xx_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params)
index cd5a939..c6bc447 100644 (file)
@@ -24,6 +24,7 @@
 #include <sound/soc.h>
 
 #include <linux/platform_data/dma-ep93xx.h>
+#include <linux/soc/cirrus/ep93xx.h>
 
 #include "ep93xx-pcm.h"
 
index 0918c5d..beab7c5 100644 (file)
@@ -27,9 +27,8 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
-#include <mach/hardware.h>
-#include <mach/ep93xx-regs.h>
 #include <linux/platform_data/dma-ep93xx.h>
+#include <linux/soc/cirrus/ep93xx.h>
 
 #include "ep93xx-pcm.h"
 
index 1ec6618..cb85053 100644 (file)
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/soc/cirrus/ep93xx.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 
 #include <asm/mach-types.h>
-#include <mach/hardware.h>
 
 static struct snd_soc_dai_link simone_dai = {
        .name           = "AC97",
index 11ff7b2..dea4909 100644 (file)
 
 #include <linux/platform_device.h>
 #include <linux/module.h>
+#include <linux/soc/cirrus/ep93xx.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 
 #include <asm/mach-types.h>
-#include <mach/hardware.h>
 
 #include "../codecs/tlv320aic23.h"
 
index 156aa7c..2bbb92e 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/time.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
index 72336ba..63e0cf6 100644 (file)
@@ -629,7 +629,7 @@ union bpf_attr {
  *             **BPF_F_INVALIDATE_HASH** (set *skb*\ **->hash**, *skb*\
  *             **->swhash** and *skb*\ **->l4hash** to 0).
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -654,7 +654,7 @@ union bpf_attr {
  *             flexibility and can handle sizes larger than 2 or 4 for the
  *             checksum to update.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -686,7 +686,7 @@ union bpf_attr {
  *             flexibility and can handle sizes larger than 2 or 4 for the
  *             checksum to update.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -741,7 +741,7 @@ union bpf_attr {
  *             efficient, but it is handled through an action code where the
  *             redirection happens only after the eBPF program has returned.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -806,7 +806,7 @@ union bpf_attr {
  *             **ETH_P_8021Q** and **ETH_P_8021AD**, it is considered to
  *             be **ETH_P_8021Q**.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -818,7 +818,7 @@ union bpf_attr {
  *     Description
  *             Pop a VLAN header from the packet associated to *skb*.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1168,7 +1168,7 @@ union bpf_attr {
  *             All values for *flags* are reserved for future usage, and must
  *             be left at zero.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1281,7 +1281,7 @@ union bpf_attr {
  *             implicitly linearizes, unclones and drops offloads from the
  *             *skb*.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1317,7 +1317,7 @@ union bpf_attr {
  *             **bpf_skb_pull_data()** to effectively unclone the *skb* from
  *             the very beginning in case it is indeed cloned.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1369,7 +1369,7 @@ union bpf_attr {
  *             All values for *flags* are reserved for future usage, and must
  *             be left at zero.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1384,7 +1384,7 @@ union bpf_attr {
  *             can be used to prepare the packet for pushing or popping
  *             headers.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1518,20 +1518,20 @@ union bpf_attr {
  *             * **BPF_F_ADJ_ROOM_FIXED_GSO**: Do not adjust gso_size.
  *               Adjusting mss in this way is not allowed for datagrams.
  *
- *             * **BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 **:
- *             * **BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 **:
+ *             * **BPF_F_ADJ_ROOM_ENCAP_L3_IPV4**,
+ *               **BPF_F_ADJ_ROOM_ENCAP_L3_IPV6**:
  *               Any new space is reserved to hold a tunnel header.
  *               Configure skb offsets and other fields accordingly.
  *
- *             * **BPF_F_ADJ_ROOM_ENCAP_L4_GRE **:
- *             * **BPF_F_ADJ_ROOM_ENCAP_L4_UDP **:
+ *             * **BPF_F_ADJ_ROOM_ENCAP_L4_GRE**,
+ *               **BPF_F_ADJ_ROOM_ENCAP_L4_UDP**:
  *               Use with ENCAP_L3 flags to further specify the tunnel type.
  *
- *             * **BPF_F_ADJ_ROOM_ENCAP_L2(len) **:
+ *             * **BPF_F_ADJ_ROOM_ENCAP_L2**\ (*len*):
  *               Use with ENCAP_L3/L4 flags to further specify the tunnel
- *               type; **len** is the length of the inner MAC header.
+ *               type; *len* is the length of the inner MAC header.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1610,7 +1610,7 @@ union bpf_attr {
  *             more flexibility as the user is free to store whatever meta
  *             data they need.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1852,7 +1852,7 @@ union bpf_attr {
  *             copied if necessary (i.e. if data was not linear and if start
  *             and end pointers do not point to the same chunk).
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -1886,7 +1886,7 @@ union bpf_attr {
  *             only possible to shrink the packet as of this writing,
  *             therefore *delta* must be a negative integer.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -2061,18 +2061,18 @@ union bpf_attr {
  *             **BPF_LWT_ENCAP_IP**
  *                     IP encapsulation (GRE/GUE/IPIP/etc). The outer header
  *                     must be IPv4 or IPv6, followed by zero or more
- *                     additional headers, up to LWT_BPF_MAX_HEADROOM total
- *                     bytes in all prepended headers. Please note that
- *                     if skb_is_gso(skb) is true, no more than two headers
- *                     can be prepended, and the inner header, if present,
- *                     should be either GRE or UDP/GUE.
- *
- *             BPF_LWT_ENCAP_SEG6*** types can be called by bpf programs of
- *             type BPF_PROG_TYPE_LWT_IN; BPF_LWT_ENCAP_IP type can be called
- *             by bpf programs of types BPF_PROG_TYPE_LWT_IN and
- *             BPF_PROG_TYPE_LWT_XMIT.
- *
- *             A call to this helper is susceptible to change the underlaying
+ *                     additional headers, up to **LWT_BPF_MAX_HEADROOM**
+ *                     total bytes in all prepended headers. Please note that
+ *                     if **skb_is_gso**\ (*skb*) is true, no more than two
+ *                     headers can be prepended, and the inner header, if
+ *                     present, should be either GRE or UDP/GUE.
+ *
+ *             **BPF_LWT_ENCAP_SEG6**\ \* types can be called by BPF programs
+ *             of type **BPF_PROG_TYPE_LWT_IN**; **BPF_LWT_ENCAP_IP** type can
+ *             be called by bpf programs of types **BPF_PROG_TYPE_LWT_IN** and
+ *             **BPF_PROG_TYPE_LWT_XMIT**.
+ *
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -2087,7 +2087,7 @@ union bpf_attr {
  *             inside the outermost IPv6 Segment Routing Header can be
  *             modified through this helper.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -2103,7 +2103,7 @@ union bpf_attr {
  *             after the segments are accepted. *delta* can be as well
  *             positive (growing) as negative (shrinking).
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -2126,13 +2126,13 @@ union bpf_attr {
  *                     Type of *param*: **int**.
  *             **SEG6_LOCAL_ACTION_END_B6**
  *                     End.B6 action: Endpoint bound to an SRv6 policy.
- *                     Type of param: **struct ipv6_sr_hdr**.
+ *                     Type of *param*: **struct ipv6_sr_hdr**.
  *             **SEG6_LOCAL_ACTION_END_B6_ENCAP**
  *                     End.B6.Encap action: Endpoint bound to an SRv6
  *                     encapsulation policy.
- *                     Type of param: **struct ipv6_sr_hdr**.
+ *                     Type of *param*: **struct ipv6_sr_hdr**.
  *
- *             A call to this helper is susceptible to change the underlaying
+ *             A call to this helper is susceptible to change the underlying
  *             packet buffer. Therefore, at load time, all checks on pointers
  *             previously done by the verifier are invalidated and must be
  *             performed again, if the helper is used in combination with
@@ -2285,7 +2285,8 @@ union bpf_attr {
  *     Return
  *             Pointer to **struct bpf_sock**, or **NULL** in case of failure.
  *             For sockets with reuseport option, the **struct bpf_sock**
- *             result is from **reuse->socks**\ [] using the hash of the tuple.
+ *             result is from *reuse*\ **->socks**\ [] using the hash of the
+ *             tuple.
  *
  * struct bpf_sock *bpf_sk_lookup_udp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags)
  *     Description
@@ -2321,7 +2322,8 @@ union bpf_attr {
  *     Return
  *             Pointer to **struct bpf_sock**, or **NULL** in case of failure.
  *             For sockets with reuseport option, the **struct bpf_sock**
- *             result is from **reuse->socks**\ [] using the hash of the tuple.
+ *             result is from *reuse*\ **->socks**\ [] using the hash of the
+ *             tuple.
  *
  * int bpf_sk_release(struct bpf_sock *sock)
  *     Description
@@ -2490,31 +2492,34 @@ union bpf_attr {
  *             network namespace *netns*. The return value must be checked,
  *             and if non-**NULL**, released via **bpf_sk_release**\ ().
  *
- *             This function is identical to bpf_sk_lookup_tcp, except that it
- *             also returns timewait or request sockets. Use bpf_sk_fullsock
- *             or bpf_tcp_socket to access the full structure.
+ *             This function is identical to **bpf_sk_lookup_tcp**\ (), except
+ *             that it also returns timewait or request sockets. Use
+ *             **bpf_sk_fullsock**\ () or **bpf_tcp_sock**\ () to access the
+ *             full structure.
  *
  *             This helper is available only if the kernel was compiled with
  *             **CONFIG_NET** configuration option.
  *     Return
  *             Pointer to **struct bpf_sock**, or **NULL** in case of failure.
  *             For sockets with reuseport option, the **struct bpf_sock**
- *             result is from **reuse->socks**\ [] using the hash of the tuple.
+ *             result is from *reuse*\ **->socks**\ [] using the hash of the
+ *             tuple.
  *
  * int bpf_tcp_check_syncookie(struct bpf_sock *sk, void *iph, u32 iph_len, struct tcphdr *th, u32 th_len)
  *     Description
- *             Check whether iph and th contain a valid SYN cookie ACK for
- *             the listening socket in sk.
+ *             Check whether *iph* and *th* contain a valid SYN cookie ACK for
+ *             the listening socket in *sk*.
  *
- *             iph points to the start of the IPv4 or IPv6 header, while
- *             iph_len contains sizeof(struct iphdr) or sizeof(struct ip6hdr).
+ *             *iph* points to the start of the IPv4 or IPv6 header, while
+ *             *iph_len* contains **sizeof**\ (**struct iphdr**) or
+ *             **sizeof**\ (**struct ip6hdr**).
  *
- *             th points to the start of the TCP header, while th_len contains
- *             sizeof(struct tcphdr).
+ *             *th* points to the start of the TCP header, while *th_len*
+ *             contains **sizeof**\ (**struct tcphdr**).
  *
  *     Return
- *             0 if iph and th are a valid SYN cookie ACK, or a negative error
- *             otherwise.
+ *             0 if *iph* and *th* are a valid SYN cookie ACK, or a negative
+ *             error otherwise.
  *
  * int bpf_sysctl_get_name(struct bpf_sysctl *ctx, char *buf, size_t buf_len, u64 flags)
  *     Description
@@ -2592,17 +2597,17 @@ union bpf_attr {
  *             and save the result in *res*.
  *
  *             The string may begin with an arbitrary amount of white space
- *             (as determined by isspace(3)) followed by a single optional '-'
- *             sign.
+ *             (as determined by **isspace**\ (3)) followed by a single
+ *             optional '**-**' sign.
  *
  *             Five least significant bits of *flags* encode base, other bits
  *             are currently unused.
  *
  *             Base must be either 8, 10, 16 or 0 to detect it automatically
- *             similar to user space strtol(3).
+ *             similar to user space **strtol**\ (3).
  *     Return
  *             Number of characters consumed on success. Must be positive but
- *             no more than buf_len.
+ *             no more than *buf_len*.
  *
  *             **-EINVAL** if no valid digits were found or unsupported base
  *             was provided.
@@ -2616,16 +2621,16 @@ union bpf_attr {
  *             given base and save the result in *res*.
  *
  *             The string may begin with an arbitrary amount of white space
- *             (as determined by isspace(3)).
+ *             (as determined by **isspace**\ (3)).
  *
  *             Five least significant bits of *flags* encode base, other bits
  *             are currently unused.
  *
  *             Base must be either 8, 10, 16 or 0 to detect it automatically
- *             similar to user space strtoul(3).
+ *             similar to user space **strtoul**\ (3).
  *     Return
  *             Number of characters consumed on success. Must be positive but
- *             no more than buf_len.
+ *             no more than *buf_len*.
  *
  *             **-EINVAL** if no valid digits were found or unsupported base
  *             was provided.
@@ -2634,26 +2639,26 @@ union bpf_attr {
  *
  * void *bpf_sk_storage_get(struct bpf_map *map, struct bpf_sock *sk, void *value, u64 flags)
  *     Description
- *             Get a bpf-local-storage from a sk.
+ *             Get a bpf-local-storage from a *sk*.
  *
  *             Logically, it could be thought of getting the value from
  *             a *map* with *sk* as the **key**.  From this
  *             perspective,  the usage is not much different from
- *             **bpf_map_lookup_elem(map, &sk)** except this
- *             helper enforces the key must be a **bpf_fullsock()**
- *             and the map must be a BPF_MAP_TYPE_SK_STORAGE also.
+ *             **bpf_map_lookup_elem**\ (*map*, **&**\ *sk*) except this
+ *             helper enforces the key must be a full socket and the map must
+ *             be a **BPF_MAP_TYPE_SK_STORAGE** also.
  *
  *             Underneath, the value is stored locally at *sk* instead of
- *             the map.  The *map* is used as the bpf-local-storage **type**.
- *             The bpf-local-storage **type** (i.e. the *map*) is searched
- *             against all bpf-local-storages residing at sk.
+ *             the *map*.  The *map* is used as the bpf-local-storage
+ *             "type". The bpf-local-storage "type" (i.e. the *map*) is
+ *             searched against all bpf-local-storages residing at *sk*.
  *
- *             An optional *flags* (BPF_SK_STORAGE_GET_F_CREATE) can be
+ *             An optional *flags* (**BPF_SK_STORAGE_GET_F_CREATE**) can be
  *             used such that a new bpf-local-storage will be
  *             created if one does not exist.  *value* can be used
- *             together with BPF_SK_STORAGE_GET_F_CREATE to specify
+ *             together with **BPF_SK_STORAGE_GET_F_CREATE** to specify
  *             the initial value of a bpf-local-storage.  If *value* is
- *             NULL, the new bpf-local-storage will be zero initialized.
+ *             **NULL**, the new bpf-local-storage will be zero initialized.
  *     Return
  *             A bpf-local-storage pointer is returned on success.
  *
@@ -2662,7 +2667,7 @@ union bpf_attr {
  *
  * int bpf_sk_storage_delete(struct bpf_map *map, struct bpf_sock *sk)
  *     Description
- *             Delete a bpf-local-storage from a sk.
+ *             Delete a bpf-local-storage from a *sk*.
  *     Return
  *             0 on success.
  *
index 11a65db..7e3b79d 100644 (file)
@@ -44,6 +44,7 @@
 #include "btf.h"
 #include "str_error.h"
 #include "libbpf_util.h"
+#include "libbpf_internal.h"
 
 #ifndef EM_BPF
 #define EM_BPF 247
@@ -128,6 +129,10 @@ struct bpf_capabilities {
        __u32 name:1;
        /* v5.2: kernel support for global data sections. */
        __u32 global_data:1;
+       /* BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO support */
+       __u32 btf_func:1;
+       /* BTF_KIND_VAR and BTF_KIND_DATASEC support */
+       __u32 btf_datasec:1;
 };
 
 /*
@@ -1021,6 +1026,74 @@ static bool section_have_execinstr(struct bpf_object *obj, int idx)
        return false;
 }
 
+static void bpf_object__sanitize_btf(struct bpf_object *obj)
+{
+       bool has_datasec = obj->caps.btf_datasec;
+       bool has_func = obj->caps.btf_func;
+       struct btf *btf = obj->btf;
+       struct btf_type *t;
+       int i, j, vlen;
+       __u16 kind;
+
+       if (!obj->btf || (has_func && has_datasec))
+               return;
+
+       for (i = 1; i <= btf__get_nr_types(btf); i++) {
+               t = (struct btf_type *)btf__type_by_id(btf, i);
+               kind = BTF_INFO_KIND(t->info);
+
+               if (!has_datasec && kind == BTF_KIND_VAR) {
+                       /* replace VAR with INT */
+                       t->info = BTF_INFO_ENC(BTF_KIND_INT, 0, 0);
+                       t->size = sizeof(int);
+                       *(int *)(t+1) = BTF_INT_ENC(0, 0, 32);
+               } else if (!has_datasec && kind == BTF_KIND_DATASEC) {
+                       /* replace DATASEC with STRUCT */
+                       struct btf_var_secinfo *v = (void *)(t + 1);
+                       struct btf_member *m = (void *)(t + 1);
+                       struct btf_type *vt;
+                       char *name;
+
+                       name = (char *)btf__name_by_offset(btf, t->name_off);
+                       while (*name) {
+                               if (*name == '.')
+                                       *name = '_';
+                               name++;
+                       }
+
+                       vlen = BTF_INFO_VLEN(t->info);
+                       t->info = BTF_INFO_ENC(BTF_KIND_STRUCT, 0, vlen);
+                       for (j = 0; j < vlen; j++, v++, m++) {
+                               /* order of field assignments is important */
+                               m->offset = v->offset * 8;
+                               m->type = v->type;
+                               /* preserve variable name as member name */
+                               vt = (void *)btf__type_by_id(btf, v->type);
+                               m->name_off = vt->name_off;
+                       }
+               } else if (!has_func && kind == BTF_KIND_FUNC_PROTO) {
+                       /* replace FUNC_PROTO with ENUM */
+                       vlen = BTF_INFO_VLEN(t->info);
+                       t->info = BTF_INFO_ENC(BTF_KIND_ENUM, 0, vlen);
+                       t->size = sizeof(__u32); /* kernel enforced */
+               } else if (!has_func && kind == BTF_KIND_FUNC) {
+                       /* replace FUNC with TYPEDEF */
+                       t->info = BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0);
+               }
+       }
+}
+
+static void bpf_object__sanitize_btf_ext(struct bpf_object *obj)
+{
+       if (!obj->btf_ext)
+               return;
+
+       if (!obj->caps.btf_func) {
+               btf_ext__free(obj->btf_ext);
+               obj->btf_ext = NULL;
+       }
+}
+
 static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
 {
        Elf *elf = obj->efile.elf;
@@ -1164,8 +1237,10 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
                        obj->btf = NULL;
                } else {
                        err = btf__finalize_data(obj, obj->btf);
-                       if (!err)
+                       if (!err) {
+                               bpf_object__sanitize_btf(obj);
                                err = btf__load(obj->btf);
+                       }
                        if (err) {
                                pr_warning("Error finalizing and loading %s into kernel: %d. Ignored and continue.\n",
                                           BTF_ELF_SEC, err);
@@ -1187,6 +1262,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
                                           BTF_EXT_ELF_SEC,
                                           PTR_ERR(obj->btf_ext));
                                obj->btf_ext = NULL;
+                       } else {
+                               bpf_object__sanitize_btf_ext(obj);
                        }
                }
        }
@@ -1556,12 +1633,63 @@ bpf_object__probe_global_data(struct bpf_object *obj)
        return 0;
 }
 
+static int bpf_object__probe_btf_func(struct bpf_object *obj)
+{
+       const char strs[] = "\0int\0x\0a";
+       /* void x(int a) {} */
+       __u32 types[] = {
+               /* int */
+               BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+               /* FUNC_PROTO */                                /* [2] */
+               BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 1), 0),
+               BTF_PARAM_ENC(7, 1),
+               /* FUNC x */                                    /* [3] */
+               BTF_TYPE_ENC(5, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 0), 2),
+       };
+       int res;
+
+       res = libbpf__probe_raw_btf((char *)types, sizeof(types),
+                                   strs, sizeof(strs));
+       if (res < 0)
+               return res;
+       if (res > 0)
+               obj->caps.btf_func = 1;
+       return 0;
+}
+
+static int bpf_object__probe_btf_datasec(struct bpf_object *obj)
+{
+       const char strs[] = "\0x\0.data";
+       /* static int a; */
+       __u32 types[] = {
+               /* int */
+               BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
+               /* VAR x */                                     /* [2] */
+               BTF_TYPE_ENC(1, BTF_INFO_ENC(BTF_KIND_VAR, 0, 0), 1),
+               BTF_VAR_STATIC,
+               /* DATASEC val */                               /* [3] */
+               BTF_TYPE_ENC(3, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
+               BTF_VAR_SECINFO_ENC(2, 0, 4),
+       };
+       int res;
+
+       res = libbpf__probe_raw_btf((char *)types, sizeof(types),
+                                   strs, sizeof(strs));
+       if (res < 0)
+               return res;
+       if (res > 0)
+               obj->caps.btf_datasec = 1;
+       return 0;
+}
+
 static int
 bpf_object__probe_caps(struct bpf_object *obj)
 {
        int (*probe_fn[])(struct bpf_object *obj) = {
                bpf_object__probe_name,
                bpf_object__probe_global_data,
+               bpf_object__probe_btf_func,
+               bpf_object__probe_btf_datasec,
        };
        int i, ret;
 
diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h
new file mode 100644 (file)
index 0000000..789e435
--- /dev/null
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
+
+/*
+ * Internal libbpf helpers.
+ *
+ * Copyright (c) 2019 Facebook
+ */
+
+#ifndef __LIBBPF_LIBBPF_INTERNAL_H
+#define __LIBBPF_LIBBPF_INTERNAL_H
+
+#define BTF_INFO_ENC(kind, kind_flag, vlen) \
+       ((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
+#define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type)
+#define BTF_INT_ENC(encoding, bits_offset, nr_bits) \
+       ((encoding) << 24 | (bits_offset) << 16 | (nr_bits))
+#define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \
+       BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \
+       BTF_INT_ENC(encoding, bits_offset, bits)
+#define BTF_MEMBER_ENC(name, type, bits_offset) (name), (type), (bits_offset)
+#define BTF_PARAM_ENC(name, type) (name), (type)
+#define BTF_VAR_SECINFO_ENC(type, offset, size) (type), (offset), (size)
+
+int libbpf__probe_raw_btf(const char *raw_types, size_t types_len,
+                         const char *str_sec, size_t str_len);
+
+#endif /* __LIBBPF_LIBBPF_INTERNAL_H */
index a2c64a9..5e2aa83 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "bpf.h"
 #include "libbpf.h"
+#include "libbpf_internal.h"
 
 static bool grep(const char *buffer, const char *pattern)
 {
@@ -132,21 +133,43 @@ bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex)
        return errno != EINVAL && errno != EOPNOTSUPP;
 }
 
-static int load_btf(void)
+int libbpf__probe_raw_btf(const char *raw_types, size_t types_len,
+                         const char *str_sec, size_t str_len)
 {
-#define BTF_INFO_ENC(kind, kind_flag, vlen) \
-       ((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
-#define BTF_TYPE_ENC(name, info, size_or_type) \
-       (name), (info), (size_or_type)
-#define BTF_INT_ENC(encoding, bits_offset, nr_bits) \
-       ((encoding) << 24 | (bits_offset) << 16 | (nr_bits))
-#define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \
-       BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \
-       BTF_INT_ENC(encoding, bits_offset, bits)
-#define BTF_MEMBER_ENC(name, type, bits_offset) \
-       (name), (type), (bits_offset)
-
-       const char btf_str_sec[] = "\0bpf_spin_lock\0val\0cnt\0l";
+       struct btf_header hdr = {
+               .magic = BTF_MAGIC,
+               .version = BTF_VERSION,
+               .hdr_len = sizeof(struct btf_header),
+               .type_len = types_len,
+               .str_off = types_len,
+               .str_len = str_len,
+       };
+       int btf_fd, btf_len;
+       __u8 *raw_btf;
+
+       btf_len = hdr.hdr_len + hdr.type_len + hdr.str_len;
+       raw_btf = malloc(btf_len);
+       if (!raw_btf)
+               return -ENOMEM;
+
+       memcpy(raw_btf, &hdr, sizeof(hdr));
+       memcpy(raw_btf + hdr.hdr_len, raw_types, hdr.type_len);
+       memcpy(raw_btf + hdr.hdr_len + hdr.type_len, str_sec, hdr.str_len);
+
+       btf_fd = bpf_load_btf(raw_btf, btf_len, NULL, 0, false);
+       if (btf_fd < 0) {
+               free(raw_btf);
+               return 0;
+       }
+
+       close(btf_fd);
+       free(raw_btf);
+       return 1;
+}
+
+static int load_sk_storage_btf(void)
+{
+       const char strs[] = "\0bpf_spin_lock\0val\0cnt\0l";
        /* struct bpf_spin_lock {
         *   int val;
         * };
@@ -155,7 +178,7 @@ static int load_btf(void)
         *   struct bpf_spin_lock l;
         * };
         */
-       __u32 btf_raw_types[] = {
+       __u32 types[] = {
                /* int */
                BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
                /* struct bpf_spin_lock */                      /* [2] */
@@ -166,23 +189,9 @@ static int load_btf(void)
                BTF_MEMBER_ENC(19, 1, 0), /* int cnt; */
                BTF_MEMBER_ENC(23, 2, 32),/* struct bpf_spin_lock l; */
        };
-       struct btf_header btf_hdr = {
-               .magic = BTF_MAGIC,
-               .version = BTF_VERSION,
-               .hdr_len = sizeof(struct btf_header),
-               .type_len = sizeof(btf_raw_types),
-               .str_off = sizeof(btf_raw_types),
-               .str_len = sizeof(btf_str_sec),
-       };
-       __u8 raw_btf[sizeof(struct btf_header) + sizeof(btf_raw_types) +
-                    sizeof(btf_str_sec)];
-
-       memcpy(raw_btf, &btf_hdr, sizeof(btf_hdr));
-       memcpy(raw_btf + sizeof(btf_hdr), btf_raw_types, sizeof(btf_raw_types));
-       memcpy(raw_btf + sizeof(btf_hdr) + sizeof(btf_raw_types),
-              btf_str_sec, sizeof(btf_str_sec));
 
-       return bpf_load_btf(raw_btf, sizeof(raw_btf), 0, 0, 0);
+       return libbpf__probe_raw_btf((char *)types, sizeof(types),
+                                    strs, sizeof(strs));
 }
 
 bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
@@ -222,7 +231,7 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
                value_size = 8;
                max_entries = 0;
                map_flags = BPF_F_NO_PREALLOC;
-               btf_fd = load_btf();
+               btf_fd = load_sk_storage_btf();
                if (btf_fd < 0)
                        return false;
                break;
index 8df526c..4dd11a5 100644 (file)
@@ -306,7 +306,7 @@ ignore it:
 
 - To skip validation of a file, add
 
-    OBJECT_FILES_NON_STANDARD_filename.o := n
+    OBJECT_FILES_NON_STANDARD_filename.o := y
 
   to the Makefile.
 
index ac743a1..7325d89 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/hashtable.h>
 #include <linux/kernel.h>
 
+#define FAKE_JUMP_OFFSET -1
+
 struct alternative {
        struct list_head list;
        struct instruction *insn;
@@ -568,7 +570,7 @@ static int add_jump_destinations(struct objtool_file *file)
                    insn->type != INSN_JUMP_UNCONDITIONAL)
                        continue;
 
-               if (insn->ignore)
+               if (insn->ignore || insn->offset == FAKE_JUMP_OFFSET)
                        continue;
 
                rela = find_rela_by_dest_range(insn->sec, insn->offset,
@@ -745,10 +747,10 @@ static int handle_group_alt(struct objtool_file *file,
                clear_insn_state(&fake_jump->state);
 
                fake_jump->sec = special_alt->new_sec;
-               fake_jump->offset = -1;
+               fake_jump->offset = FAKE_JUMP_OFFSET;
                fake_jump->type = INSN_JUMP_UNCONDITIONAL;
                fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
-               fake_jump->ignore = true;
+               fake_jump->func = orig_insn->func;
        }
 
        if (!special_alt->new_len) {
@@ -1957,7 +1959,8 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
                        return 1;
                }
 
-               func = insn->func ? insn->func->pfunc : NULL;
+               if (insn->func)
+                       func = insn->func->pfunc;
 
                if (func && insn->ignore) {
                        WARN_FUNC("BUG: why am I validating an ignored function?",
index 46e4c2f..9b75344 100644 (file)
@@ -14,9 +14,12 @@ MAKEFLAGS += -r
 
 CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
 
-ALL_TARGETS := pcitest pcitest.sh
+ALL_TARGETS := pcitest
 ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
 
+SCRIPTS := pcitest.sh
+ALL_SCRIPTS := $(patsubst %,$(OUTPUT)%,$(SCRIPTS))
+
 all: $(ALL_PROGRAMS)
 
 export srctree OUTPUT CC LD CFLAGS
@@ -46,6 +49,9 @@ install: $(ALL_PROGRAMS)
        install -d -m 755 $(DESTDIR)$(bindir);          \
        for program in $(ALL_PROGRAMS); do              \
                install $$program $(DESTDIR)$(bindir);  \
+       done;                                           \
+       for script in $(ALL_SCRIPTS); do                \
+               install $$script $(DESTDIR)$(bindir);   \
        done
 
 FORCE:
index ec4d51f..5fa5c2b 100644 (file)
@@ -140,6 +140,7 @@ static void run_test(struct pci_test *test)
        }
 
        fflush(stdout);
+       return (ret < 0) ? ret : 1 - ret; /* return 0 if test succeeded */
 }
 
 int main(int argc, char **argv)
@@ -162,7 +163,7 @@ int main(int argc, char **argv)
        /* set default endpoint device */
        test->device = "/dev/pci-endpoint-test.0";
 
-       while ((c = getopt(argc, argv, "D:b:m:x:i:Ilrwcs:")) != EOF)
+       while ((c = getopt(argc, argv, "D:b:m:x:i:Ilhrwcs:")) != EOF)
        switch (c) {
        case 'D':
                test->device = optarg;
@@ -206,7 +207,6 @@ int main(int argc, char **argv)
        case 's':
                test->size = strtoul(optarg, NULL, 0);
                continue;
-       case '?':
        case 'h':
        default:
 usage:
@@ -224,10 +224,10 @@ usage:
                        "\t-w                   Write buffer test\n"
                        "\t-c                   Copy buffer test\n"
                        "\t-s <size>            Size of buffer {default: 100KB}\n",
+                       "\t-h                   Print this help message\n",
                        argv[0]);
                return -EINVAL;
        }
 
-       run_test(test);
-       return 0;
+       return run_test(test);
 }
index 1598b4f..045f5f7 100644 (file)
@@ -9,7 +9,7 @@ ifeq ("$(origin O)", "command line")
 endif
 
 turbostat : turbostat.c
-override CFLAGS +=     -Wall
+override CFLAGS +=     -Wall -I../../../include
 override CFLAGS +=     -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
 override CFLAGS +=     -DINTEL_FAMILY_HEADER='"../../../../arch/x86/include/asm/intel-family.h"'
 
index ae7a0e0..1fdeef8 100644 (file)
@@ -9,7 +9,7 @@ ifeq ("$(origin O)", "command line")
 endif
 
 x86_energy_perf_policy : x86_energy_perf_policy.c
-override CFLAGS +=     -Wall
+override CFLAGS +=     -Wall -I../../../include
 override CFLAGS +=     -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
 
 %: %.c
index 275ad8a..4711f57 100755 (executable)
@@ -64,6 +64,7 @@ my %default = (
     "STOP_TEST_AFTER"          => 600,
     "MAX_MONITOR_WAIT"         => 1800,
     "GRUB_REBOOT"              => "grub2-reboot",
+    "GRUB_BLS_GET"             => "grubby --info=ALL",
     "SYSLINUX"                 => "extlinux",
     "SYSLINUX_PATH"            => "/boot/extlinux",
     "CONNECT_TIMEOUT"          => 25,
@@ -125,6 +126,7 @@ my $last_grub_menu;
 my $grub_file;
 my $grub_number;
 my $grub_reboot;
+my $grub_bls_get;
 my $syslinux;
 my $syslinux_path;
 my $syslinux_label;
@@ -295,6 +297,7 @@ my %option_map = (
     "GRUB_MENU"                        => \$grub_menu,
     "GRUB_FILE"                        => \$grub_file,
     "GRUB_REBOOT"              => \$grub_reboot,
+    "GRUB_BLS_GET"             => \$grub_bls_get,
     "SYSLINUX"                 => \$syslinux,
     "SYSLINUX_PATH"            => \$syslinux_path,
     "SYSLINUX_LABEL"           => \$syslinux_label,
@@ -440,7 +443,7 @@ EOF
     ;
 $config_help{"REBOOT_TYPE"} = << "EOF"
  Way to reboot the box to the test kernel.
- Only valid options so far are "grub", "grub2", "syslinux", and "script".
+ Only valid options so far are "grub", "grub2", "grub2bls", "syslinux", and "script".
 
  If you specify grub, it will assume grub version 1
  and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
@@ -454,6 +457,8 @@ $config_help{"REBOOT_TYPE"} = << "EOF"
  If you specify grub2, then you also need to specify both \$GRUB_MENU
  and \$GRUB_FILE.
 
+ If you specify grub2bls, then you also need to specify \$GRUB_MENU.
+
  If you specify syslinux, then you may use SYSLINUX to define the syslinux
  command (defaults to extlinux), and SYSLINUX_PATH to specify the path to
  the syslinux install (defaults to /boot/extlinux). But you have to specify
@@ -479,6 +484,9 @@ $config_help{"GRUB_MENU"} = << "EOF"
  menu must be a non-nested menu. Add the quotes used in the menu
  to guarantee your selection, as the first menuentry with the content
  of \$GRUB_MENU that is found will be used.
+
+ For grub2bls, \$GRUB_MENU is searched on the result of \$GRUB_BLS_GET
+ command for the lines that begin with "title".
 EOF
     ;
 $config_help{"GRUB_FILE"} = << "EOF"
@@ -695,7 +703,7 @@ sub get_mandatory_configs {
        }
     }
 
-    if ($rtype eq "grub") {
+    if (($rtype eq "grub") or ($rtype eq "grub2bls")) {
        get_mandatory_config("GRUB_MENU");
     }
 
@@ -1871,36 +1879,37 @@ sub run_scp_mod {
     return run_scp($src, $dst, $cp_scp);
 }
 
-sub get_grub2_index {
+sub _get_grub_index {
+
+    my ($command, $target, $skip) = @_;
 
     return if (defined($grub_number) && defined($last_grub_menu) &&
               $last_grub_menu eq $grub_menu && defined($last_machine) &&
               $last_machine eq $machine);
 
-    doprint "Find grub2 menu ... ";
+    doprint "Find $reboot_type menu ... ";
     $grub_number = -1;
 
     my $ssh_grub = $ssh_exec;
-    $ssh_grub =~ s,\$SSH_COMMAND,cat $grub_file,g;
+    $ssh_grub =~ s,\$SSH_COMMAND,$command,g;
 
     open(IN, "$ssh_grub |")
-       or dodie "unable to get $grub_file";
+       or dodie "unable to execute $command";
 
     my $found = 0;
-    my $grub_menu_qt = quotemeta($grub_menu);
 
     while (<IN>) {
-       if (/^menuentry.*$grub_menu_qt/) {
+       if (/$target/) {
            $grub_number++;
            $found = 1;
            last;
-       } elsif (/^menuentry\s|^submenu\s/) {
+       } elsif (/$skip/) {
            $grub_number++;
        }
     }
     close(IN);
 
-    dodie "Could not find '$grub_menu' in $grub_file on $machine"
+    dodie "Could not find '$grub_menu' through $command on $machine"
        if (!$found);
     doprint "$grub_number\n";
     $last_grub_menu = $grub_menu;
@@ -1909,46 +1918,34 @@ sub get_grub2_index {
 
 sub get_grub_index {
 
-    if ($reboot_type eq "grub2") {
-       get_grub2_index;
-       return;
-    }
+    my $command;
+    my $target;
+    my $skip;
+    my $grub_menu_qt;
 
-    if ($reboot_type ne "grub") {
+    if ($reboot_type !~ /^grub/) {
        return;
     }
-    return if (defined($grub_number) && defined($last_grub_menu) &&
-              $last_grub_menu eq $grub_menu && defined($last_machine) &&
-              $last_machine eq $machine);
 
-    doprint "Find grub menu ... ";
-    $grub_number = -1;
-
-    my $ssh_grub = $ssh_exec;
-    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
-
-    open(IN, "$ssh_grub |")
-       or dodie "unable to get menu.lst";
-
-    my $found = 0;
-    my $grub_menu_qt = quotemeta($grub_menu);
+    $grub_menu_qt = quotemeta($grub_menu);
 
-    while (<IN>) {
-       if (/^\s*title\s+$grub_menu_qt\s*$/) {
-           $grub_number++;
-           $found = 1;
-           last;
-       } elsif (/^\s*title\s/) {
-           $grub_number++;
-       }
+    if ($reboot_type eq "grub") {
+       $command = "cat /boot/grub/menu.lst";
+       $target = '^\s*title\s+' . $grub_menu_qt . '\s*$';
+       $skip = '^\s*title\s';
+    } elsif ($reboot_type eq "grub2") {
+       $command = "cat $grub_file";
+       $target = '^menuentry.*' . $grub_menu_qt;
+       $skip = '^menuentry\s|^submenu\s';
+    } elsif ($reboot_type eq "grub2bls") {
+        $command = $grub_bls_get;
+        $target = '^title=.*' . $grub_menu_qt;
+        $skip = '^title=';
+    } else {
+       return;
     }
-    close(IN);
 
-    dodie "Could not find '$grub_menu' in /boot/grub/menu on $machine"
-       if (!$found);
-    doprint "$grub_number\n";
-    $last_grub_menu = $grub_menu;
-    $last_machine = $machine;
+    _get_grub_index($command, $target, $skip);
 }
 
 sub wait_for_input
@@ -4303,7 +4300,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
 
     if (!$buildonly) {
        $target = "$ssh_user\@$machine";
-       if ($reboot_type eq "grub") {
+       if (($reboot_type eq "grub") or ($reboot_type eq "grub2bls")) {
            dodie "GRUB_MENU not defined" if (!defined($grub_menu));
        } elsif ($reboot_type eq "grub2") {
            dodie "GRUB_MENU not defined" if (!defined($grub_menu));
@@ -4423,7 +4420,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
 }
 
 if (defined($final_post_ktest)) {
-    run_command $final_post_ktest;
+
+    my $cp_final_post_ktest = eval_kernel_version $final_post_ktest;
+    run_command $cp_final_post_ktest;
 }
 
 if ($opt{"POWEROFF_ON_SUCCESS"}) {
index 8c893a5..c3bc933 100644 (file)
 # option to boot to with GRUB_REBOOT
 #GRUB_FILE = /boot/grub2/grub.cfg
 
-# The tool for REBOOT_TYPE = grub2 to set the next reboot kernel
+# The tool for REBOOT_TYPE = grub2 or grub2bls to set the next reboot kernel
 # to boot into (one shot mode).
 # (default grub2_reboot)
 #GRUB_REBOOT = grub2_reboot
 
 # The grub title name for the test kernel to boot
-# (Only mandatory if REBOOT_TYPE = grub or grub2)
+# (Only mandatory if REBOOT_TYPE = grub or grub2 or grub2bls)
 #
 # Note, ktest.pl will not update the grub menu.lst, you need to
 # manually add an option for the test. ktest.pl will search
 # do a: GRUB_MENU = 'Test Kernel'
 # For customizing, add your entry in /etc/grub.d/40_custom.
 #
+# For grub2bls, a search of "title"s are done. The menu is found
+# by searching for the contents of GRUB_MENU in the line that starts
+# with "title".
+#
 #GRUB_MENU = Test Kernel
 
 # For REBOOT_TYPE = syslinux, the name of the syslinux executable
 # default (undefined)
 #POST_KTEST = ${SSH} ~/dismantle_test
 
+# If you want to remove the kernel entry in Boot Loader Specification (BLS)
+# environment, use kernel-install command.
+# Here's the example:
+#POST_KTEST = ssh root@Test "/usr/bin/kernel-install remove $KERNEL_VERSION"
+
 # The default test type (default test)
 # The test types may be:
 #   build   - only build the kernel, do nothing else
 # or on some systems:
 #POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION
 
+# If you want to add the kernel entry in Boot Loader Specification (BLS)
+# environment, use kernel-install command.
+# Here's the example:
+#POST_INSTALL = ssh root@Test "/usr/bin/kernel-install add $KERNEL_VERSION /boot/vmlinuz-$KERNEL_VERSION"
+
 # If for some reason you just want to boot the kernel and you do not
 # want the test to install anything new. For example, you may just want
 # to boot test the same kernel over and over and do not want to go through
 # For REBOOT_TYPE = grub2, you must define both GRUB_MENU and
 # GRUB_FILE.
 #
+# For REBOOT_TYPE = grub2bls, you must define GRUB_MENU.
+#
 # For REBOOT_TYPE = syslinux, you must define SYSLINUX_LABEL, and
 # perhaps modify SYSLINUX (default extlinux) and SYSLINUX_PATH
 # (default /boot/extlinux)
index e1286d2..c4a9196 100644 (file)
@@ -68,8 +68,11 @@ device_dax-y += device_dax_test.o
 device_dax-y += config_check.o
 
 dax_pmem-y := $(DAX_SRC)/pmem/pmem.o
+dax_pmem-y += dax_pmem_test.o
 dax_pmem_core-y := $(DAX_SRC)/pmem/core.o
+dax_pmem_core-y += dax_pmem_core_test.o
 dax_pmem_compat-y := $(DAX_SRC)/pmem/compat.o
+dax_pmem_compat-y += dax_pmem_compat_test.o
 dax_pmem-y += config_check.o
 
 libnvdimm-y := $(NVDIMM_SRC)/core.o
diff --git a/tools/testing/nvdimm/dax_pmem_compat_test.c b/tools/testing/nvdimm/dax_pmem_compat_test.c
new file mode 100644 (file)
index 0000000..7cd1877
--- /dev/null
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright(c) 2019 Intel Corporation. All rights reserved.
+
+#include <linux/module.h>
+#include <linux/printk.h>
+#include "watermark.h"
+
+nfit_test_watermark(dax_pmem_compat);
diff --git a/tools/testing/nvdimm/dax_pmem_core_test.c b/tools/testing/nvdimm/dax_pmem_core_test.c
new file mode 100644 (file)
index 0000000..a4249cd
--- /dev/null
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright(c) 2019 Intel Corporation. All rights reserved.
+
+#include <linux/module.h>
+#include <linux/printk.h>
+#include "watermark.h"
+
+nfit_test_watermark(dax_pmem_core);
diff --git a/tools/testing/nvdimm/dax_pmem_test.c b/tools/testing/nvdimm/dax_pmem_test.c
new file mode 100644 (file)
index 0000000..fd4c94a
--- /dev/null
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright(c) 2019 Intel Corporation. All rights reserved.
+
+#include <linux/module.h>
+#include <linux/printk.h>
+#include "watermark.h"
+
+nfit_test_watermark(dax_pmem);
index 85ffdcf..bb4225c 100644 (file)
@@ -3171,6 +3171,9 @@ static __init int nfit_test_init(void)
        acpi_nfit_test();
        device_dax_test();
        mcsafe_test();
+       dax_pmem_test();
+       dax_pmem_core_test();
+       dax_pmem_compat_test();
 
        nfit_test_setup(nfit_test_lookup, nfit_test_evaluate_dsm);
 
index ed05287..43fc4f3 100644 (file)
@@ -6,6 +6,9 @@ int pmem_test(void);
 int libnvdimm_test(void);
 int acpi_nfit_test(void);
 int device_dax_test(void);
+int dax_pmem_test(void);
+int dax_pmem_core_test(void);
+int dax_pmem_compat_test(void);
 
 /*
  * dummy routine for nfit_test to validate it is linking to the properly
index 9175035..8059ce8 100644 (file)
@@ -1,4 +1,3 @@
-kselftest
 gpiogpio-event-mon
 gpiogpio-hammer
 gpioinclude/
index f2ebf8c..9781ca7 100644 (file)
@@ -71,6 +71,9 @@ override LDFLAGS =
 override MAKEFLAGS =
 endif
 
+# Append kselftest to KBUILD_OUTPUT to avoid cluttering
+# KBUILD_OUTPUT with selftest objects and headers installed
+# by selftests Makefile or lib.mk.
 ifneq ($(KBUILD_SRC),)
 override LDFLAGS =
 endif
@@ -79,19 +82,13 @@ ifneq ($(O),)
        BUILD := $(O)
 else
        ifneq ($(KBUILD_OUTPUT),)
-               BUILD := $(KBUILD_OUTPUT)
+               BUILD := $(KBUILD_OUTPUT)/kselftest
        else
                BUILD := $(shell pwd)
                DEFAULT_INSTALL_HDR_PATH := 1
        endif
 endif
 
-# KSFT_TAP_LEVEL is used from KSFT framework to prevent nested TAP header
-# printing from tests. Applicable to run_tests case where run_tests adds
-# TAP header prior running tests and when a test program invokes another
-# with system() call. Export it here to cover override RUN_TESTS defines.
-export KSFT_TAP_LEVEL=`echo 1`
-
 # Prepare for headers install
 top_srcdir ?= ../../..
 include $(top_srcdir)/scripts/subarch.include
@@ -169,14 +166,22 @@ clean_hotplug:
 run_pstore_crash:
        make -C pstore run_crash
 
-INSTALL_PATH ?= install
+# Use $BUILD as the default install root. $BUILD points to the
+# right output location for the following cases:
+# 1. output_dir=kernel_src
+# 2. a separate output directory is specified using O= KBUILD_OUTPUT
+# 3. a separate output directory is specified using KBUILD_OUTPUT
+#
+INSTALL_PATH ?= $(BUILD)/install
 INSTALL_PATH := $(abspath $(INSTALL_PATH))
 ALL_SCRIPT := $(INSTALL_PATH)/run_kselftest.sh
 
-install:
+install: all
 ifdef INSTALL_PATH
        @# Ask all targets to install their files
-       mkdir -p $(INSTALL_PATH)
+       mkdir -p $(INSTALL_PATH)/kselftest
+       install -m 744 kselftest/runner.sh $(INSTALL_PATH)/kselftest/
+       install -m 744 kselftest/prefix.pl $(INSTALL_PATH)/kselftest/
        @for TARGET in $(TARGETS); do \
                BUILD_TARGET=$$BUILD/$$TARGET;  \
                make OUTPUT=$$BUILD_TARGET -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \
@@ -186,24 +191,20 @@ ifdef INSTALL_PATH
        echo "#!/bin/sh" > $(ALL_SCRIPT)
        echo "BASE_DIR=\$$(realpath \$$(dirname \$$0))" >> $(ALL_SCRIPT)
        echo "cd \$$BASE_DIR" >> $(ALL_SCRIPT)
+       echo ". ./kselftest/runner.sh" >> $(ALL_SCRIPT)
        echo "ROOT=\$$PWD" >> $(ALL_SCRIPT)
        echo "if [ \"\$$1\" = \"--summary\" ]; then" >> $(ALL_SCRIPT)
-       echo "  OUTPUT=\$$BASE_DIR/output.log" >> $(ALL_SCRIPT)
-       echo "  cat /dev/null > \$$OUTPUT" >> $(ALL_SCRIPT)
-       echo "else" >> $(ALL_SCRIPT)
-       echo "  OUTPUT=/dev/stdout" >> $(ALL_SCRIPT)
+       echo "  logfile=\$$BASE_DIR/output.log" >> $(ALL_SCRIPT)
+       echo "  cat /dev/null > \$$logfile" >> $(ALL_SCRIPT)
        echo "fi" >> $(ALL_SCRIPT)
-       echo "export KSFT_TAP_LEVEL=1" >> $(ALL_SCRIPT)
-       echo "export skip=4" >> $(ALL_SCRIPT)
 
        for TARGET in $(TARGETS); do \
                BUILD_TARGET=$$BUILD/$$TARGET;  \
-               echo "echo ; echo TAP version 13" >> $(ALL_SCRIPT);     \
-               echo "echo Running tests in $$TARGET" >> $(ALL_SCRIPT); \
-               echo "echo ========================================" >> $(ALL_SCRIPT); \
                echo "[ -w /dev/kmsg ] && echo \"kselftest: Running tests in $$TARGET\" >> /dev/kmsg" >> $(ALL_SCRIPT); \
                echo "cd $$TARGET" >> $(ALL_SCRIPT); \
+               echo -n "run_many" >> $(ALL_SCRIPT); \
                make -s --no-print-directory OUTPUT=$$BUILD_TARGET -C $$TARGET emit_tests >> $(ALL_SCRIPT); \
+               echo "" >> $(ALL_SCRIPT);           \
                echo "cd \$$ROOT" >> $(ALL_SCRIPT); \
        done;
 
index 41e8a68..a877803 100644 (file)
@@ -32,3 +32,5 @@ test_tcpnotify_user
 test_libbpf
 test_tcp_check_syncookie_user
 alu32
+libbpf.pc
+libbpf.so.*
index 8e6fcc8..6f951d1 100644 (file)
        .result_unpriv = REJECT,
        .result = ACCEPT,
 },
+{
+       "jump test 6",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_MOV64_IMM(BPF_REG_1, 2),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 2),
+       BPF_MOV64_IMM(BPF_REG_0, 2),
+       BPF_EXIT_INSN(),
+       BPF_JMP_REG(BPF_JNE, BPF_REG_0, BPF_REG_1, 16),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, -20),
+       },
+       .result = ACCEPT,
+       .retval = 2,
+},
+{
+       "jump test 7",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 2),
+       BPF_MOV64_IMM(BPF_REG_0, 3),
+       BPF_EXIT_INSN(),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 2, 16),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_JMP_IMM(BPF_JA, 0, 0, -20),
+       },
+       .result = ACCEPT,
+       .retval = 3,
+},
+{
+       "jump test 8",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_MOV64_IMM(BPF_REG_1, 2),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 2),
+       BPF_MOV64_IMM(BPF_REG_0, 3),
+       BPF_EXIT_INSN(),
+       BPF_JMP_REG(BPF_JNE, BPF_REG_0, BPF_REG_1, 16),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_JMP_IMM(BPF_JA, 0, 0, -20),
+       },
+       .result = ACCEPT,
+       .retval = 3,
+},
+{
+       "jump/call test 9",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 2),
+       BPF_MOV64_IMM(BPF_REG_0, 3),
+       BPF_EXIT_INSN(),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 2, 16),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, -20),
+       BPF_EXIT_INSN(),
+       },
+       .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+       .result = REJECT,
+       .errstr = "jump out of range from insn 1 to 4",
+},
+{
+       "jump/call test 10",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
+       BPF_MOV64_IMM(BPF_REG_0, 3),
+       BPF_EXIT_INSN(),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 2, 16),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, -20),
+       BPF_EXIT_INSN(),
+       },
+       .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+       .result = REJECT,
+       .errstr = "last insn is not an exit or jmp",
+},
+{
+       "jump/call test 11",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 4),
+       BPF_MOV64_IMM(BPF_REG_0, 3),
+       BPF_EXIT_INSN(),
+       BPF_MOV64_IMM(BPF_REG_0, 3),
+       BPF_EXIT_INSN(),
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 2, 26),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_MOV64_IMM(BPF_REG_0, 42),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, -31),
+       BPF_EXIT_INSN(),
+       },
+       .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+       .result = ACCEPT,
+       .retval = 3,
+},
index 901b85e..8f3655e 100644 (file)
@@ -21,6 +21,8 @@
 
 #include "../kselftest.h"
 
+#define COUNT_ISN_BPS  4
+#define COUNT_WPS      4
 
 /* Breakpoint access modes */
 enum {
@@ -220,7 +222,7 @@ static void trigger_tests(void)
                        if (!local && !global)
                                continue;
 
-                       for (i = 0; i < 4; i++) {
+                       for (i = 0; i < COUNT_ISN_BPS; i++) {
                                dummy_funcs[i]();
                                check_trapped();
                        }
@@ -292,7 +294,7 @@ static void launch_instruction_breakpoints(char *buf, int local, int global)
 {
        int i;
 
-       for (i = 0; i < 4; i++) {
+       for (i = 0; i < COUNT_ISN_BPS; i++) {
                set_breakpoint_addr(dummy_funcs[i], i);
                toggle_breakpoint(i, BP_X, 1, local, global, 1);
                ptrace(PTRACE_CONT, child_pid, NULL, 0);
@@ -314,7 +316,7 @@ static void launch_watchpoints(char *buf, int mode, int len,
        else
                mode_str = "read";
 
-       for (i = 0; i < 4; i++) {
+       for (i = 0; i < COUNT_WPS; i++) {
                set_breakpoint_addr(&dummy_var[i], i);
                toggle_breakpoint(i, mode, len, local, global, 1);
                ptrace(PTRACE_CONT, child_pid, NULL, 0);
@@ -330,8 +332,15 @@ static void launch_watchpoints(char *buf, int mode, int len,
 static void launch_tests(void)
 {
        char buf[1024];
+       unsigned int tests = 0;
        int len, local, global, i;
 
+       tests += 3 * COUNT_ISN_BPS;
+       tests += sizeof(long) / 2 * 3 * COUNT_WPS;
+       tests += sizeof(long) / 2 * 3 * COUNT_WPS;
+       tests += 2;
+       ksft_set_plan(tests);
+
        /* Instruction breakpoints */
        for (local = 0; local < 2; local++) {
                for (global = 0; global < 2; global++) {
index 2d95e5a..ab59d81 100644 (file)
@@ -118,7 +118,7 @@ static bool set_watchpoint(pid_t pid, int size, int wp)
        return false;
 }
 
-static bool run_test(int wr_size, int wp_size, int wr, int wp)
+static bool arun_test(int wr_size, int wp_size, int wr, int wp)
 {
        int status;
        siginfo_t siginfo;
@@ -214,6 +214,7 @@ int main(int argc, char **argv)
        bool result;
 
        ksft_print_header();
+       ksft_set_plan(213);
 
        act.sa_handler = sigalrm;
        sigemptyset(&act.sa_mask);
index f82dcc1..cf868b5 100644 (file)
@@ -173,6 +173,7 @@ int main(int argc, char **argv)
        int opt;
        bool do_suspend = true;
        bool succeeded = true;
+       unsigned int tests = 0;
        cpu_set_t available_cpus;
        int err;
        int cpu;
@@ -191,6 +192,13 @@ int main(int argc, char **argv)
                }
        }
 
+       for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
+               if (!CPU_ISSET(cpu, &available_cpus))
+                       continue;
+               tests++;
+       }
+       ksft_set_plan(tests);
+
        if (do_suspend)
                suspend();
 
index 3ab39a6..df0ef02 100644 (file)
@@ -430,8 +430,6 @@ int main(int argc, char **argv)
 {
        char *tmp1, *tmp2, *our_path;
 
-       ksft_print_header();
-
        /* Find our path */
        tmp1 = strdup(argv[0]);
        if (!tmp1)
@@ -445,6 +443,8 @@ int main(int argc, char **argv)
        mpid = getpid();
 
        if (fork_wait()) {
+               ksft_print_header();
+               ksft_set_plan(12);
                ksft_print_msg("[RUN]\t+++ Tests with uid == 0 +++\n");
                return do_tests(0, our_path);
        }
@@ -452,6 +452,8 @@ int main(int argc, char **argv)
        ksft_print_msg("==================================================\n");
 
        if (fork_wait()) {
+               ksft_print_header();
+               ksft_set_plan(9);
                ksft_print_msg("[RUN]\t+++ Tests with uid != 0 +++\n");
                return do_tests(1, our_path);
        }
diff --git a/tools/testing/selftests/drivers/.gitignore b/tools/testing/selftests/drivers/.gitignore
new file mode 100644 (file)
index 0000000..f6aebcc
--- /dev/null
@@ -0,0 +1 @@
+/dma-buf/udmabuf
index 64073e0..b02279d 100644 (file)
@@ -6,4 +6,5 @@ execveat.moved
 execveat.path.ephemeral
 execveat.ephemeral
 execveat.denatured
-xxxxxxxx*
\ No newline at end of file
+/recursion-depth
+xxxxxxxx*
index 427c41b..33339e3 100644 (file)
@@ -1,11 +1,15 @@
 # SPDX-License-Identifier: GPL-2.0
 CFLAGS = -Wall
+CFLAGS += -Wno-nonnull
+CFLAGS += -D_GNU_SOURCE
 
 TEST_GEN_PROGS := execveat
 TEST_GEN_FILES := execveat.symlink execveat.denatured script subdir
 # Makefile is a run-time dependency, since it's accessed by the execveat test
 TEST_FILES := Makefile
 
+TEST_GEN_PROGS += recursion-depth
+
 EXTRA_CLEAN := $(OUTPUT)/subdir.moved $(OUTPUT)/execveat.moved $(OUTPUT)/xxxxx*
 
 include ../lib.mk
diff --git a/tools/testing/selftests/exec/recursion-depth.c b/tools/testing/selftests/exec/recursion-depth.c
new file mode 100644 (file)
index 0000000..2dbd5bc
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019 Alexey Dobriyan <adobriyan@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Test that pointing #! script interpreter to self doesn't recurse. */
+#include <errno.h>
+#include <sched.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mount.h>
+#include <unistd.h>
+
+int main(void)
+{
+       if (unshare(CLONE_NEWNS) == -1) {
+               if (errno == ENOSYS || errno == EPERM) {
+                       fprintf(stderr, "error: unshare, errno %d\n", errno);
+                       return 4;
+               }
+               fprintf(stderr, "error: unshare, errno %d\n", errno);
+               return 1;
+       }
+       if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) == -1) {
+               fprintf(stderr, "error: mount '/', errno %d\n", errno);
+               return 1;
+       }
+       /* Require "exec" filesystem. */
+       if (mount(NULL, "/tmp", "ramfs", 0, NULL) == -1) {
+               fprintf(stderr, "error: mount ramfs, errno %d\n", errno);
+               return 1;
+       }
+
+#define FILENAME "/tmp/1"
+
+       int fd = creat(FILENAME, 0700);
+       if (fd == -1) {
+               fprintf(stderr, "error: creat, errno %d\n", errno);
+               return 1;
+       }
+#define S "#!" FILENAME "\n"
+       if (write(fd, S, strlen(S)) != strlen(S)) {
+               fprintf(stderr, "error: write, errno %d\n", errno);
+               return 1;
+       }
+       close(fd);
+
+       int rv = execve(FILENAME, NULL, NULL);
+       if (rv == -1 && errno == ELOOP) {
+               return 0;
+       }
+       fprintf(stderr, "error: execve, rv %d, errno %d\n", rv, errno);
+       return 1;
+}
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/tracing-error-log.tc b/tools/testing/selftests/ftrace/test.d/ftrace/tracing-error-log.tc
new file mode 100644 (file)
index 0000000..021c03f
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: ftrace - test tracing error log support
+
+fail() { #msg
+    echo $1
+    exit_fail
+}
+
+# event tracing is currently the only ftrace tracer that uses the
+# tracing error_log, hence this check
+if [ ! -f set_event ]; then
+    echo "event tracing is not supported"
+    exit_unsupported
+fi
+
+ftrace_errlog_check 'event filter parse error' '((sig >= 10 && sig < 15) || dsig ^== 17) && comm != bash' 'events/signal/signal_generate/filter'
+
+exit 0
index 7b96e80..779ec11 100644 (file)
@@ -109,3 +109,15 @@ LOCALHOST=127.0.0.1
 yield() {
     ping $LOCALHOST -c 1 || sleep .001 || usleep 1 || sleep 1
 }
+
+ftrace_errlog_check() { # err-prefix command-with-error-pos-by-^ command-file
+    pos=$(echo -n "${2%^*}" | wc -c) # error position
+    command=$(echo "$2" | tr -d ^)
+    echo "Test command: $command"
+    echo > error_log
+    (! echo "$command" > "$3" ) 2> /dev/null
+    grep "$1: error:" -A 3 error_log
+    N=$(tail -n 1 error_log | wc -c)
+    # "  Command: " and "^\n" => 13
+    test $(expr 13 + $pos) -eq $N
+}
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
new file mode 100644 (file)
index 0000000..29faaec
--- /dev/null
@@ -0,0 +1,85 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: Kprobe event parser error log check
+
+[ -f kprobe_events ] || exit_unsupported # this is configurable
+
+[ -f error_log ] || exit_unsupported
+
+check_error() { # command-with-error-pos-by-^
+    ftrace_errlog_check 'trace_kprobe' "$1" 'kprobe_events'
+}
+
+if grep -q 'r\[maxactive\]' README; then
+check_error 'p^100 vfs_read'           # MAXACT_NO_KPROBE
+check_error 'r^1a111 vfs_read'         # BAD_MAXACT
+check_error 'r^100000 vfs_read'                # MAXACT_TOO_BIG
+fi
+
+check_error 'p ^non_exist_func'                # BAD_PROBE_ADDR (enoent)
+check_error 'p ^hoge-fuga'             # BAD_PROBE_ADDR (bad syntax)
+check_error 'p ^hoge+1000-1000'                # BAD_PROBE_ADDR (bad syntax)
+check_error 'r ^vfs_read+10'           # BAD_RETPROBE
+check_error 'p:^/bar vfs_read'         # NO_GROUP_NAME
+check_error 'p:^12345678901234567890123456789012345678901234567890123456789012345/bar vfs_read'        # GROUP_TOO_LONG
+
+check_error 'p:^foo.1/bar vfs_read'    # BAD_GROUP_NAME
+check_error 'p:foo/^ vfs_read'         # NO_EVENT_NAME
+check_error 'p:foo/^12345678901234567890123456789012345678901234567890123456789012345 vfs_read'        # EVENT_TOO_LONG
+check_error 'p:foo/^bar.1 vfs_read'    # BAD_EVENT_NAME
+
+check_error 'p vfs_read ^$retval'      # RETVAL_ON_PROBE
+check_error 'p vfs_read ^$stack10000'  # BAD_STACK_NUM
+
+if grep -q '$arg<N>' README; then
+check_error 'p vfs_read ^$arg10000'    # BAD_ARG_NUM
+fi
+
+check_error 'p vfs_read ^$none_var'    # BAD_VAR
+
+check_error 'p vfs_read ^%none_reg'    # BAD_REG_NAME
+check_error 'p vfs_read ^@12345678abcde'       # BAD_MEM_ADDR
+check_error 'p vfs_read ^@+10'         # FILE_ON_KPROBE
+
+check_error 'p vfs_read ^+0@0)'                # DEREF_NEED_BRACE
+check_error 'p vfs_read ^+0ab1(@0)'    # BAD_DEREF_OFFS
+check_error 'p vfs_read +0(+0(@0^)'    # DEREF_OPEN_BRACE
+
+if grep -A1 "fetcharg:" README | grep -q '\$comm' ; then
+check_error 'p vfs_read +0(^$comm)'    # COMM_CANT_DEREF
+fi
+
+check_error 'p vfs_read ^&1'           # BAD_FETCH_ARG
+
+
+# We've introduced this limitation with array support
+if grep -q ' <type>\\\[<array-size>\\\]' README; then
+check_error 'p vfs_read +0(^+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(+0(@0))))))))))))))'   # TOO_MANY_OPS?
+check_error 'p vfs_read +0(@11):u8[10^'                # ARRAY_NO_CLOSE
+check_error 'p vfs_read +0(@11):u8[10]^a'      # BAD_ARRAY_SUFFIX
+check_error 'p vfs_read +0(@11):u8[^10a]'      # BAD_ARRAY_NUM
+check_error 'p vfs_read +0(@11):u8[^256]'      # ARRAY_TOO_BIG
+fi
+
+check_error 'p vfs_read @11:^unknown_type'     # BAD_TYPE
+check_error 'p vfs_read $stack0:^string'       # BAD_STRING
+check_error 'p vfs_read @11:^b10@a/16'         # BAD_BITFIELD
+
+check_error 'p vfs_read ^arg123456789012345678901234567890=@11'        # ARG_NAME_TOO_LOG
+check_error 'p vfs_read ^=@11'                 # NO_ARG_NAME
+check_error 'p vfs_read ^var.1=@11'            # BAD_ARG_NAME
+check_error 'p vfs_read var1=@11 ^var1=@12'    # USED_ARG_NAME
+check_error 'p vfs_read ^+1234567(+1234567(+1234567(+1234567(+1234567(+1234567(@1234))))))'    # ARG_TOO_LONG
+check_error 'p vfs_read arg1=^'                        # NO_ARG_BODY
+
+# instruction boundary check is valid on x86 (at this moment)
+case $(uname -m) in
+  x86_64|i[3456]86)
+    echo 'p vfs_read' > kprobe_events
+    if grep -q FTRACE ../kprobes/list ; then
+       check_error 'p ^vfs_read+3'             # BAD_INSN_BNDRY (only if function-tracer is enabled)
+    fi
+    ;;
+esac
+
+exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/uprobe_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/kprobe/uprobe_syntax_errors.tc
new file mode 100644 (file)
index 0000000..14229d5
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: Uprobe event parser error log check
+
+[ -f uprobe_events ] || exit_unsupported # this is configurable
+
+[ -f error_log ] || exit_unsupported
+
+check_error() { # command-with-error-pos-by-^
+    ftrace_errlog_check 'trace_uprobe' "$1" 'uprobe_events'
+}
+
+check_error 'p ^/non_exist_file:100'   # FILE_NOT_FOUND
+check_error 'p ^/sys:100'              # NO_REGULAR_FILE
+check_error 'p /bin/sh:^10a'           # BAD_UPROBE_OFFS
+check_error 'p /bin/sh:10(^1a)'                # BAD_REFCNT
+check_error 'p /bin/sh:10(10^'         # REFCNT_OPEN_BRACE
+check_error 'p /bin/sh:10(10)^a'       # BAD_REFCNT_SUFFIX
+
+check_error 'p /bin/sh:10 ^@+ab'       # BAD_FILE_OFFS
+check_error 'p /bin/sh:10 ^@symbol'    # SYM_ON_UPROBE
+
+exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-extended-error-support.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-extended-error-support.tc
deleted file mode 100644 (file)
index 9912616..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-# description: event trigger - test extended error support
-
-
-fail() { #msg
-    echo $1
-    exit_fail
-}
-
-if [ ! -f set_event ]; then
-    echo "event tracing is not supported"
-    exit_unsupported
-fi
-
-if [ ! -f synthetic_events ]; then
-    echo "synthetic event is not supported"
-    exit_unsupported
-fi
-
-echo "Test extended error support"
-echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' > events/sched/sched_wakeup/trigger
-! echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' >> events/sched/sched_wakeup/trigger 2> /dev/null
-if ! grep -q "ERROR:" events/sched/sched_wakeup/hist; then
-    fail "Failed to generate extended error in histogram"
-fi
-
-exit 0
index 54cd5c4..8d20957 100644 (file)
@@ -395,6 +395,7 @@ int main(int argc, char *argv[])
        }
 
        ksft_print_header();
+       ksft_set_plan(1);
        ksft_print_msg("%s: Test requeue functionality\n", basename(argv[0]));
        ksft_print_msg(
                "\tArguments: broadcast=%d locked=%d owner=%d timeout=%ldns\n",
index 08187a1..742624c 100644 (file)
@@ -79,6 +79,7 @@ int main(int argc, char *argv[])
        }
 
        ksft_print_header();
+       ksft_set_plan(1);
        ksft_print_msg("%s: Detect mismatched requeue_pi operations\n",
               basename(argv[0]));
 
index f0542a3..a0f5934 100644 (file)
@@ -144,6 +144,7 @@ int main(int argc, char *argv[])
        }
 
        ksft_print_header();
+       ksft_set_plan(1);
        ksft_print_msg("%s: Test signal handling during requeue_pi\n",
               basename(argv[0]));
        ksft_print_msg("\tArguments: <none>\n");
index 6216de8..a458d42 100644 (file)
@@ -98,6 +98,7 @@ int main(int argc, char **argv)
        }
 
        ksft_print_header();
+       ksft_set_plan(1);
        ksft_print_msg(
                "%s: Test the futex value of private file mappings in FUTEX_WAIT\n",
                basename(argv[0]));
index bab3dfe..04b9547 100644 (file)
@@ -69,6 +69,7 @@ int main(int argc, char *argv[])
        }
 
        ksft_print_header();
+       ksft_set_plan(1);
        ksft_print_msg("%s: Block on a futex and wait for timeout\n",
               basename(argv[0]));
        ksft_print_msg("\tArguments: timeout=%ldns\n", timeout_ns);
index 2697532..3a1d12a 100644 (file)
@@ -100,6 +100,7 @@ int main(int argc, char **argv)
        }
 
        ksft_print_header();
+       ksft_set_plan(1);
        ksft_print_msg("%s: Test the uninitialized futex value in FUTEX_WAIT\n",
               basename(argv[0]));
 
index da15a63..a34a6bb 100644 (file)
@@ -65,6 +65,7 @@ int main(int argc, char *argv[])
        }
 
        ksft_print_header();
+       ksft_set_plan(1);
        ksft_print_msg("%s: Test the unexpected futex value in FUTEX_WAIT\n",
               basename(argv[0]));
 
index 47e1d99..ec15c4f 100644 (file)
@@ -33,6 +33,7 @@ struct ksft_count {
 };
 
 static struct ksft_count ksft_cnt;
+static unsigned int ksft_plan;
 
 static inline int ksft_test_num(void)
 {
@@ -61,13 +62,21 @@ static inline void ksft_print_header(void)
                printf("TAP version 13\n");
 }
 
+static inline void ksft_set_plan(unsigned int plan)
+{
+       ksft_plan = plan;
+       printf("1..%d\n", ksft_plan);
+}
+
 static inline void ksft_print_cnts(void)
 {
-       printf("Pass %d Fail %d Xfail %d Xpass %d Skip %d Error %d\n",
+       if (ksft_plan != ksft_test_num())
+               printf("# Planned tests != run tests (%u != %u)\n",
+                       ksft_plan, ksft_test_num());
+       printf("# Pass %d Fail %d Xfail %d Xpass %d Skip %d Error %d\n",
                ksft_cnt.ksft_pass, ksft_cnt.ksft_fail,
                ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass,
                ksft_cnt.ksft_xskip, ksft_cnt.ksft_error);
-       printf("1..%d\n", ksft_test_num());
 }
 
 static inline void ksft_print_msg(const char *msg, ...)
@@ -111,7 +120,7 @@ static inline void ksft_test_result_skip(const char *msg, ...)
        ksft_cnt.ksft_xskip++;
 
        va_start(args, msg);
-       printf("ok %d # skip ", ksft_test_num());
+       printf("not ok %d # SKIP ", ksft_test_num());
        vprintf(msg, args);
        va_end(args);
 }
@@ -172,7 +181,7 @@ static inline int ksft_exit_skip(const char *msg, ...)
                va_list args;
 
                va_start(args, msg);
-               printf("1..%d # Skipped: ", ksft_test_num());
+               printf("not ok %d # SKIP ", 1 + ksft_test_num());
                vprintf(msg, args);
                va_end(args);
        } else {
diff --git a/tools/testing/selftests/kselftest/prefix.pl b/tools/testing/selftests/kselftest/prefix.pl
new file mode 100755 (executable)
index 0000000..ec7e481
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+# SPDX-License-Identifier: GPL-2.0
+# Prefix all lines with "# ", unbuffered. Command being piped in may need
+# to have unbuffering forced with "stdbuf -i0 -o0 -e0 $cmd".
+use strict;
+
+binmode STDIN;
+binmode STDOUT;
+
+STDOUT->autoflush(1);
+
+my $needed = 1;
+while (1) {
+       my $char;
+       my $bytes = sysread(STDIN, $char, 1);
+       exit 0 if ($bytes == 0);
+       if ($needed) {
+               print "# ";
+               $needed = 0;
+       }
+       print $char;
+       $needed = 1 if ($char eq "\n");
+}
diff --git a/tools/testing/selftests/kselftest/runner.sh b/tools/testing/selftests/kselftest/runner.sh
new file mode 100644 (file)
index 0000000..eff3ee3
--- /dev/null
@@ -0,0 +1,86 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Runs a set of tests in a given subdirectory.
+export skip_rc=4
+export logfile=/dev/stdout
+export per_test_logging=
+
+# There isn't a shell-agnostic way to find the path of a sourced file,
+# so we must rely on BASE_DIR being set to find other tools.
+if [ -z "$BASE_DIR" ]; then
+       echo "Error: BASE_DIR must be set before sourcing." >&2
+       exit 1
+fi
+
+# If Perl is unavailable, we must fall back to line-at-a-time prefixing
+# with sed instead of unbuffered output.
+tap_prefix()
+{
+       if [ ! -x /usr/bin/perl ]; then
+               sed -e 's/^/# /'
+       else
+               "$BASE_DIR"/kselftest/prefix.pl
+       fi
+}
+
+# If stdbuf is unavailable, we must fall back to line-at-a-time piping.
+tap_unbuffer()
+{
+       if ! which stdbuf >/dev/null ; then
+               "$@"
+       else
+               stdbuf -i0 -o0 -e0 "$@"
+       fi
+}
+
+run_one()
+{
+       DIR="$1"
+       TEST="$2"
+       NUM="$3"
+
+       BASENAME_TEST=$(basename $TEST)
+
+       TEST_HDR_MSG="selftests: $DIR: $BASENAME_TEST"
+       echo "# $TEST_HDR_MSG"
+       if [ ! -x "$TEST" ]; then
+               echo -n "# Warning: file $TEST is "
+               if [ ! -e "$TEST" ]; then
+                       echo "missing!"
+               else
+                       echo "not executable, correct this."
+               fi
+               echo "not ok $test_num $TEST_HDR_MSG"
+       else
+               cd `dirname $TEST` > /dev/null
+               (((((tap_unbuffer ./$BASENAME_TEST 2>&1; echo $? >&3) |
+                       tap_prefix >&4) 3>&1) |
+                       (read xs; exit $xs)) 4>>"$logfile" &&
+               echo "ok $test_num $TEST_HDR_MSG") ||
+               (if [ $? -eq $skip_rc ]; then   \
+                       echo "not ok $test_num $TEST_HDR_MSG # SKIP"
+               else
+                       echo "not ok $test_num $TEST_HDR_MSG"
+               fi)
+               cd - >/dev/null
+       fi
+}
+
+run_many()
+{
+       echo "TAP version 13"
+       DIR=$(basename "$PWD")
+       test_num=0
+       total=$(echo "$@" | wc -w)
+       echo "1..$total"
+       for TEST in "$@"; do
+               BASENAME_TEST=$(basename $TEST)
+               test_num=$(( test_num + 1 ))
+               if [ -n "$per_test_logging" ]; then
+                       logfile="/tmp/$BASENAME_TEST"
+                       cat /dev/null > "$logfile"
+               fi
+               run_one "$DIR" "$TEST" "$test_num"
+       done
+}
index 5979fdc..0773371 100644 (file)
@@ -3,17 +3,12 @@
 CC := $(CROSS_COMPILE)gcc
 
 ifeq (0,$(MAKELEVEL))
-    ifneq ($(O),)
-       OUTPUT := $(O)
-    else
-       ifneq ($(KBUILD_OUTPUT),)
-               OUTPUT := $(KBUILD_OUTPUT)
-       else
-               OUTPUT := $(shell pwd)
-               DEFAULT_INSTALL_HDR_PATH := 1
-       endif
+    ifeq ($(OUTPUT),)
+       OUTPUT := $(shell pwd)
+       DEFAULT_INSTALL_HDR_PATH := 1
     endif
 endif
+selfdir = $(realpath $(dir $(filter %/lib.mk,$(MAKEFILE_LIST))))
 
 # The following are built by lib.mk common compile rules.
 # TEST_CUSTOM_PROGS should be used by tests that require
@@ -65,44 +60,13 @@ all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES)
 endif
 
 .ONESHELL:
-define RUN_TEST_PRINT_RESULT
-       TEST_HDR_MSG="selftests: "`basename $$PWD`:" $$BASENAME_TEST";  \
-       echo $$TEST_HDR_MSG;                                    \
-       echo "========================================";        \
-       if [ ! -x $$TEST ]; then        \
-               echo "$$TEST_HDR_MSG: Warning: file $$BASENAME_TEST is not executable, correct this.";\
-               echo "not ok 1..$$test_num $$TEST_HDR_MSG [FAIL]"; \
-       else                                    \
-               cd `dirname $$TEST` > /dev/null; \
-               if [ "X$(summary)" != "X" ]; then       \
-                       (./$$BASENAME_TEST > /tmp/$$BASENAME_TEST 2>&1 && \
-                       echo "ok 1..$$test_num $$TEST_HDR_MSG [PASS]") || \
-                       (if [ $$? -eq $$skip ]; then    \
-                               echo "not ok 1..$$test_num $$TEST_HDR_MSG [SKIP]";                              \
-                       else echo "not ok 1..$$test_num $$TEST_HDR_MSG [FAIL]";                                 \
-                       fi;)                    \
-               else                            \
-                       (./$$BASENAME_TEST &&   \
-                       echo "ok 1..$$test_num $$TEST_HDR_MSG [PASS]") ||                                               \
-                       (if [ $$? -eq $$skip ]; then \
-                               echo "not ok 1..$$test_num $$TEST_HDR_MSG [SKIP]"; \
-                       else echo "not ok 1..$$test_num $$TEST_HDR_MSG [FAIL]";                         \
-                       fi;)            \
-               fi;                             \
-               cd - > /dev/null;               \
-       fi;
-endef
-
 define RUN_TESTS
-       @export KSFT_TAP_LEVEL=`echo 1`;                \
-       test_num=`echo 0`;                              \
-       skip=`echo 4`;                                  \
-       echo "TAP version 13";                          \
-       for TEST in $(1); do                            \
-               BASENAME_TEST=`basename $$TEST`;        \
-               test_num=`echo $$test_num+1 | bc`;      \
-               $(call RUN_TEST_PRINT_RESULT,$(TEST),$(BASENAME_TEST),$(test_num),$(skip))                                              \
-       done;
+       @BASE_DIR="$(selfdir)";                 \
+       . $(selfdir)/kselftest/runner.sh;       \
+       if [ "X$(summary)" != "X" ]; then       \
+               per_test_logging=1;             \
+       fi;                                     \
+       run_many $(1)
 endef
 
 run_tests: all
@@ -139,24 +103,12 @@ else
        $(error Error: set INSTALL_PATH to use install)
 endif
 
-define EMIT_TESTS
-       @test_num=`echo 0`;                             \
+emit_tests:
        for TEST in $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS); do \
                BASENAME_TEST=`basename $$TEST`;        \
-               test_num=`echo $$test_num+1 | bc`;      \
-               TEST_HDR_MSG="selftests: "`basename $$PWD`:" $$BASENAME_TEST";  \
-               echo "echo $$TEST_HDR_MSG";     \
-               if [ ! -x $$TEST ]; then        \
-                       echo "echo \"$$TEST_HDR_MSG: Warning: file $$BASENAME_TEST is not executable, correct this.\"";         \
-                       echo "echo \"not ok 1..$$test_num $$TEST_HDR_MSG [FAIL]\""; \
-               else
-                       echo "(./$$BASENAME_TEST >> \$$OUTPUT 2>&1 && echo \"ok 1..$$test_num $$TEST_HDR_MSG [PASS]\") || (if [ \$$? -eq \$$skip ]; then echo \"not ok 1..$$test_num $$TEST_HDR_MSG [SKIP]\"; else echo \"not ok 1..$$test_num $$TEST_HDR_MSG [FAIL]\"; fi;)"; \
-               fi;             \
-       done;
-endef
-
-emit_tests:
-       $(EMIT_TESTS)
+               echo "  \\";                            \
+               echo -n "       \"$$BASENAME_TEST\"";   \
+       done;                                           \
 
 # define if isn't already. It is undefined in make O= case.
 ifeq ($(RM),)
index 6793f8e..70b4ddb 100644 (file)
@@ -304,6 +304,7 @@ static int test_membarrier_query(void)
 int main(int argc, char **argv)
 {
        ksft_print_header();
+       ksft_set_plan(13);
 
        test_membarrier_query();
        test_membarrier();
diff --git a/tools/testing/selftests/pidfd/.gitignore b/tools/testing/selftests/pidfd/.gitignore
new file mode 100644 (file)
index 0000000..822a1e6
--- /dev/null
@@ -0,0 +1 @@
+pidfd_test
index d59378a..5bae179 100644 (file)
@@ -371,6 +371,7 @@ static int test_pidfd_send_signal_syscall_support(void)
 int main(int argc, char **argv)
 {
        ksft_print_header();
+       ksft_set_plan(4);
 
        test_pidfd_send_signal_syscall_support();
        test_pidfd_send_signal_simple_success();
index c30c52e..d646953 100644 (file)
@@ -1,5 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0+ OR MIT
-CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L./ -Wl,-rpath=./
+
+ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
+CLANG_FLAGS += -no-integrated-as
+endif
+
+CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L./ -Wl,-rpath=./ \
+         $(CLANG_FLAGS)
 LDLIBS += -lpthread
 
 # Own dependencies because we only want to build against 1st prerequisite, but
index 3cea198..84f28f1 100644 (file)
@@ -5,7 +5,54 @@
  * (C) Copyright 2016-2018 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  */
 
-#define RSEQ_SIG       0x53053053
+/*
+ * RSEQ_SIG uses the udf A32 instruction with an uncommon immediate operand
+ * value 0x5de3. This traps if user-space reaches this instruction by mistake,
+ * and the uncommon operand ensures the kernel does not move the instruction
+ * pointer to attacker-controlled code on rseq abort.
+ *
+ * The instruction pattern in the A32 instruction set is:
+ *
+ * e7f5def3    udf    #24035    ; 0x5de3
+ *
+ * This translates to the following instruction pattern in the T16 instruction
+ * set:
+ *
+ * little endian:
+ * def3        udf    #243      ; 0xf3
+ * e7f5        b.n    <7f5>
+ *
+ * pre-ARMv6 big endian code:
+ * e7f5        b.n    <7f5>
+ * def3        udf    #243      ; 0xf3
+ *
+ * ARMv6+ -mbig-endian generates mixed endianness code vs data: little-endian
+ * code and big-endian data. Ensure the RSEQ_SIG data signature matches code
+ * endianness. Prior to ARMv6, -mbig-endian generates big-endian code and data
+ * (which match), so there is no need to reverse the endianness of the data
+ * representation of the signature. However, the choice between BE32 and BE8
+ * is done by the linker, so we cannot know whether code and data endianness
+ * will be mixed before the linker is invoked.
+ */
+
+#define RSEQ_SIG_CODE  0xe7f5def3
+
+#ifndef __ASSEMBLER__
+
+#define RSEQ_SIG_DATA                                                  \
+       ({                                                              \
+               int sig;                                                \
+               asm volatile ("b 2f\n\t"                                \
+                             "1: .inst " __rseq_str(RSEQ_SIG_CODE) "\n\t" \
+                             "2:\n\t"                                  \
+                             "ldr %[sig], 1b\n\t"                      \
+                             : [sig] "=r" (sig));                      \
+               sig;                                                    \
+       })
+
+#define RSEQ_SIG       RSEQ_SIG_DATA
+
+#endif
 
 #define rseq_smp_mb()  __asm__ __volatile__ ("dmb" ::: "memory", "cc")
 #define rseq_smp_rmb() __asm__ __volatile__ ("dmb" ::: "memory", "cc")
@@ -30,18 +77,35 @@ do {                                                                        \
 #include "rseq-skip.h"
 #else /* !RSEQ_SKIP_FASTPATH */
 
-#define __RSEQ_ASM_DEFINE_TABLE(version, flags,        start_ip,               \
+#define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip,       \
                                post_commit_offset, abort_ip)           \
-               ".pushsection __rseq_table, \"aw\"\n\t"                 \
+               ".pushsection __rseq_cs, \"aw\"\n\t"                    \
                ".balign 32\n\t"                                        \
+               __rseq_str(label) ":\n\t"                                       \
                ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
                ".word " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \
+               ".popsection\n\t"                                       \
+               ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t"          \
+               ".word " __rseq_str(label) "b, 0x0\n\t"                 \
                ".popsection\n\t"
 
-#define RSEQ_ASM_DEFINE_TABLE(start_ip, post_commit_ip, abort_ip)      \
-       __RSEQ_ASM_DEFINE_TABLE(0x0, 0x0, start_ip,                     \
+#define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
+       __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip,              \
                                (post_commit_ip - start_ip), abort_ip)
 
+/*
+ * Exit points of a rseq critical section consist of all instructions outside
+ * of the critical section where a critical section can either branch to or
+ * reach through the normal course of its execution. The abort IP and the
+ * post-commit IP are already part of the __rseq_cs section and should not be
+ * explicitly defined as additional exit points. Knowing all exit points is
+ * useful to assist debuggers stepping over the critical section.
+ */
+#define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)                  \
+               ".pushsection __rseq_exit_point_array, \"aw\"\n\t"      \
+               ".word " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) ", 0x0\n\t" \
+               ".popsection\n\t"
+
 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)               \
                RSEQ_INJECT_ASM(1)                                      \
                "adr r0, " __rseq_str(cs_label) "\n\t"                  \
@@ -61,7 +125,8 @@ do {                                                                 \
                __rseq_str(table_label) ":\n\t"                         \
                ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
                ".word " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \
-               ".word " __rseq_str(RSEQ_SIG) "\n\t"                    \
+               ".arm\n\t"                                              \
+               ".inst " __rseq_str(RSEQ_SIG_CODE) "\n\t"               \
                __rseq_str(label) ":\n\t"                               \
                teardown                                                \
                "b %l[" __rseq_str(abort_label) "]\n\t"
@@ -86,7 +151,12 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -148,7 +218,12 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -214,7 +289,10 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -266,7 +344,12 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -336,7 +419,12 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -407,7 +495,13 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -485,7 +579,12 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                "str %[src], %[rseq_scratch0]\n\t"
                "str %[dst], %[rseq_scratch1]\n\t"
                "str %[len], %[rseq_scratch2]\n\t"
@@ -604,7 +703,12 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                "str %[src], %[rseq_scratch0]\n\t"
                "str %[dst], %[rseq_scratch1]\n\t"
                "str %[len], %[rseq_scratch2]\n\t"
index 954f346..200dae9 100644 (file)
@@ -6,7 +6,20 @@
  * (C) Copyright 2018 - Will Deacon <will.deacon@arm.com>
  */
 
-#define RSEQ_SIG       0xd428bc00      /* BRK #0x45E0 */
+/*
+ * aarch64 -mbig-endian generates mixed endianness code vs data:
+ * little-endian code and big-endian data. Ensure the RSEQ_SIG signature
+ * matches code endianness.
+ */
+#define RSEQ_SIG_CODE  0xd428bc00      /* BRK #0x45E0.  */
+
+#ifdef __AARCH64EB__
+#define RSEQ_SIG_DATA  0x00bc28d4      /* BRK #0x45E0.  */
+#else
+#define RSEQ_SIG_DATA  RSEQ_SIG_CODE
+#endif
+
+#define RSEQ_SIG       RSEQ_SIG_DATA
 
 #define rseq_smp_mb()  __asm__ __volatile__ ("dmb ish" ::: "memory")
 #define rseq_smp_rmb() __asm__ __volatile__ ("dmb ishld" ::: "memory")
@@ -82,19 +95,35 @@ do {                                                                                \
 
 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip,               \
                                post_commit_offset, abort_ip)                   \
-       "       .pushsection    __rseq_table, \"aw\"\n"                         \
+       "       .pushsection    __rseq_cs, \"aw\"\n"                            \
        "       .balign 32\n"                                                   \
        __rseq_str(label) ":\n"                                                 \
        "       .long   " __rseq_str(version) ", " __rseq_str(flags) "\n"       \
        "       .quad   " __rseq_str(start_ip) ", "                             \
                          __rseq_str(post_commit_offset) ", "                   \
                          __rseq_str(abort_ip) "\n"                             \
+       "       .popsection\n\t"                                                \
+       "       .pushsection __rseq_cs_ptr_array, \"aw\"\n"                             \
+       "       .quad " __rseq_str(label) "b\n"                                 \
        "       .popsection\n"
 
 #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip)       \
        __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip,                      \
                                (post_commit_ip - start_ip), abort_ip)
 
+/*
+ * Exit points of a rseq critical section consist of all instructions outside
+ * of the critical section where a critical section can either branch to or
+ * reach through the normal course of its execution. The abort IP and the
+ * post-commit IP are already part of the __rseq_cs section and should not be
+ * explicitly defined as additional exit points. Knowing all exit points is
+ * useful to assist debuggers stepping over the critical section.
+ */
+#define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)                          \
+       "       .pushsection __rseq_exit_point_array, \"aw\"\n"                 \
+       "       .quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n"      \
+       "       .popsection\n"
+
 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)                       \
        RSEQ_INJECT_ASM(1)                                                      \
        "       adrp    " RSEQ_ASM_TMP_REG ", " __rseq_str(cs_label) "\n"       \
@@ -105,7 +134,7 @@ do {                                                                                \
 
 #define RSEQ_ASM_DEFINE_ABORT(label, abort_label)                              \
        "       b       222f\n"                                                 \
-       "       .inst   "       __rseq_str(RSEQ_SIG) "\n"                       \
+       "       .inst   "       __rseq_str(RSEQ_SIG_CODE) "\n"                  \
        __rseq_str(label) ":\n"                                                 \
        "       b       %l[" __rseq_str(abort_label) "]\n"                      \
        "222:\n"
@@ -182,6 +211,11 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
+#endif
                RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
                RSEQ_INJECT_ASM(3)
@@ -231,6 +265,11 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
+#endif
                RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
                RSEQ_INJECT_ASM(3)
@@ -282,6 +321,9 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
+#endif
                RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
                RSEQ_INJECT_ASM(3)
@@ -325,6 +367,11 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
+#endif
                RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
                RSEQ_INJECT_ASM(3)
@@ -379,6 +426,11 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
+#endif
                RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
                RSEQ_INJECT_ASM(3)
@@ -433,6 +485,12 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error3])
+#endif
                RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
                RSEQ_INJECT_ASM(3)
@@ -490,6 +548,11 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
+#endif
                RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
                RSEQ_INJECT_ASM(3)
@@ -545,6 +608,11 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
+#endif
                RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
                RSEQ_INJECT_ASM(3)
index 7f48ecf..e989e7c 100644 (file)
@@ -7,7 +7,39 @@
  * (C) Copyright 2016-2018 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  */
 
-#define RSEQ_SIG       0x53053053
+/*
+ * RSEQ_SIG uses the break instruction. The instruction pattern is:
+ *
+ * On MIPS:
+ *     0350000d        break     0x350
+ *
+ * On nanoMIPS:
+ *      00100350        break     0x350
+ *
+ * On microMIPS:
+ *      0000d407        break     0x350
+ *
+ * For nanoMIPS32 and microMIPS, the instruction stream is encoded as 16-bit
+ * halfwords, so the signature halfwords need to be swapped accordingly for
+ * little-endian.
+ */
+#if defined(__nanomips__)
+# ifdef __MIPSEL__
+#  define RSEQ_SIG     0x03500010
+# else
+#  define RSEQ_SIG     0x00100350
+# endif
+#elif defined(__mips_micromips)
+# ifdef __MIPSEL__
+#  define RSEQ_SIG     0xd4070000
+# else
+#  define RSEQ_SIG     0x0000d407
+# endif
+#elif defined(__mips__)
+# define RSEQ_SIG      0x0350000d
+#else
+/* Unknown MIPS architecture. */
+#endif
 
 #define rseq_smp_mb()  __asm__ __volatile__ ("sync" ::: "memory")
 #define rseq_smp_rmb() rseq_smp_mb()
@@ -54,20 +86,38 @@ do {                                                                        \
 # error unsupported _MIPS_SZLONG
 #endif
 
-#define __RSEQ_ASM_DEFINE_TABLE(version, flags,        start_ip, \
+#define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip, \
                                post_commit_offset, abort_ip) \
-               ".pushsection __rseq_table, \"aw\"\n\t" \
+               ".pushsection __rseq_cs, \"aw\"\n\t" \
                ".balign 32\n\t" \
+               __rseq_str(label) ":\n\t"                                       \
                ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
                LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \
                LONG " " U32_U64_PAD(__rseq_str(post_commit_offset)) "\n\t" \
                LONG " " U32_U64_PAD(__rseq_str(abort_ip)) "\n\t" \
+               ".popsection\n\t" \
+               ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \
+               LONG " " U32_U64_PAD(__rseq_str(label) "b") "\n\t" \
                ".popsection\n\t"
 
-#define RSEQ_ASM_DEFINE_TABLE(start_ip, post_commit_ip, abort_ip) \
-       __RSEQ_ASM_DEFINE_TABLE(0x0, 0x0, start_ip, \
+#define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
+       __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip, \
                                (post_commit_ip - start_ip), abort_ip)
 
+/*
+ * Exit points of a rseq critical section consist of all instructions outside
+ * of the critical section where a critical section can either branch to or
+ * reach through the normal course of its execution. The abort IP and the
+ * post-commit IP are already part of the __rseq_cs section and should not be
+ * explicitly defined as additional exit points. Knowing all exit points is
+ * useful to assist debuggers stepping over the critical section.
+ */
+#define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \
+               ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \
+               LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \
+               LONG " " U32_U64_PAD(__rseq_str(exit_ip)) "\n\t" \
+               ".popsection\n\t"
+
 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
                RSEQ_INJECT_ASM(1) \
                LONG_LA " $4, " __rseq_str(cs_label) "\n\t" \
@@ -113,7 +163,12 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -173,7 +228,12 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -237,7 +297,10 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -289,7 +352,12 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -357,7 +425,12 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -426,7 +499,13 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -500,7 +579,12 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                LONG_S " %[src], %[rseq_scratch0]\n\t"
                LONG_S "  %[dst], %[rseq_scratch1]\n\t"
                LONG_S " %[len], %[rseq_scratch2]\n\t"
@@ -616,7 +700,12 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
 
        rseq_workaround_gcc_asm_size_guess();
        __asm__ __volatile__ goto (
-               RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                LONG_S " %[src], %[rseq_scratch0]\n\t"
                LONG_S " %[dst], %[rseq_scratch1]\n\t"
                LONG_S " %[len], %[rseq_scratch2]\n\t"
index 52630c9..76be901 100644 (file)
@@ -6,7 +6,15 @@
  * (C) Copyright 2016-2018 - Boqun Feng <boqun.feng@gmail.com>
  */
 
-#define RSEQ_SIG       0x53053053
+/*
+ * RSEQ_SIG is used with the following trap instruction:
+ *
+ * powerpc-be:    0f e5 00 0b           twui   r5,11
+ * powerpc64-le:  0b 00 e5 0f           twui   r5,11
+ * powerpc64-be:  0f e5 00 0b           twui   r5,11
+ */
+
+#define RSEQ_SIG       0x0fe5000b
 
 #define rseq_smp_mb()          __asm__ __volatile__ ("sync"    ::: "memory", "cc")
 #define rseq_smp_lwsync()      __asm__ __volatile__ ("lwsync"  ::: "memory", "cc")
@@ -33,8 +41,8 @@ do {                                                                  \
 #else /* !RSEQ_SKIP_FASTPATH */
 
 /*
- * The __rseq_table section can be used by debuggers to better handle
- * single-stepping through the restartable critical sections.
+ * The __rseq_cs_ptr_array and __rseq_cs sections can be used by debuggers to
+ * better handle single-stepping through the restartable critical sections.
  */
 
 #ifdef __PPC64__
@@ -46,11 +54,14 @@ do {                                                                        \
 
 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,                         \
                        start_ip, post_commit_offset, abort_ip)                 \
-               ".pushsection __rseq_table, \"aw\"\n\t"                         \
+               ".pushsection __rseq_cs, \"aw\"\n\t"                            \
                ".balign 32\n\t"                                                \
                __rseq_str(label) ":\n\t"                                       \
                ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t"      \
                ".quad " __rseq_str(start_ip) ", " __rseq_str(post_commit_offset) ", " __rseq_str(abort_ip) "\n\t" \
+               ".popsection\n\t"                                               \
+               ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t"                  \
+               ".quad " __rseq_str(label) "b\n\t"                              \
                ".popsection\n\t"
 
 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)                       \
@@ -63,6 +74,19 @@ do {                                                                 \
                "std %%r17, %[" __rseq_str(rseq_cs) "]\n\t"                     \
                __rseq_str(label) ":\n\t"
 
+/*
+ * Exit points of a rseq critical section consist of all instructions outside
+ * of the critical section where a critical section can either branch to or
+ * reach through the normal course of its execution. The abort IP and the
+ * post-commit IP are already part of the __rseq_cs section and should not be
+ * explicitly defined as additional exit points. Knowing all exit points is
+ * useful to assist debuggers stepping over the critical section.
+ */
+#define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)                  \
+               ".pushsection __rseq_exit_point_array, \"aw\"\n\t"      \
+               ".quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n\t" \
+               ".popsection\n\t"
+
 #else /* #ifdef __PPC64__ */
 
 #define STORE_WORD     "stw "
@@ -72,12 +96,29 @@ do {                                                                        \
 
 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,                         \
                        start_ip, post_commit_offset, abort_ip)                 \
-               ".pushsection __rseq_table, \"aw\"\n\t"                         \
+               ".pushsection __rseq_cs, \"aw\"\n\t"                            \
                ".balign 32\n\t"                                                \
                __rseq_str(label) ":\n\t"                                       \
                ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t"      \
                /* 32-bit only supported on BE */                               \
                ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) "\n\t" \
+               ".popsection\n\t"                                       \
+               ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t"          \
+               ".long 0x0, " __rseq_str(label) "b\n\t"                 \
+               ".popsection\n\t"
+
+/*
+ * Exit points of a rseq critical section consist of all instructions outside
+ * of the critical section where a critical section can either branch to or
+ * reach through the normal course of its execution. The abort IP and the
+ * post-commit IP are already part of the __rseq_cs section and should not be
+ * explicitly defined as additional exit points. Knowing all exit points is
+ * useful to assist debuggers stepping over the critical section.
+ */
+#define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)                          \
+               ".pushsection __rseq_exit_point_array, \"aw\"\n\t"              \
+               /* 32-bit only supported on BE */                               \
+               ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) "\n\t" \
                ".popsection\n\t"
 
 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)                       \
@@ -169,6 +210,11 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
                /* cmp cpuid */
@@ -224,6 +270,11 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
                /* cmp cpuid */
@@ -286,6 +337,9 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
                /* cmp cpuid */
@@ -337,6 +391,11 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
                /* cmp cpuid */
@@ -400,6 +459,11 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
                /* cmp cpuid */
@@ -465,6 +529,12 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
                /* cmp cpuid */
@@ -532,6 +602,11 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* setup for mempcy */
                "mr %%r19, %[len]\n\t"
                "mr %%r20, %[src]\n\t"
@@ -601,6 +676,11 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* setup for mempcy */
                "mr %%r19, %[len]\n\t"
                "mr %%r20, %[src]\n\t"
index 0afdf79..8ef94ad 100644 (file)
@@ -44,22 +44,54 @@ do {                                                                        \
 
 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,                 \
                                start_ip, post_commit_offset, abort_ip) \
-               ".pushsection __rseq_table, \"aw\"\n\t"                 \
+               ".pushsection __rseq_cs, \"aw\"\n\t"                    \
                ".balign 32\n\t"                                        \
                __rseq_str(label) ":\n\t"                               \
                ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
                ".quad " __rseq_str(start_ip) ", " __rseq_str(post_commit_offset) ", " __rseq_str(abort_ip) "\n\t" \
+               ".popsection\n\t"                                       \
+               ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t"          \
+               ".quad " __rseq_str(label) "b\n\t"                      \
+               ".popsection\n\t"
+
+/*
+ * Exit points of a rseq critical section consist of all instructions outside
+ * of the critical section where a critical section can either branch to or
+ * reach through the normal course of its execution. The abort IP and the
+ * post-commit IP are already part of the __rseq_cs section and should not be
+ * explicitly defined as additional exit points. Knowing all exit points is
+ * useful to assist debuggers stepping over the critical section.
+ */
+#define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)                  \
+               ".pushsection __rseq_exit_point_array, \"aw\"\n\t"      \
+               ".quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n\t" \
                ".popsection\n\t"
 
 #elif __s390__
 
 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,                 \
                                start_ip, post_commit_offset, abort_ip) \
-               ".pushsection __rseq_table, \"aw\"\n\t"                 \
+               ".pushsection __rseq_cs, \"aw\"\n\t"                    \
                ".balign 32\n\t"                                        \
                __rseq_str(label) ":\n\t"                               \
                ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
                ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) "\n\t" \
+               ".popsection\n\t"                                       \
+               ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t"          \
+               ".long 0x0, " __rseq_str(label) "b\n\t"                 \
+               ".popsection\n\t"
+
+/*
+ * Exit points of a rseq critical section consist of all instructions outside
+ * of the critical section where a critical section can either branch to or
+ * reach through the normal course of its execution. The abort IP and the
+ * post-commit IP are already part of the __rseq_cs section and should not be
+ * explicitly defined as additional exit points. Knowing all exit points is
+ * useful to assist debuggers stepping over the critical section.
+ */
+#define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)                  \
+               ".pushsection __rseq_exit_point_array, \"aw\"\n\t"      \
+               ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) "\n\t" \
                ".popsection\n\t"
 
 #define LONG_L                 "l"
@@ -92,14 +124,14 @@ do {                                                                       \
                ".long " __rseq_str(RSEQ_SIG) "\n\t"                    \
                __rseq_str(label) ":\n\t"                               \
                teardown                                                \
-               "j %l[" __rseq_str(abort_label) "]\n\t"                 \
+               "jg %l[" __rseq_str(abort_label) "]\n\t"                \
                ".popsection\n\t"
 
 #define RSEQ_ASM_DEFINE_CMPFAIL(label, teardown, cmpfail_label)                \
                ".pushsection __rseq_failure, \"ax\"\n\t"               \
                __rseq_str(label) ":\n\t"                               \
                teardown                                                \
-               "j %l[" __rseq_str(cmpfail_label) "]\n\t"               \
+               "jg %l[" __rseq_str(cmpfail_label) "]\n\t"              \
                ".popsection\n\t"
 
 static inline __attribute__((always_inline))
@@ -109,6 +141,11 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -167,6 +204,11 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -227,6 +269,9 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -275,6 +320,11 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -346,6 +396,12 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
                RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
                RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
@@ -414,6 +470,11 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                LONG_S " %[src], %[rseq_scratch0]\n\t"
                LONG_S " %[dst], %[rseq_scratch1]\n\t"
                LONG_S " %[len], %[rseq_scratch2]\n\t"
index 089410a..b2da600 100644 (file)
@@ -7,8 +7,25 @@
 
 #include <stdint.h>
 
+/*
+ * RSEQ_SIG is used with the following reserved undefined instructions, which
+ * trap in user-space:
+ *
+ * x86-32:    0f b9 3d 53 30 05 53      ud1    0x53053053,%edi
+ * x86-64:    0f b9 3d 53 30 05 53      ud1    0x53053053(%rip),%edi
+ */
 #define RSEQ_SIG       0x53053053
 
+/*
+ * Due to a compiler optimization bug in gcc-8 with asm goto and TLS asm input
+ * operands, we cannot use "m" input operands, and rather pass the __rseq_abi
+ * address through a "r" input operand.
+ */
+
+/* Offset of cpu_id and rseq_cs fields in struct rseq. */
+#define RSEQ_CPU_ID_OFFSET     4
+#define RSEQ_CS_OFFSET         8
+
 #ifdef __x86_64__
 
 #define rseq_smp_mb()  \
@@ -37,32 +54,49 @@ do {                                                                        \
 
 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,                 \
                                start_ip, post_commit_offset, abort_ip) \
-               ".pushsection __rseq_table, \"aw\"\n\t"                 \
+               ".pushsection __rseq_cs, \"aw\"\n\t"                    \
                ".balign 32\n\t"                                        \
                __rseq_str(label) ":\n\t"                               \
                ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
                ".quad " __rseq_str(start_ip) ", " __rseq_str(post_commit_offset) ", " __rseq_str(abort_ip) "\n\t" \
+               ".popsection\n\t"                                       \
+               ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t"          \
+               ".quad " __rseq_str(label) "b\n\t"                      \
                ".popsection\n\t"
 
+
 #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
        __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip,              \
                                (post_commit_ip - start_ip), abort_ip)
 
+/*
+ * Exit points of a rseq critical section consist of all instructions outside
+ * of the critical section where a critical section can either branch to or
+ * reach through the normal course of its execution. The abort IP and the
+ * post-commit IP are already part of the __rseq_cs section and should not be
+ * explicitly defined as additional exit points. Knowing all exit points is
+ * useful to assist debuggers stepping over the critical section.
+ */
+#define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)                  \
+               ".pushsection __rseq_exit_point_array, \"aw\"\n\t"      \
+               ".quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n\t" \
+               ".popsection\n\t"
+
 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)               \
                RSEQ_INJECT_ASM(1)                                      \
                "leaq " __rseq_str(cs_label) "(%%rip), %%rax\n\t"       \
-               "movq %%rax, %[" __rseq_str(rseq_cs) "]\n\t"            \
+               "movq %%rax, " __rseq_str(rseq_cs) "\n\t"               \
                __rseq_str(label) ":\n\t"
 
 #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label)             \
                RSEQ_INJECT_ASM(2)                                      \
-               "cmpl %[" __rseq_str(cpu_id) "], %[" __rseq_str(current_cpu_id) "]\n\t" \
+               "cmpl %[" __rseq_str(cpu_id) "], " __rseq_str(current_cpu_id) "\n\t" \
                "jnz " __rseq_str(label) "\n\t"
 
 #define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label)            \
                ".pushsection __rseq_failure, \"ax\"\n\t"               \
-               /* Disassembler-friendly signature: nopl <sig>(%rip). */\
-               ".byte 0x0f, 0x1f, 0x05\n\t"                            \
+               /* Disassembler-friendly signature: ud1 <sig>(%rip),%edi. */ \
+               ".byte 0x0f, 0xb9, 0x3d\n\t"                            \
                ".long " __rseq_str(RSEQ_SIG) "\n\t"                    \
                __rseq_str(label) ":\n\t"                               \
                teardown                                                \
@@ -83,15 +117,20 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
                "cmpq %[v], %[expect]\n\t"
                "jnz %l[cmpfail]\n\t"
                RSEQ_INJECT_ASM(4)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
                "cmpq %[v], %[expect]\n\t"
                "jnz %l[error2]\n\t"
 #endif
@@ -102,8 +141,7 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
                RSEQ_ASM_DEFINE_ABORT(4, "", abort)
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  [v]                   "m" (*v),
                  [expect]              "r" (expect),
                  [newv]                "r" (newv)
@@ -140,16 +178,21 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
                "movq %[v], %%rbx\n\t"
                "cmpq %%rbx, %[expectnot]\n\t"
                "je %l[cmpfail]\n\t"
                RSEQ_INJECT_ASM(4)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
                "movq %[v], %%rbx\n\t"
                "cmpq %%rbx, %[expectnot]\n\t"
                "je %l[error2]\n\t"
@@ -164,8 +207,7 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
                RSEQ_ASM_DEFINE_ABORT(4, "", abort)
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  /* final store input */
                  [v]                   "m" (*v),
                  [expectnot]           "r" (expectnot),
@@ -199,12 +241,15 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
 #endif
                /* final store */
                "addq %[count], %[v]\n\t"
@@ -213,8 +258,7 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
                RSEQ_ASM_DEFINE_ABORT(4, "", abort)
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  /* final store input */
                  [v]                   "m" (*v),
                  [count]               "er" (count)
@@ -244,15 +288,20 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
                "cmpq %[v], %[expect]\n\t"
                "jnz %l[cmpfail]\n\t"
                RSEQ_INJECT_ASM(4)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
                "cmpq %[v], %[expect]\n\t"
                "jnz %l[error2]\n\t"
 #endif
@@ -266,8 +315,7 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
                RSEQ_ASM_DEFINE_ABORT(4, "", abort)
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  /* try store input */
                  [v2]                  "m" (*v2),
                  [newv2]               "r" (newv2),
@@ -314,9 +362,15 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
                "cmpq %[v], %[expect]\n\t"
                "jnz %l[cmpfail]\n\t"
@@ -325,7 +379,7 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
                "jnz %l[cmpfail]\n\t"
                RSEQ_INJECT_ASM(5)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
                "cmpq %[v], %[expect]\n\t"
                "jnz %l[error2]\n\t"
                "cmpq %[v2], %[expect2]\n\t"
@@ -338,8 +392,7 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
                RSEQ_ASM_DEFINE_ABORT(4, "", abort)
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  /* cmp2 input */
                  [v2]                  "m" (*v2),
                  [expect2]             "r" (expect2),
@@ -381,18 +434,23 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                "movq %[src], %[rseq_scratch0]\n\t"
                "movq %[dst], %[rseq_scratch1]\n\t"
                "movq %[len], %[rseq_scratch2]\n\t"
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
                "cmpq %[v], %[expect]\n\t"
                "jnz 5f\n\t"
                RSEQ_INJECT_ASM(4)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f)
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 6f)
                "cmpq %[v], %[expect]\n\t"
                "jnz 7f\n\t"
 #endif
@@ -440,8 +498,7 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
 #endif
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  /* final store input */
                  [v]                   "m" (*v),
                  [expect]              "r" (expect),
@@ -520,31 +577,47 @@ do {                                                                      \
  */
 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,                 \
                                start_ip, post_commit_offset, abort_ip) \
-               ".pushsection __rseq_table, \"aw\"\n\t"                 \
+               ".pushsection __rseq_cs, \"aw\"\n\t"                    \
                ".balign 32\n\t"                                        \
                __rseq_str(label) ":\n\t"                               \
                ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
                ".long " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \
+               ".popsection\n\t"                                       \
+               ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t"          \
+               ".long " __rseq_str(label) "b, 0x0\n\t"                 \
                ".popsection\n\t"
 
 #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
        __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip,              \
                                (post_commit_ip - start_ip), abort_ip)
 
+/*
+ * Exit points of a rseq critical section consist of all instructions outside
+ * of the critical section where a critical section can either branch to or
+ * reach through the normal course of its execution. The abort IP and the
+ * post-commit IP are already part of the __rseq_cs section and should not be
+ * explicitly defined as additional exit points. Knowing all exit points is
+ * useful to assist debuggers stepping over the critical section.
+ */
+#define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)                  \
+               ".pushsection __rseq_exit_point_array, \"aw\"\n\t"      \
+               ".long " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) ", 0x0\n\t" \
+               ".popsection\n\t"
+
 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)               \
                RSEQ_INJECT_ASM(1)                                      \
-               "movl $" __rseq_str(cs_label) ", %[rseq_cs]\n\t"        \
+               "movl $" __rseq_str(cs_label) ", " __rseq_str(rseq_cs) "\n\t"   \
                __rseq_str(label) ":\n\t"
 
 #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label)             \
                RSEQ_INJECT_ASM(2)                                      \
-               "cmpl %[" __rseq_str(cpu_id) "], %[" __rseq_str(current_cpu_id) "]\n\t" \
+               "cmpl %[" __rseq_str(cpu_id) "], " __rseq_str(current_cpu_id) "\n\t" \
                "jnz " __rseq_str(label) "\n\t"
 
 #define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label)            \
                ".pushsection __rseq_failure, \"ax\"\n\t"               \
-               /* Disassembler-friendly signature: nopl <sig>. */      \
-               ".byte 0x0f, 0x1f, 0x05\n\t"                            \
+               /* Disassembler-friendly signature: ud1 <sig>,%edi. */  \
+               ".byte 0x0f, 0xb9, 0x3d\n\t"                            \
                ".long " __rseq_str(RSEQ_SIG) "\n\t"                    \
                __rseq_str(label) ":\n\t"                               \
                teardown                                                \
@@ -565,15 +638,20 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
                "cmpl %[v], %[expect]\n\t"
                "jnz %l[cmpfail]\n\t"
                RSEQ_INJECT_ASM(4)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
                "cmpl %[v], %[expect]\n\t"
                "jnz %l[error2]\n\t"
 #endif
@@ -584,8 +662,7 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
                RSEQ_ASM_DEFINE_ABORT(4, "", abort)
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  [v]                   "m" (*v),
                  [expect]              "r" (expect),
                  [newv]                "r" (newv)
@@ -622,16 +699,21 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
                "movl %[v], %%ebx\n\t"
                "cmpl %%ebx, %[expectnot]\n\t"
                "je %l[cmpfail]\n\t"
                RSEQ_INJECT_ASM(4)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
                "movl %[v], %%ebx\n\t"
                "cmpl %%ebx, %[expectnot]\n\t"
                "je %l[error2]\n\t"
@@ -646,8 +728,7 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
                RSEQ_ASM_DEFINE_ABORT(4, "", abort)
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  /* final store input */
                  [v]                   "m" (*v),
                  [expectnot]           "r" (expectnot),
@@ -681,12 +762,15 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
 #endif
                /* final store */
                "addl %[count], %[v]\n\t"
@@ -695,8 +779,7 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
                RSEQ_ASM_DEFINE_ABORT(4, "", abort)
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  /* final store input */
                  [v]                   "m" (*v),
                  [count]               "ir" (count)
@@ -726,15 +809,20 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
                "cmpl %[v], %[expect]\n\t"
                "jnz %l[cmpfail]\n\t"
                RSEQ_INJECT_ASM(4)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
                "cmpl %[v], %[expect]\n\t"
                "jnz %l[error2]\n\t"
 #endif
@@ -749,8 +837,7 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
                RSEQ_ASM_DEFINE_ABORT(4, "", abort)
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  /* try store input */
                  [v2]                  "m" (*v2),
                  [newv2]               "m" (newv2),
@@ -788,16 +875,21 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
                "movl %[expect], %%eax\n\t"
                "cmpl %[v], %%eax\n\t"
                "jnz %l[cmpfail]\n\t"
                RSEQ_INJECT_ASM(4)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
                "movl %[expect], %%eax\n\t"
                "cmpl %[v], %%eax\n\t"
                "jnz %l[error2]\n\t"
@@ -813,8 +905,7 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
                RSEQ_ASM_DEFINE_ABORT(4, "", abort)
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  /* try store input */
                  [v2]                  "m" (*v2),
                  [newv2]               "r" (newv2),
@@ -853,9 +944,15 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
+#endif
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
                "cmpl %[v], %[expect]\n\t"
                "jnz %l[cmpfail]\n\t"
@@ -864,7 +961,7 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
                "jnz %l[cmpfail]\n\t"
                RSEQ_INJECT_ASM(5)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
                "cmpl %[v], %[expect]\n\t"
                "jnz %l[error2]\n\t"
                "cmpl %[expect2], %[v2]\n\t"
@@ -878,8 +975,7 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
                RSEQ_ASM_DEFINE_ABORT(4, "", abort)
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  /* cmp2 input */
                  [v2]                  "m" (*v2),
                  [expect2]             "r" (expect2),
@@ -922,19 +1018,24 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                "movl %[src], %[rseq_scratch0]\n\t"
                "movl %[dst], %[rseq_scratch1]\n\t"
                "movl %[len], %[rseq_scratch2]\n\t"
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
                "movl %[expect], %%eax\n\t"
                "cmpl %%eax, %[v]\n\t"
                "jnz 5f\n\t"
                RSEQ_INJECT_ASM(4)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f)
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 6f)
                "movl %[expect], %%eax\n\t"
                "cmpl %%eax, %[v]\n\t"
                "jnz 7f\n\t"
@@ -984,8 +1085,7 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
 #endif
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  /* final store input */
                  [v]                   "m" (*v),
                  [expect]              "m" (expect),
@@ -1030,19 +1130,24 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
 
        __asm__ __volatile__ goto (
                RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
+#endif
                "movl %[src], %[rseq_scratch0]\n\t"
                "movl %[dst], %[rseq_scratch1]\n\t"
                "movl %[len], %[rseq_scratch2]\n\t"
                /* Start rseq by storing table entry pointer into rseq_cs. */
-               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
                RSEQ_INJECT_ASM(3)
                "movl %[expect], %%eax\n\t"
                "cmpl %%eax, %[v]\n\t"
                "jnz 5f\n\t"
                RSEQ_INJECT_ASM(4)
 #ifdef RSEQ_COMPARE_TWICE
-               RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f)
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 6f)
                "movl %[expect], %%eax\n\t"
                "cmpl %%eax, %[v]\n\t"
                "jnz 7f\n\t"
@@ -1093,8 +1198,7 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
 #endif
                : /* gcc asm goto does not allow outputs */
                : [cpu_id]              "r" (cpu),
-                 [current_cpu_id]      "m" (__rseq_abi.cpu_id),
-                 [rseq_cs]             "m" (__rseq_abi.rseq_cs),
+                 [rseq_abi]            "r" (&__rseq_abi),
                  /* final store input */
                  [v]                   "m" (*v),
                  [expect]              "m" (expect),
index 4847e97..7159eb7 100644 (file)
 #include <syscall.h>
 #include <assert.h>
 #include <signal.h>
+#include <limits.h>
 
 #include "rseq.h"
 
 #define ARRAY_SIZE(arr)        (sizeof(arr) / sizeof((arr)[0]))
 
-__attribute__((tls_model("initial-exec"))) __thread
-volatile struct rseq __rseq_abi = {
+__thread volatile struct rseq __rseq_abi = {
        .cpu_id = RSEQ_CPU_ID_UNINITIALIZED,
 };
 
-static __attribute__((tls_model("initial-exec"))) __thread
-volatile int refcount;
+/*
+ * Shared with other libraries. This library may take rseq ownership if it is
+ * still 0 when executing the library constructor. Set to 1 by library
+ * constructor when handling rseq. Set to 0 in destructor if handling rseq.
+ */
+int __rseq_handled;
+
+/* Whether this library have ownership of rseq registration. */
+static int rseq_ownership;
+
+static __thread volatile uint32_t __rseq_refcount;
 
 static void signal_off_save(sigset_t *oldset)
 {
@@ -69,8 +78,14 @@ int rseq_register_current_thread(void)
        int rc, ret = 0;
        sigset_t oldset;
 
+       if (!rseq_ownership)
+               return 0;
        signal_off_save(&oldset);
-       if (refcount++)
+       if (__rseq_refcount == UINT_MAX) {
+               ret = -1;
+               goto end;
+       }
+       if (__rseq_refcount++)
                goto end;
        rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), 0, RSEQ_SIG);
        if (!rc) {
@@ -78,9 +93,9 @@ int rseq_register_current_thread(void)
                goto end;
        }
        if (errno != EBUSY)
-               __rseq_abi.cpu_id = -2;
+               __rseq_abi.cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED;
        ret = -1;
-       refcount--;
+       __rseq_refcount--;
 end:
        signal_restore(oldset);
        return ret;
@@ -91,13 +106,20 @@ int rseq_unregister_current_thread(void)
        int rc, ret = 0;
        sigset_t oldset;
 
+       if (!rseq_ownership)
+               return 0;
        signal_off_save(&oldset);
-       if (--refcount)
+       if (!__rseq_refcount) {
+               ret = -1;
+               goto end;
+       }
+       if (--__rseq_refcount)
                goto end;
        rc = sys_rseq(&__rseq_abi, sizeof(struct rseq),
                      RSEQ_FLAG_UNREGISTER, RSEQ_SIG);
        if (!rc)
                goto end;
+       __rseq_refcount = 1;
        ret = -1;
 end:
        signal_restore(oldset);
@@ -115,3 +137,20 @@ int32_t rseq_fallback_current_cpu(void)
        }
        return cpu;
 }
+
+void __attribute__((constructor)) rseq_init(void)
+{
+       /* Check whether rseq is handled by another library. */
+       if (__rseq_handled)
+               return;
+       __rseq_handled = 1;
+       rseq_ownership = 1;
+}
+
+void __attribute__((destructor)) rseq_fini(void)
+{
+       if (!rseq_ownership)
+               return;
+       __rseq_handled = 0;
+       rseq_ownership = 0;
+}
index 6c1126e..d40d60e 100644 (file)
@@ -44,6 +44,7 @@
 #endif
 
 extern __thread volatile struct rseq __rseq_abi;
+extern int __rseq_handled;
 
 #define rseq_likely(x)         __builtin_expect(!!(x), 1)
 #define rseq_unlikely(x)       __builtin_expect(!!(x), 0)
index 228c2ae..ad0f8df 100644 (file)
@@ -109,6 +109,7 @@ int main(void)
        int err;
 
        ksft_print_header();
+       ksft_set_plan(3);
 
        sigemptyset(&act.sa_mask);
        act.sa_flags = SA_ONSTACK | SA_SIGINFO;
index 7f79382..3824b66 100644 (file)
@@ -86,6 +86,7 @@ int main(void)
        int err;
 
        ksft_print_header();
+       ksft_set_plan(3 + 7);
 
        sync_api_supported();
 
index 780ce71..6a970b1 100755 (executable)
@@ -24,19 +24,21 @@ TEST_FILE=$(mktemp)
 
 # This represents
 #
-# TEST_ID:TEST_COUNT:ENABLED
+# TEST_ID:TEST_COUNT:ENABLED:TARGET
 #
 # TEST_ID: is the test id number
 # TEST_COUNT: number of times we should run the test
 # ENABLED: 1 if enabled, 0 otherwise
+# TARGET: test target file required on the test_sysctl module
 #
 # Once these are enabled please leave them as-is. Write your own test,
 # we have tons of space.
-ALL_TESTS="0001:1:1"
-ALL_TESTS="$ALL_TESTS 0002:1:1"
-ALL_TESTS="$ALL_TESTS 0003:1:1"
-ALL_TESTS="$ALL_TESTS 0004:1:1"
-ALL_TESTS="$ALL_TESTS 0005:3:1"
+ALL_TESTS="0001:1:1:int_0001"
+ALL_TESTS="$ALL_TESTS 0002:1:1:string_0001"
+ALL_TESTS="$ALL_TESTS 0003:1:1:int_0002"
+ALL_TESTS="$ALL_TESTS 0004:1:1:uint_0001"
+ALL_TESTS="$ALL_TESTS 0005:3:1:int_0003"
+ALL_TESTS="$ALL_TESTS 0006:50:1:bitmap_0001"
 
 test_modprobe()
 {
@@ -149,6 +151,9 @@ reset_vals()
                string_0001)
                        VAL="(none)"
                        ;;
+               bitmap_0001)
+                       VAL=""
+                       ;;
                *)
                        ;;
        esac
@@ -157,8 +162,10 @@ reset_vals()
 
 set_orig()
 {
-       if [ ! -z $TARGET ]; then
-               echo "${ORIG}" > "${TARGET}"
+       if [ ! -z $TARGET ] && [ ! -z $ORIG ]; then
+               if [ -f ${TARGET} ]; then
+                       echo "${ORIG}" > "${TARGET}"
+               fi
        fi
 }
 
@@ -177,9 +184,25 @@ verify()
        return 0
 }
 
+# proc files get read a page at a time, which can confuse diff,
+# and get you incorrect results on proc files with long data. To use
+# diff against them you must first extract the output to a file, and
+# then compare against that file.
+verify_diff_proc_file()
+{
+       TMP_DUMP_FILE=$(mktemp)
+       cat $1 > $TMP_DUMP_FILE
+
+       if ! diff -w -q $TMP_DUMP_FILE $2; then
+               return 1
+       else
+               return 0
+       fi
+}
+
 verify_diff_w()
 {
-       echo "$TEST_STR" | diff -q -w -u - $1
+       echo "$TEST_STR" | diff -q -w -u - $1 > /dev/null
        return $?
 }
 
@@ -600,9 +623,70 @@ run_stringtests()
        test_rc
 }
 
+target_exists()
+{
+       TARGET="${SYSCTL}/$1"
+       TEST_ID="$2"
+
+       if [ ! -f ${TARGET} ] ; then
+               echo "Target for test $TEST_ID: $TARGET not exist, skipping test ..."
+               return 0
+       fi
+       return 1
+}
+
+run_bitmaptest() {
+       # Total length of bitmaps string to use, a bit under
+       # the maximum input size of the test node
+       LENGTH=$((RANDOM % 65000))
+
+       # First bit to set
+       BIT=$((RANDOM % 1024))
+
+       # String containing our list of bits to set
+       TEST_STR=$BIT
+
+       # build up the string
+       while [ "${#TEST_STR}" -le "$LENGTH" ]; do
+               # Make sure next entry is discontiguous,
+               # skip ahead at least 2
+               BIT=$((BIT + $((2 + RANDOM % 10))))
+
+               # Add new bit to the list
+               TEST_STR="${TEST_STR},${BIT}"
+
+               # Randomly make it a range
+               if [ "$((RANDOM % 2))" -eq "1" ]; then
+                       RANGE_END=$((BIT + $((1 + RANDOM % 10))))
+                       TEST_STR="${TEST_STR}-${RANGE_END}"
+                       BIT=$RANGE_END
+               fi
+       done
+
+       echo -n "Checking bitmap handler... "
+       TEST_FILE=$(mktemp)
+       echo -n "$TEST_STR" > $TEST_FILE
+
+       cat $TEST_FILE > $TARGET 2> /dev/null
+       if [ $? -ne 0 ]; then
+               echo "FAIL" >&2
+               rc=1
+               test_rc
+       fi
+
+       if ! verify_diff_proc_file "$TARGET" "$TEST_FILE"; then
+               echo "FAIL" >&2
+               rc=1
+       else
+               echo "ok"
+               rc=0
+       fi
+       test_rc
+}
+
 sysctl_test_0001()
 {
-       TARGET="${SYSCTL}/int_0001"
+       TARGET="${SYSCTL}/$(get_test_target 0001)"
        reset_vals
        ORIG=$(cat "${TARGET}")
        TEST_STR=$(( $ORIG + 1 ))
@@ -614,7 +698,7 @@ sysctl_test_0001()
 
 sysctl_test_0002()
 {
-       TARGET="${SYSCTL}/string_0001"
+       TARGET="${SYSCTL}/$(get_test_target 0002)"
        reset_vals
        ORIG=$(cat "${TARGET}")
        TEST_STR="Testing sysctl"
@@ -627,7 +711,7 @@ sysctl_test_0002()
 
 sysctl_test_0003()
 {
-       TARGET="${SYSCTL}/int_0002"
+       TARGET="${SYSCTL}/$(get_test_target 0003)"
        reset_vals
        ORIG=$(cat "${TARGET}")
        TEST_STR=$(( $ORIG + 1 ))
@@ -640,7 +724,7 @@ sysctl_test_0003()
 
 sysctl_test_0004()
 {
-       TARGET="${SYSCTL}/uint_0001"
+       TARGET="${SYSCTL}/$(get_test_target 0004)"
        reset_vals
        ORIG=$(cat "${TARGET}")
        TEST_STR=$(( $ORIG + 1 ))
@@ -653,13 +737,21 @@ sysctl_test_0004()
 
 sysctl_test_0005()
 {
-       TARGET="${SYSCTL}/int_0003"
+       TARGET="${SYSCTL}/$(get_test_target 0005)"
        reset_vals
        ORIG=$(cat "${TARGET}")
 
        run_limit_digit_int_array
 }
 
+sysctl_test_0006()
+{
+       TARGET="${SYSCTL}/bitmap_0001"
+       reset_vals
+       ORIG=""
+       run_bitmaptest
+}
+
 list_tests()
 {
        echo "Test ID list:"
@@ -673,10 +765,9 @@ list_tests()
        echo "0003 x $(get_test_count 0003) - tests proc_dointvec()"
        echo "0004 x $(get_test_count 0004) - tests proc_douintvec()"
        echo "0005 x $(get_test_count 0005) - tests proc_douintvec() array"
+       echo "0006 x $(get_test_count 0006) - tests proc_do_large_bitmap()"
 }
 
-test_reqs
-
 usage()
 {
        NUM_TESTS=$(grep -o ' ' <<<"$ALL_TESTS" | grep -c .)
@@ -724,25 +815,35 @@ function get_test_count()
 {
        test_num $1
        TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
-       LAST_TWO=${TEST_DATA#*:*}
-       echo ${LAST_TWO%:*}
+       echo ${TEST_DATA} | awk -F":" '{print $2}'
 }
 
 function get_test_enabled()
 {
        test_num $1
        TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
-       echo ${TEST_DATA#*:*:}
+       echo ${TEST_DATA} | awk -F":" '{print $3}'
+}
+
+function get_test_target()
+{
+       test_num $1
+       TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
+       echo ${TEST_DATA} | awk -F":" '{print $4}'
 }
 
 function run_all_tests()
 {
        for i in $ALL_TESTS ; do
-               TEST_ID=${i%:*:*}
+               TEST_ID=${i%:*:*:*}
                ENABLED=$(get_test_enabled $TEST_ID)
                TEST_COUNT=$(get_test_count $TEST_ID)
+               TEST_TARGET=$(get_test_target $TEST_ID)
+               if target_exists $TEST_TARGET $TEST_ID; then
+                       continue
+               fi
                if [[ $ENABLED -eq "1" ]]; then
-                       test_case $TEST_ID $TEST_COUNT
+                       test_case $TEST_ID $TEST_COUNT $TEST_TARGET
                fi
        done
 }
@@ -775,12 +876,14 @@ function watch_case()
 
 function test_case()
 {
-       NUM_TESTS=$DEFAULT_NUM_TESTS
-       if [ $# -eq 2 ]; then
-               NUM_TESTS=$2
-       fi
+       NUM_TESTS=$2
 
        i=0
+
+       if target_exists $3 $1; then
+               continue
+       fi
+
        while [ $i -lt $NUM_TESTS ]; do
                test_num $1
                watch_log $i ${TEST_NAME}_test_$1 noclear
@@ -803,15 +906,15 @@ function parse_args()
                elif [[ "$1" = "-t" ]]; then
                        shift
                        test_num $1
-                       test_case $1 $(get_test_count $1)
+                       test_case $1 $(get_test_count $1) $(get_test_target $1)
                elif [[ "$1" = "-c" ]]; then
                        shift
                        test_num $1
                        test_num $2
-                       test_case $1 $2
+                       test_case $1 $2 $(get_test_target $1)
                elif [[ "$1" = "-s" ]]; then
                        shift
-                       test_case $1 1
+                       test_case $1 1 $(get_test_target $1)
                elif [[ "$1" = "-l" ]]; then
                        list_tests
                elif [[ "$1" = "-h" || "$1" = "--help" ]]; then
@@ -825,8 +928,8 @@ function parse_args()
 test_reqs
 allow_user_defaults
 check_production_sysctl_writes_strict
-test_modprobe
 load_req_mod
+test_modprobe
 
 trap "test_finish" EXIT
 
index 2d566fb..c9b2633 100644 (file)
@@ -18,7 +18,6 @@
 #define ALIGN(x, a) (((x) + (a) - 1) / (a) * (a))
 #define SIZE_MAX        (~(size_t)0)
 #define KMALLOC_MAX_SIZE SIZE_MAX
-#define BUG_ON(x) assert(x)
 
 typedef pthread_spinlock_t  spinlock_t;
 
index a704d1f..5fb0f16 100644 (file)
@@ -391,7 +391,8 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
        spin_unlock(&kvm->mmu_lock);
 
        ret = kvm_arch_mmu_notifier_invalidate_range(kvm, range->start,
-                                       range->end, range->blockable);
+                                       range->end,
+                                       mmu_notifier_range_blockable(range));
 
        srcu_read_unlock(&kvm->srcu, idx);